Samsung Cloud Platform SingleID Open API를 사용하려면 먼저 해당 시스템이 Applications 로 등록이 되어 있어야 합니다.
등록된 시스템 정보로 JWT Token을 발급받아 Samsung Cloud Platform SingleID Open API 호출시 JWT Token 정보를 HTTP 헤더에 포함하여 전송해야 합니다.
API 호출 방법
HTTP 헤더에 토큰 (JWT Token) 값을 포함하여 호출
접근 Token 헤더명은 Authorization 으로 설정하고, 접근 Token 타입 값은 Bearer 으로 지정 - Bearer 문자열 다음에 JWT Token 값을 설정합니다.
MFA 인증 페이지로 Redirect 된다.
기본적으로는 response token을 post 방식으로 전달하나, get 방식(query)로 전달하려면 request token에 다음 파라미터를 추가해줍니다.
returnMethod: get
Sample
Request
Response
curl -X GET "https://stg2-cloud.singleid.samsung.net/test-tenant/common-api/open/v1.1/mfa/request?jwtTokenRequest=eyJhbGciOiJIUzI1NiJ9.eyJzeXMiOiJ0ZXN0LXN5c3RlbSIsInJlcSI6Ijc2MWVmZDUyLTk3ZDAtNDUxZi05Y2Y5LWNmODY3NDBlN2NhMyIsInVpZCI6Imppbm9uZS5raW0iLCJydG4iOiJodHRwczovL3Rlc3QuY29tL21mYS9yZXNwb25zZSIsIm5iZiI6MTY5ODIzMjA2OCwiZXhwIjoxNjk4MjM5MjY4LCJpYXQiOjE2OTgyMzIwNjh9.cDgKMHIINaHhBiyAd_OIlVvQwmUs0QaXH_RfJ8B_KdY"
페이지 이동
표. Sample
Error Code
Http Response Code
Error Code
Error Message
조치 방안
400
N/A
N/A
토큰 데이터를 확인합니다.
표. Error Code
API Specification - MFA Consumer Reques(Portal Common)
MFA Consumer Home으로 이동할지 여부를 결정합니다. true일 경우 MFA Consumer Home으로 이동합니다.
표. Request Parameters
Response
registerFlag = true 일 때 : MFA Consumer Home으로 Redirect 된다.
registerFlag = false 일 때 : MFA 인증 페이지로 Redirect 된다.
Sample
Request
Response
curl -X POST "https://stg2-cloud.singleid.samsung.net/test-tenant/common-api/open/v1.1/mfa/request?jwtTokenRequest=eyJhbGciOiJIUzI1NiJ9.eyJzeXMiOiJ0ZXN0LXN5c3RlbSIsInJlcSI6Ijc2MWVmZDUyLTk3ZDAtNDUxZi05Y2Y5LWNmODY3NDBlN2NhMyIsInVpZCI6Imppbm9uZS5raW0iLCJydG4iOiJodHRwczovL3Rlc3QuY29tL21mYS9yZXNwb25zZSIsIm5iZiI6MTY5ODIzMjA2OCwiZXhwIjoxNjk4MjM5MjY4LCJpYXQiOjE2OTgyMzIwNjh9.cDgKMHIINaHhBiyAd_OIlVvQwmUs0QaXH_RfJ8B_KdY®isterFlag=true"
페이지 이동
표. Sample
Error Code
Http Response Code
Error Code
Error Message
조치 방안
400
N/A
N/A
토큰 데이터를 확인합니다.
표. Error Code
API Specification - Send Email about Anomaly Detection(Tenant Admin Portal)
curl -X GET "https://stg1-cloud.singleid.samsung.net/test-tenant/common-api/open/v1.1/asis/test-tenant/user/mfa/token/authentication?userName=mkdir.kim&protocol=uma-uaf&sessionDataKey=sessionDataKey111&redirectUrl=redirectUrl1111&errorRedirectUrl=errorRedirectUrl1111¶ms=params111&language=ko"
Microsoft ADFS (ActiveDirectory Federation Service)는 AD계정을 기반으로 웹서비스에 대해 SAML/Oauth기반의 SSO(Single-Sign-On)을 지원하는 서비스입니다.
MS에서는 SSO 연계된 웹서비스에 대해, 3rd Party 솔루션을 활용한 MFA(복합인증)을 지원하는데,이를 위해 개발/설치되어야 하는 것이 ADFS Adapter입니다.
ADFS Adapter의 구현에는 크게 두가지 방식이 있습니다.
Server-to-Server Call 방식
WebClient 방식
이 중 WebClient방식의 경우, MFA서버 ↔ AD(FS) 間 방화벽 개통을 최소화하고, MFA Provider에서 제공하는 CX를 활용하기에 ADFS Adaptor 경량화가 가능한 장점이 있습니다.
참고
SingleID ADFS Adapter는 WebClient 방식으로 개발되었습니다.
주의
본 문서의 도식에서는 nonce 값을 LDAP에 저장 하는 설정을 가정하여 작성되었습니다.
nonce값은 MFA 결과에 대한 검증을 위해 사용되며, LDAP대신 MFA서버에 저장되도록 설정 변경이 가능합니다.
자세한 내용은 ADFS Adaptor 설정관련 매뉴얼을 참고부탁드립니다.
Server-to-Server Call 방식
그림. Server-to-Server Call 방식
WebClient 방식
그림. WebClient 방식
내부 동작
Adapter 내부 전체 흐름도
그림. Adapter 내부 전체 흐름도
Adapter 첫 실행시 흐름도
그림. Adapter 첫 실행시 흐름도
MFA 수행 후의 흐름도 (MFA PASS인 경우)
그림. MFA 수행 후의 흐름도 (MFA PASS인 경우)
MFA 수행 후의 흐름도 (MFA PASS 못한 경우)
그림. MFA 수행 후의 흐름도 (MFA PASS 못한 경우)
시나리오별 동작
그림. 시나리오별 동작
Case #1
Passcode 입력 화면에서 제한 시간을 넘겨서 Timeout 된 경우입니다.
Timeout이 되면 “코드 재전송” 버튼이 활성화되며, 이 버튼을 눌러서 Passcode 재시도 할 수 있습니다.
Case #2
틀린 Passcode를 입력한 경우입니다.
3번까지 Passcode 입력을 시도할 수 있습니다.
Case #3
Passcode 입력을 3번 틀린 경우입니다.
1분간 Passcode 입력을 할 수 없습니다.
Case #4
정상적인 MFA 프로세스입니다.
Case #5
MFA 선택 화면에서 Passcode 입력하지 않고 새로운 브라우저 탭을 추가하고, MFA 선택까지 진행한 경우입니다.
이 후에 최초의 탭에서 MFA를 성공합니다.
이 후에 새로운 탭에서 Timeout 된 경우입니다.
Case #6
MFA 선택 화면에서 Passcode 입력하지 않고 새로운 브라우저 탭을 추가하고, MFA 선택까지 진행한 경우입니다.
이 후에 최초의 탭에서 MFA를 성공합니다.
이 후에 새로운 탭에서 틀린 Passcode를 입력한 경우입니다.
Case #7
MFA 선택 화면에서 Passcode 입력하지 않고 새로운 브라우저 탭을 추가하고, MFA 선택까지 진행한 경우입니다.
이 후에 최초의 탭에서 MFA를 성공합니다.
이 후에 정상 Passcode를 입력한 경우입니다.+
1st tab, 2nd tab 모두 passcode 입력대기 상태에서 1st 인증 후에 2nd 인증시도하면 2nd에서 아무런 반응 없음 (페이지 멈춤)
1st tab passcode 입력대기, 2nd tab MFA 선택대기 상태에서 1st 인증 후에 2nd MFA 종류 선택하면 에러 발생, 어댑터 동작하기 전에 AD에서 에러 메시지 표시함
시나리오별 동작
Adapter 설치
적용 방법
사전 점검
사전 점검
위치
점검 항목
비고
ADFS서버
MFA서버 접속 가능 여부 (그룹망, TCP 80/443)
품질계: ops-sopenapi.iam.samsung.net(42.15.248.26)
운영계: sopenapi.iam.samsung.net(42.15.248.28)
nonce를 LDAP에 저장하도록 설정한 경우, MFA서버 통신 불필요
.NET Framework 4.8 설치 여부
사용자PC
MFA 서버 접속 가능 여부 (인터넷망, TCP 80/443)
품질계: ops-sopenapi.singleid.samsung.net
운영계: sopenapi.singleid.samsung.net
접속 불가 시 다음 3가지 점검 ① 방화벽 점검 ② 프록시 점검 ③ 웹사이트 차단 점검
표. 개인정보 입력항목
Adapter 배포
주의
ADFS서버가 여러 대로 구성되어 있는 경우, 아래 7단계 중 1 ~ 4단계는 모든 서버에 공통적으로 적용해야 합니다.
Adapter 관련 파일을 ADFS 서버에 업로드 시킴
위치 : [drvie]:\ADFSadapter\
ADFSadapter.dll : Adapter 파일
ADFSadatper.ini : 환경 설정 파일
replace_dll.ps1 : 이미 설치된 Adapter를 개선 버전으로 교체 시 사용하는 스크립트 파일
restart_adfs.ps1 : AD FS 서비스 재시작 스크립트 파일
Assembly_netstandard2.0 폴더 : Adapter 적용 전 사전 설치 dll 파일들
해당 폴더에 ADFS 서비스 계정의 전체 권한 부여
C:\ADFSadapter 폴더 우클릭 > 속성 > 보안 > ADFS 서비스 계정 추가 후 모든 권한 허용 선택
※ ADFS 서비스 계정은 services.msc 실행 > ADFS 서비스 실행 계정 "다음 사용자로 로그온" 으로 확인
Registry 추가
Adapter 관련 이벤트를 Windows 이벤트 로그에 찍기 위한 Registry 생성
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog 아래에 키 및 값(2개) 생성
- 생성 키 : MFA_Adapter
- MFA_Adapter에 값 2개 생성
. 이름 : AutoBackupLogFiles
. 종류 : DWORD(32비트) 값(REG_DWORD)
. 데이터 : 0
. 이름 : MaxSize
. 종류 : DWORD(32비트) 값(REG_DWORD)
. 데이터 : 16진수 80000
MFA_Adapter 키 아래에 키 및 값(1개) 생성
- 생성 키 : AdapterDLL
- AdapterDLL에 값 1개 생성
. 이름 : EventMessageFile
. 종류 : 확장 가능한 문자열 값(REG_EXPAND_SZ)
. 데이터 : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\EventLogMessages.dll
Adapter에 필요한 dll 사전 설치
C:\ADFSadapter 내 Assembly_netstandard2.0 폴더는 사전 설치가 필요한 라이브러리 모음 설치 작업은 다음을 참고한다.
ADFS Adapter가 실행될 때 필요한 어셈블리가 로드될 수 있도록 ADFS 서버 내 전역어셈블리캐시에 dll을 설치한다.
**dll 설치**
#사전 작업
C:\ADFSadapter 폴더에 Assembly_netstandard2.0 폴더 압축을 풀어 복사해둔다.
#관리자 권한으로 Powershell 실행 후 수행 위치 이동
PS>cd C:\ADFSadapter
#dll 설치
PS>.\gacutil.exe /il .\Assembly_netstandard2.0\AssemblyList.txt
#dll 확인
PS>.\gacutil.exe /l
설치 필요한 어셈블리 파일들을 Assembly_netstandard2.0 폴더에 저장해두었으며, 서버에 해당 파일을 복사한 후 오프라인 상태에서 설치 가능
Assembly_netstandard2.0 폴더 : Microsoft.IdentityModel.Tokens v7.2, System.IdentityModel.Tokens.Jwt v7.2 어셈블리 설치를 위한 dll 파일 (dependancy 파일 모두 포함)
설치 dll 리스트
셈블리명
설치 버전
패키지 버전
Microsoft.Bcl.AsyncInterfaces
1.0.0.0
1.0.0
Microsoft.IdentityModel.Abstractions
7.2.0.0
7.2.0
Microsoft.IdentityModel.JsonWebTokens
7.2.0.0
7.2.0
Microsoft.IdentityModel.Logging
7.2.0.0
7.2.0
Microsoft.IdentityModel.Tokens
7.2.0.0
7.2.0
System.Buffers
4.0.3.0
4.5.1
System.IdentityModel.Tokens.Jwt
7.2.0.0
7.2.0
System.Memory
4.0.1.1
4.5.3
System.Numerics.Vectors
4.1.4.0
4.5.0
Microsoft.CSharp
4.0.4.0
4.5.0
System.Runtime.CompilerServices.Unsafe
4.0.4.1
4.5.3
System.Security.Cryptography.Cng
4.3.0.0
5.0.0
System.Text.Encodings.Web
4.0.5.1
4.7.2
System.Text.Json
4.0.1.2
4.7.2
System.Threading.Tasks.Extensions
4.2.0.1
4.5.4
표. 설치 dll 리스트
Adapter 배포
nuget 파일을 다운 받아 설치하였으며, nuget 패키지 버전과 서버에 설치되는 버전 표기가 다르니 주의하세요.
.net framework 4.8을 기준으로 dll은 .net standard2.0(.net framework 4.8 지원) 규격으로 사용하세요
#수행 위치 이동
PS>cd C:\ADFSadapter
#dll 등록
PS>./gacutil.exe /if ADFSadapter.dll
#dll 확인
PS>./gacutil.exe /l ADFSadapter
전역 어셈블리 캐시에 다음 어셈블리가 들어 있습니다.
ADFSadapter, Version=1.2.1.0, Culture=neutral, PublicKeyToken=0e0fe476002e81b3, processorArchitecture=MSIL
#ADFS에 인증 공급자로 등록
PS>$typename="ADFSadapter.AuthenticationAdapter, ADFSadapter, Version=1.2.1.0, Culture=neutral, PublicKeyToken=0e0fe476002e81b3, processorArchitecture=MSIL"
PS>Register-AdfsAuthenticationProvider -TypeName $typename -Name "ADFSadapter"
#ADFS에 인증 공급자 확인
PS>Get-AdfsAuthenticationProvider
AdminName : ADFS MFA Adapter
AllowedForPrimaryExtranet : False
AllowedForPrimaryIntranet : False
AllowedForAdditionalAuthentication : True
AuthenticationMethods : {http://schemas.microsoft.com/ws/2012/12/authmethod/otp}
Descriptions : {[1033, ADFS MFA Adapter], [1042, ADFS MFA Adapter]}
DisplayNames : {[1033, ADFS MFA Adapter], [1042, ADFS MFA Adapter]}
Name : ADFSadapter
IdentityClaims : {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn}
IsCustom : True
RequiresIdentity : True
#ADFS 서비스 재시작
PS>net stop adfssrv
PS>net start adfssrv
#수행 위치 이동
PS>cd C:\ADFSadapter
#dll 등록
PS>./gacutil.exe /if ADFSadapter.dll
#dll 확인
PS>./gacutil.exe /l ADFSadapter
전역 어셈블리 캐시에 다음 어셈블리가 들어 있습니다.
ADFSadapter, Version=1.2.1.0, Culture=neutral, PublicKeyToken=0e0fe476002e81b3, processorArchitecture=MSIL
#ADFS 서비스 재시작
PS>net stop adfssrv
PS>net start adfssrv
ADFS의 다단계 인증 방법 설정
AD FS 관리 > 서비스 > 인증 방법 > 다단계 인증 방법 > 편집 클릭 후 생성한 mfa(ADFS MFA Adapter) 선택 후 적용 (복수선택 가능)
신뢰 당사자 트러스트에 mfa 정책 적용
AD FS 관리 > 신뢰 당사자 트러스트 > 적용할 신뢰 당사자 트러스트 선택 > 액세스 제어 정책 편집 > ‘모든 사용자를 허용하고 MFA 요구’ 선택 후 적용
Adapter 업그레이드 및 변경
해당 방법은 기존에 ADFS MFA Adapter 가 등록되어 있는 상태에서 해당 Adapter를 업그레이드/변경할 경우에 수행하는 Adapter 교체 작업입니다.
교체 작업 시 해당 스크립트만 수행하면 Adapter 변경 및 적용이 완료 됩니다.
#수행 위치 이동하여 변경된 Adapter.dll 파일 업로드
PS>cd C:\ADFSadapter
#Adapter 교체 수행
PS>./replace_dll.ps1
확인창 출력 시 예(Y) 혹은 모두 예(A) 클릭
- 예(Y) 혹은 모두 예(A) 선택 : ADFS에서 기존 Adapter 제거 후 교체 작업 진행 (정상 절차)
- 아니요(N) 혹은 모두 아니요(L) 선택 : Adapter 제거 안하고 다음 단계로 수행되어 오류 발생
- 일시 중단(S) 선택: 해당 스크립트 중단
참고
※ 주서버와 보조서버에서 모두 수행.
보조 서버에서는 ADFS에 등록 시 오류 발생하나 dll 설치를 위해서 수행 필요
Adapter 설정
Adapter 환경설정 파일에 대한 설명입니다.
ADFS Adapter 적용하기 전에 반드시 환경설정을 먼저 해야 합니다.
안내
adapter 설치위치 변경 사항
adapter 1.2.0.6부터 C 드라이브 이외의 다른 드라이브에 설치가 가능합니다.
기존 : C:/ADFSadapter 에만 설치
변경 : C to Z 드라이브의 root에 설치
예시: C:/ADFSadapter , D:/ADFSadapter , E:/ADFSadapter , …… , Z:/ADFSadapter
주의사항 : 단 1개의 드라이브에만 설치해야 하며, 만일 여러 개의 드라이브에 설치된 경우 C to Z 스캔하면서 가장 먼저 발견된 디렉토리를 사용함
아래의 예시는, adapter를 C:\ADFSadapter 디렉토리에 설치한 경우입니다.
C 이외의 다른 드라이브에 설치한 경우, 아래의 예시에서 드라이브명(drive letter)만 변경하면 됩니다.
예시: D:\ADFSadapter 에 설치한 경우 ini 경로 → D:\ADFSadapter\ADFSadapter.ini
파일명 및 경로
파일명 → ADFSadapter.ini
전체 경로 → C:\ADFSadapter\ADFSadapter.ini
파일 인코딩 → 반드시 UTF-8 로 저장할 것 (그렇지 않으면 한글이 깨짐)
알아두어야 할 점
값을 표현할때 " 와 ’ 를 사용할 수 있으며 = 좌우에 빈칸을 입력해도 됨
Value 의 앞뒤에 있는 공백은 Trim 처리 됨
아래의 Value는 모두 동일함
예1) MAIN_TITLE=DWP MFA Adapter
예2) MAIN_TITLE = DWP MFA Adapter
예3) MAIN_TITLE = “DWP MFA Adapter”
예4) MAIN_TITLE = " DWP MFA Adapter "
섹션 이름들 중에 뒷부분에 -1033, -1042 가 붙는 것들은 locale 을 의미함
최소한 1033 은 반드시 있어야 합니다.
# ADFS MFA Adapter 환경 설정
# 설치위치 변경 사항
# - v1.2.0.6 이전 : C:\ADFSadapter\ADFSadapter.ini
# - v1.2.0.6 부터 : C 이외의 다른 드라이브에 설치할 수 있음 (adapter 리소스 설치한 위치와 동일)
# 예시: C:\ADFSadapter\ADFSadapter.ini , D:\ADFSadapter\ADFSadapter.ini , E:\ADFSadapter\ADFSadapter.ini
# 주의 : DLL 파일명은 ADFSadapter.dll 이며, 기존의 Nexsign 연계한 MFAadapter.dll과는 다름
# 값을 표현할때 " 와 ' 를 사용할 수 있으며 = 좌우에 빈칸을 입력해도 됩니다
# Value 의 앞뒤에 있는 공백은 Trim 처리 됩니다.
# 아래의 Value는 모두 동일합니다.
# 예1) MAIN_TITLE=ADFS MFA Adapter
# 예2) MAIN_TITLE = ADFS MFA Adapter
# 예3) MAIN_TITLE = "ADFS MFA Adapter"
# 예4) MAIN_TITLE = " ADFS MFA Adapter "
# 섹션 이름들 중에 뒷부분에 -1033, -1042 가 붙는 것들은 locale 을 의미합니다
# 최소한 1033 은 반드시 있어야 합니다
# locale number : 1033 (en-us), 1042 (ko)
# locale section : MFA-1033, MFA-1042, TXT-1033, TXT-1042, MSG-1033, MSG-1042
# LOG_LEVEL (Windows 이벤트 로그에 기록하는 기준)
# 0 : Error
# 1 : Error + Warning
# 2 : Error + Warning + Information + Debug
[MAIN]
MAIN_MFA_TITLE="ADFS MFA Adapter"
MAIN_CLAIM1=http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod
MAIN_CLAIM2=http://schemas.microsoft.com/ws/2012/12/authmethod/otp
# MFA API 정보
# URL 끝부분에 "/" 붙이지 말 것
#MFA_API_URL="https://stg2-cloud.singleid.samsung.net/test/common-api/open/v1.1/mfa/request"
MFA_API_URL="https://stg1-cloud.singleid.samsung.net/test/common-api/open/v1.1/mfa/request"
CONSUMER_KEY="**************************************"
SECRET_KEY="**************************************"
# Donmain vs Consumer Key 리스트
# 도메인별로 Consumer Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 CONSUMER_KEY 값을 비울 것)
# Reqeust Token의 sys 값에 대입
# 형태 : DOMAIN_CONSUMER_KEY_##=domain;consumerKey
# 예시: DOMAIN_CONSUMER_KEY_01=aaa.com;**************************************
# DOMAIN_CONSUMER_KEY_02=bbb.com;**************************************
# (주의) CONSUMER_KEY 값과 리스트 값이 모두 있다면, CONSUMER_KEY 값만 사용함
DOMAIN_CONSUMER_KEY_01=aaa.com;**************************************
DOMAIN_CONSUMER_KEY_02=bbb.com;**************************************
# Donmain vs Secret Key 리스트
# 도메인별로 Secret Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 SECRET_KEY 값을 비울 것)
# 형태 : DOMAIN_SECRET_KEY_##=domain;secretKey
# 예시: DOMAIN_SECRET_KEY_01=aaa.com;**************************************
# DOMAIN_SECRET_KEY_02=bbb.com;**************************************
# (주의) SECRET_KEY 값과 리스트 값이 모두 있다면, SECRET_KEY 값만 사용함
DOMAIN_SECRET_KEY_01=aaa.com;**************************************
DOMAIN_SECRET_KEY_02=bbb.com;**************************************
# LDAP Search 결과에 따른, MFA 진행 여부
# 0 : LDAP Search를 하지 않음 (아래의 LDAP_SERVER, LDAP_USE_IDPW, ... 등의 정보 사용하지 않음. token에는 빈 값 대입)
# 1 : LDAP Search를 시도하지만 실패해도 관계없음 (서버 실패, 정보 없음 등이 발생하여도 MFA 진행함. token에는 빈 값 대입)
# 2 : LDAP Search가 성공 & 사용자 정보가 존재해야 함 (사용자 정보가 존재할 경우에만 진행함. 단, 결과 값이 빈 값이어도 진행함)
USE_LDAP_SEARCH=1
# LDAP 주소와 ID/PW
# LDAP_SERVER는 domain, ipv4, ipv6 등의 3가지 모두 가능하며, 앞부분에 대문자 "LDAP://" 을 붙여야 함 (반드시 대문자)
# 예시: LDAP://adpw5004.hw.dev , LDAP://70.2.180.218 , LDAP://fe80::644b:3c9f:c5ac:ce1c%10
# ID/PW를 사용하려면 LDAP_USE_IDPW 값을 1, 사용하지 않으려면 LDAP_USE_IDPW 값을 0 으로 설정
# SSL/TLS 사용하려면 LDAP_SSLTLS 값을 1, 사용하지 않으려면 LDAP_SSLTLS 값을 0 으로 설정 (단, LDAP_USE_IDPW=1 인 경우에만 해당)
LDAP_SERVER="LDAP://adpw5004.hw.dev"
LDAP_USE_IDPW=1
LDAP_SSLTLS=1
LDAP_ID="isadmin"
LDAP_PW="sds*****"
# DNS Lookup을 하여 LDAP 서버(LDAP_SERVER)의 IP 주소를 확인하고, IP 주소 기반으로 접속 여부
# LDAP_SERVER 값이 IP(ipv4, ipv6)로 설정되어 있어도 DNS Lookup을 수행하며, IP 그대로 리턴됨
# 만약, DNS Lookup을 실패하면, LDAP_SERVER 값 그대로 접속
# 0 : LDAP_SERVER 값 그대로 서버에 접속 (DNS lookup 하지 않음)
# 1 : DNS lookup으로 IP 주소를 확인하여 LDAP 서버에 접속 (DNS lookup 결과 리스트에서 첫번째 IP 사용)
# 2 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP_SERVER 사용)
# 3 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP 접속 안함)
LDAP_DNS_LOOKUP=1
# DNS Lookup 결과가 여러 개일때, 첫번째 IP 주소로 연결이 안되면 그 다음 IP 주소로 시도할지 여부
# 예시: lookup 결과가 4개 : 1차 IP 연결 실패 -> 2차 IP 연결 시도 & 싪패 -> 3차 IP 연결 시도 & 싪패 -> 4차 IP 연결 시도
LDAP_DNS_IF_FAIL_USE_NEXT=1
# DNS Lookup 결과와 비교하는 접속 허용된 LDAP 서버 IP 리스트 (LDAP_DNS_LOOKUP = 2 or 3 인 경우에만 해당)
# LDAP_WHITE_IP_## 형태이며, 01부터 99까지 순차적으로 기록
# DNS Lookup 결과와 리스트를 순차적으로 비교
# IPv4, IPv6 형태로 기록 (동일한 서버의 IPv4, IPv6가 있다면 리스트의 앞순위에 있는 IP가 적용됨)
# DNS Lookup 결과 순서와 White IP 리스트 순서가 다르다면 -> White IP 리스트 순서를 따름
LDAP_WHITE_IP_01="70.2.180.218"
LDAP_WHITE_IP_02="fe80::644b:3c9f:c5ac:ce1c%10"
# 사용자 정보를 암호화할지 여부 (예: mobile, email 등)
# 대상 : USERINFO_## 리스트
# 암호화 여부에 따라 API 서버에 전송하는 token의 claim 이름이 다름
# 0 : 암호화 하지 않음 -> token의 claim 이름이 plainMobile, plainEmail
# 1 : 암호화 -> token의 claim 이름이 mobile, email
USERINFO_ENCRYPT=0
# LDAP Search할 사용자 정보 attribute name과 JWT token에 사용할 claim name (2개 값을 구분하는 delimeter = ";")
# 형태: USERINFO_## = attribute;encryptedClaim;plainClaim
# 예시: LDAP에서 "mail" 속성을 읽어서, JWT에 "email" claim으로 사용된다면 -> "mail;email;plainEmail"
# key 명칭은 "USERINFO_##" 형태로 하고, 시작은 USERINFO_01
# key 갯수 : 0개 ~ 최대 99개 (0개인 경우, ini에 아무것도 적지 않으면 되며, USERINFO_00 이라고 적지 말 것)
# 주의사항) USERINFO_##에서 ## 에 해당되는 숫자는 반드시 01부터 시작하며, 여러 개인 경우 번호가 끊어지지 않아야 함
# USERINFO_01, USERINFO_02, USERINFO_03 : OK (01, 02, 03 정보가 사용됨)
# USERINFO_01, USERINFO_02, USERINFO_05 : 02까지 읽고, 끊어진 번호 이후는 사용하지 않음 (01, 02 정보가 사용됨)
USERINFO_01=mobile;mobile;plainMobile
USERINFO_02=mail;email;plainEmail
# MFA API 서버가 Callback 해줄때, 결과 Parameter에 사용되는 Key 이름
# 예시: https://adpw5004.hw.dev/adfs/ls?client-request-id=xxxxxx&pullStatus=0&jwtTokenResponse=yyyyyy
KEY_NAME_IN_RESPONSE="jwtTokenResponse"
# JWT Token의 exp에 적용될 더하기 값
# 형테 : 일시분초(dhms) 형태의 문자열 -> 1d=86400, 1h=3600, 1m=60 (dhms 가 전혀 없는 단순 숫자는 초로 판단함)
# 예시1 : 1d02h38m27s -> 95907 초
# 예시2 : 12345 -> 12345 초
TOKEN_EXP_TIME=1d
# API 호출할때 구성하는 token에 client claim을 추가할지 여부
# client : SAML인 경우 issuer, OIDC인 경우 client-id
# 0 : token에 client 포함시키지 않음
# 1 : token에 client 포함
TOKEN_CLAIM_CLIENT=0
# MFA nonce(guid, requset-id) 검증 방법
# 0 : 검증 안함
# 1 : adapter가 생성한 guid를 LDAP에 저장/비교하는 방식 (adapter가 검증)
# -> 관련 설정 값 : CACHE_ATTRIBUTE, CACHE_DELIMETER, SKEW_SECONDS, CACHE_LIFE_TIME
# 2 : API 서버가 생성한 requeset-id를 adapter가 받아서 호출 URL에 사용하는 방식 (API 서버가 검증)
# -> 관련 설정 값 : MFA_VERIFY_URL
MFA_VERIFY_TYPE=2
# MFA 결과검증 URL (서버 to 서버 통신) : URL 뒷부분에 API 서버로부터 받은 {request-id}를 덧붙여서 호출함
# adapter는 리턴 200 (OK) 인지 확인하여 MFA 결과 처리
# URL 끝부분에 "/" 붙이지 말 것
MFA_VERIFY_URL="https://stg1-cloud.iam.samsung.net/test/common-api/open/v1.1/mfa/request/status"
# MFA 결과검증할때 사용할 보안 프로토콜
# 선택 가능한 프로토콜 (대소문자 구분 없음) : TLS12, TLS13
# (주의) SSL3, TLS, TLS11 은 사용하지 않음
MFA_VERIFY_SECURE_PROTOCOL="TLS12"
# 사용자의 req guid 값을 저장할 LDAP attribute의 이름
# (주의) LDAP에 write 권한이 있어야 함
CACHE_ATTRIBUTE="otherPager"
# LDAP에 저장하는 req + 시간 정보를 조합할때 사용하는 delimeter -> "req;시간"
CACHE_DELIMETER=";"
# LDAP에 저장된 req의 시간과 JWT 수신시 시간의 차이 허용치 (초단위)
# MFA 선택화면 누를 때가 아니라, AD 로그인 직후의 시간이므로 (MFA 선택화면 보일때 이미 시간이 저장되었음)
# 사용자가 MFA 선택화면 누르고 Passcode 입력할 때까지의 시간이 아님
# 따라서, tight 하게 시간을 설정하면 안되며, 1시간 정도가 적당?? (MFA 선택을 1시간 고민하는 사람이 있나?)
SKEW_SECONDS=3600
# LDAP에 저장된 req의 수명 -> 다음 access시 시간 확인해서 이전의 오래된 것들 삭제
# 형태 : 일시분초(dhms) 형태의 문자열 -> 1d=86400, 1h=3600, 1m=60 (dhms 가 전혀 없는 단순 숫자는 초로 판단함)
# 예시1 : 1d02h38m27s -> 95907 초
# 예시2 : 12345 -> 12345 초
CACHE_LIFE_TIME=1d
# Adapter 기능을 ByPass 할 것인지 여부 (0=정상 사용, 283901=무력화, 그 외 값들=정상 사용)
# MFA 기능 문제로 급하게 adapter 기능의 무력화가 필요한 비상 상황에서 사용
# 평상시에는 절대로 수정하지 말 것 -> 평상시 값은 0
# 주의 : 무력화하려면 반드시 정확한 값을 설정해야 함 (0 이외의 숫자가 해당되는 것이 아니며 정확한 숫자 필요함. noise 우려)
BYPASS_ADAPTER=0
[API]
API_SYSTEMNAME=SingleID
[MSG-1033]
MSG_INTERNAL_ERROR="Internal error occurred. Contact administrator."
[MSG-1042]
MSG_INTERNAL_ERROR="Internal error occurred. Contact administrator."
[MANAGE]
LOG_LEVEL=2
설정 값 설명
값 고정 : 하단 테이블의 “설정 값” 컬럼에 표시된 값을 ADFS 서버에 설치시에도 그대로 사용한다는 의미
영문, 한국어 이외의 언어를 추가하고자 한다면, 2개 Section에 대해서는 추가가 가능함
→ MSG-1033, MSG-1042
SingleID MFA API 주소 tenant에 따라서 달라질 수 있으므로, 정확한 주소 값을 확인해야 함
CONSUMER_KEY
4312a8b9-75c4-7897-89a7-89347f18943e
SingleID 로부터 발급받은 Consumer Key
SECRET_KEY
gQgkyLVO6FR8vJkLtlgBiupsRM/ilgrbEfoKWRnhALd=
SingleID 로부터 발급받은 Secret Key JWT Signautre 검증에 사용 외부 공개 절대 금지
DOMAIN_CONSUMER_KEY_01
4312a8b9-75c4-7897-89a7-89347f18943e
Donmain vs Consumer Key 리스트 도메인별로 Consumer Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 CONSUMER_KEY 값을 비울 것) 형태 : DOMAIN_CONSUMER_KEY_##=domain;consumerKey 예시: DOMAIN_CONSUMER_KEY_01=aaa.com;4312a8b9-75c4-7897-89a7-89347f18943e DOMAIN_CONSUMER_KEY_02=bbb.com;96567780-2b12-23da-637c-9375a6502d5a (주의) CONSUMER_KEY 값과 리스트 값이 모두 있다면, CONSUMER_KEY 값만 사용함
DOMAIN_CONSUMER_KEY_02
96567780-2b12-23da-637c-9375a6502d5a
DOMAIN_CONSUMER_KEY_##
367c89d5-88f7-978a-9739-8ed21748f36b
DOMAIN_SECRET_KEY_01
gQgkyLVO6FR8vJkLtlgBiupsRM/ilgrbEfoKWRnhALd=
Donmain vs Secret Key 리스트 도메인별로 Secret Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 SECRET_KEY 값을 비울 것) 형태 : DOMAIN_SECRET_KEY_##=domain;secretKey 예시: DOMAIN_SECRET_KEY_01=aaa.com;gQgkyLVO6FR8vJkLtlgBiupsRM/ilgrbEfoKWRnhALd= DOMAIN_SECRET_KEY_02=bbb.com;kgkWRnLygQhsRgrLVbtKlO6FiLdABupEgoMR8v/ilfJ= (주의) SECRET_KEY 값과 리스트 값이 모두 있다면, SECRET_KEY 값만 사용함
DOMAIN_SECRET_KEY_02
kgkWRnLygQhsRgrLVbtKlO6FiLdABupEgoMR8v/ilfJ=
DOMAIN_SECRET_KEY_##
dABupkRnLygQhsrLgWVRbt8vRgkLilLKlO1FioMgfJE=
USE_LDAP_SEARCH
0 or 1 or 2
LDAP Search 결과에 따른, MFA 진행 여부 0 : LDAP Search를 하지 않음 (아래의 LDAP_SERVER, LDAP_USE_IDPW, … 등의 정보 사용하지 않음. token에는 빈 값 대입) 1 : LDAP Search를 시도하지만 실패해도 관계없음 (서버 실패, 정보 없음 등이 발생하여도 MFA 진행함. token에는 빈 값 대입) 2 : LDAP Search가 성공 & 사용자 정보가 존재해야 함 (사용자 정보가 존재할 경우에만 진행함. 단, 결과 값이 빈 값이어도 진행함)
LDAP_SERVER
LDAP://adpw5004.hw.dev
AD 사용자 정보를 Query 할 수 있는 LDAP 주소 domain, ipv4, ipv6 등의 3가지 모두 가능하며, 앞부분에 “LDAP://” 을 붙여야 함
LDAP_USE_IDPW
0 or 1
LDAP 접속시 id/pw를 사용하는지 여부 adapter는 시스템 권한으로 동작하므로 id/pw 필요없이 LDAP 접속이 되는 것이 일반적이나, 그렇지 않은 경우도 존재함 id/pw 사용하지 않고 접속하도록 설정한 상태에서 이벤트 로그에 AD 접속 에러가 있다면, id/pw를 사용하여 접속하도록 설정 필요 이 값을 1로 설정하면, LDAP_ID, LDAP_PW 값을 반드시 설정하여야 함
LDAP_SSLTLS
0 or 1
LDAP 연결시 SSL/TLS를 사용할지 여부 일반적으로 사용하도록 설정
LDAP_ID
LDAP 접속 id
LDAP 접속 id (LDAP_USE_IDPW=1 인 경우)
LDAP_PW
LDAP 접속 pw
LDAP 접속 pw (LDAP_USE_IDPW=1 인 경우)
LDAP_DNS_LOOKUP
0 or 1 or 2 or 3
DNS Lookup을 하여 LDAP 서버(LDAP_SERVER)의 IP 주소를 확인하고, IP 주소 기반으로 접속 여부 0 : LDAP_SERVER 값 그대로 서버에 접속 (DNS lookup 하지 않음) 1 : DNS lookup으로 IP 주소를 확인하여 LDAP 서버에 접속 (DNS lookup 결과 리스트에서 첫번째 IP 사용) 2 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP_SERVER 사용) 3 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP 접속 안함)
LDAP_DNS_IF_FAIL_USE_NEXT
0 or 1
DNS Lookup 결과가 여러 개일때, 첫번째 IP 주소로 연결이 안되면 그 다음 IP 주소로 시도할지 여부 예시: lookup 결과가 4개 : 1차 IP 연결 실패 -> 2차 IP 연결 시도 & 실패 -> 3차 IP 연결 시도 & 실패 -> 4차 IP 연결 시도
LDAP_WHITE_IP_01
70.2.180.218
DNS Lookup 결과와 비교하는 접속 허용된 LDAP 서버 IP 리스트 (LDAP_DNS_LOOKUP = 2 or 3 인 경우에만 해당) LDAP_WHITE_IP_## 형태이며, 01부터 99까지 순차적으로 기록 DNS Lookup 결과와 리스트를 순차적으로 비교 IPv4, IPv6 형태로 기록 (동일한 서버의 IPv4, IPv6가 있다면 리스트의 앞순위에 있는 IP가 적용됨) DNS Lookup 결과 순서와 White IP 리스트 순서가 다르다면 → White IP 리스트 순서를 따름
LDAP_WHITE_IP_02
fe80::644b:3c9f:c5ac:ce1c%10
LDAP_WHITE_IP_##
A. : 01 ~ 99 White IP 주소 (IPv4 or IPv6)
USERINFO_ENCRYPT
0 or 1
사용자 정보를 암호화할지 여부 (예: mobile, email 등) 대상 : USERINFO_## 리스트 암호화 여부에 따라 API 서버에 전송하는 token의 claim 이름이 다름 0 : 암호화 하지 않음 -> token의 claim 이름이 plainMobile, plainEmail 1 : 암호화 -> token의 claim 이름이 mobile, email
USERINFO_01
mobile;mobile;plainMobile
O
LDAP Search할 사용자 정보 attribute name과 JWT token에 사용할 claim name (3개 값을 구분하는 delimeter = “;”) 형태: USERINFO_## = attribute;encryptedClaim;plainClaim 예시: LDAP에서 “mail” 속성을 읽어서, JWT에 암호화된 값은 “email” claim으로 , 평문 값은 “plainEmail” claim으로 사용된다면 → “mail;email;plainEmail”
JWT Token의 exp에 적용될 더하기 값 일시분초(dhms) 형태의 문자열 1d=86400, 1h=3600, 1m=60 dhms 가 전혀 없는 단순 숫자는 초로 판단함 예시1 : 1d02h38m27s → 95907 초 예시2 : 12345 → 12345 초
TOKEN_CLAIM_CLIENT
0 or 1
API 호출할때 구성하는 token에 client claim을 추가할지 여부 client : SAML인 경우 issuer, OIDC인 경우 client-id 0 : token에 client 포함시키지 않음 1 : token에 client 포함
MFA_VERIFY_TYPE
0 or 1 or 2
MFA nonce(guid, requset-id) 검증 방법 0 : 검증 안함 1 : adapter가 생성한 guid를 LDAP에 저장/비교하는 방식 (adapter가 검증) → 관련 설정 값 : CACHE_ATTRIBUTE, CACHE_DELIMETER, SKEW_SECONDS, CACHE_LIFE_TIME 2 : API 서버가 생성한 requeset-id를 adapter가 받아서 호출 URL에 사용하는 방식 (API 서버가 검증) → 관련 설정 값 : MFA_VERIFY_URL
MFA 결과검증 URL (서버 to 서버 통신) : URL 뒷부분에 API 서버로부터 받은 {request-id}를 덧붙여서 호출함 → adapter는 리턴 200 (OK) 인지 확인하여 MFA 결과 처리 URL 끝부분에 “/” 붙이지 말 것
MFA_VERIFY_SECURE_PROTOCOL
TLS12 or TLS13
MFA 결과검증할때 사용할 보안 프로토콜 선택 가능한 프로토콜 (대소문자 구분 없음) : TLS12, TLS13 (주의) SSL3, TLS, TLS11 은 사용하지 않음
CACHE_ATTRIBUTE
otherPager
O
사용자의 req guid 값을 저장할 LDAP attribute의 이름
CACHE_DELIMETER
“;”
LDAP에 저장하는 req + 시간 정보를 조합할때 사용하는 delimeter -> “req;시간”
SKEW_SECONDS
3600
LDAP에 저장된 req의 시간과 JWT 수신시 시간의 차이 허용치 (초단위) MFA 선택화면 누를 때가 아니라, AD 로그인 직후의 시간이므로 (MFA 선택화면 보일때 이미 시간이 저장되었음) 사용자가 MFA 선택화면 누르고 Passcode 입력할 때까지의 시간이 아님 따라서, tight 하게 시간을 설정하면 안되며, 1시간 정도가 적당?? (MFA 선택을 1시간 고민하는 사람이 있나?)
CACHE_LIFE_TIME
1d
LDAP에 저장된 req의 수명 -> 다음 access시 시간 확인해서 이전의 오래된 것들 삭제 일시분초(dhms) 형태의 문자열 1d=86400, 1h=3600, 1m=60 (dhms 가 전혀 없는 단순 숫자는 초로 판단함)
BYPASS_ADAPTER
0 or 283901
Adapter 기능을 ByPass 할 것인지 여부 (0=정상 사용, 283901=무력화, 그 외 값들=정상 사용) MFA 기능 문제로 급하게 adapter 기능의 무력화가 필요한 비상 상황에서 사용 평상시에는 절대로 수정하지 말 것 -> 평상시 값은 0 주의 : 무력화하려면 반드시 정확한 값을 설정해야 함 (0 이외의 숫자가 해당되는 것이 아니며 정확한 숫자 필요함. noise 우려)
API
API_SYSTEMNAME
SingleID
O
(MFA 기능에 영향 없음)
MSG-1033
MSG_INTERNAL_ERROR
“Internal error occurred. Contact administrator.”
인증중단, 오류발생 등으로 진행을 멈출때 사용자에게 보여주는 메시지 (영문)
MSG-1042
MSG_INTERNAL_ERROR
“Internal error occurred. Contact administrator.”
인증중단, 오류발생 등으로 진행을 멈출때 사용자에게 보여주는 메시지 (한글) 한글 입력하면 에러 발생하니, 영문으로 입력할 것
MANAGE
LOG_LEVEL
0 또는 1 또는 2
윈도우 이벤트 로그에 기록하는 기준 0 = 에러만 기록 1 = 에러 + 경고만 기록 2 = 에러 + 경고 + 안내 등 모두 기록
표. 설정값 설명
INI 설정 방법
LDAP Search 관련
LDAP 서버의 hostName으로 DNS Lookup 사용하고자 할 때
여러개의 DNS Lookup 결과 중에서 첫번째 주소만 사용하고자 할 때
여러개의 DNS Lookup 결과를 모두 순차적으로 접속 시도하고자 할 때
LDAP 서버 접속시 id/pw를 사용하고자 할 때
허용된 LDAP 주소만 접속하고자 할 때 (White IP list)
LDAP에서 조회할 사용자 attribute 설정
API 연결 관련
API 서버에 전송할 token에 포함되는 사용자 정보의 암호화 여부
MFA 무결성 검증 방법 : 어댑터가 검증
MFA 무결성 검증 방법 : API 서버가 검증
기타
절대로 변경하면 안되는 옵션
SingleID 운영부서에게서 발급받아서 설정해야 하는 옵션
설치 환경에 맞게 설정해야 하는 옵션
주의
본 페이지에서 사용된 consumer key, secret key는 sample data입니다. (fake value)
MFA API 서버에 전송할 Request Token에 포함시킬 사용자 정보 claim입니다.
ini에 설정한 리스트 갯수만큼 LDAP에서 조회하고, 결과를 token에 포함시켜서 MFA API 서버에 전송합니다.
설정 규칙은 아래 페이지의 테이블에서 “USERINFO_##” 설명을 참고하시기 바랍니다.
본 페이지에서 사용된 consumer key, secret key는 sample data입니다. (fake value)
USERINFO_ENCRYPT
USERINFO_ENCRYPT=0
어댑터가 MFA API 서버에 전송하는 token에 포함되는 사용자 정보가 암호화인지 평문인지 여부를 설정합니다. (예를 들면, mobile, email)
어댑터 버전 v1.2.0.8 (‘24년 4월) 현재, AES/GCM/NoPadding을 사용할 수 없으므로 평문으로 설정합니다.
즉, USERINFO_ENCRYPT=0 으로 고정입니다.
후일, 어댑터가 AES/GCM/NoPadding을 지원할 수 있으면, 설정을 변경할 수 있습니다.
USE_LDAP_SEARCH
USE_LDAP_SEARCH=0
LDAP_SERVER=“LDAP://adpw5004.hw.dev”
USE_LDAP_SEARCH가 0 이므로, LDAP_SERVER 값은 사용되지 않습니다.
즉, USE_LDAP_SEARCH가 0 이면, LDAP_SERVER를 빈 값으로 하거나 삭제해도 됩니다.
USE_LDAP_SEARCH=1
LDAP 검색이 실패한다면?
사용자 정보를 빈 값 처리하여 다음 단계로 진행합니다.
실패의 원인이 서버 연결 실패이든 정보 없음이든 관계없습니다.
USE_LDAP_SEARCH=2
LDAP 검색이 실패한다면?
사용자에게 에러를 표시하며 진행을 중지합니다.
서버 로그에는 아래와 같이 기록됩니다. (또는 유사한 내용)
“LDAP에서 사용자 정보를 가져올 수 없습니다.”
이 옵션은 매우 신중하게 사용해야 하며, 가급적 USE_LDAP_SEARCH=1 로 설정하시기 바랍니다.
사용자 정보가 없는 것에 대한 처리는 MFA API 측에 맡기는 것이 바람직할 것입니다.
어댑터는 이러한 상황에 대한 사용자 안내처리 및 기능이 미흡할 수 밖에 없기 때문입니다.
어댑터는 DNS lookup 결과를 메모리에 리스트 형태로 기억해둡니다. (순서가 있는 리스트) → LDAP 주소 리스트
LDAP 서버 이중화이고 각각의 IP가 아래와 같다고 가정합니다. (DNS에서 lookup이 되는 IP)
IP#1 : 10.10.10.10
IP#2 : 10.10.10.20
DNS lookup 결과는 IPv4, IPv6 모두 해당되므로, 아래처럼 결과가 나옵니다. (아래는 sample이며, 실제와 다름)
IP#1 = fe80::644b:3c9f:c5ac:ce1c%10
IP#2 = fe80::f03d:b045:8dc3:f5ed%3
IP#3 = 10.10.10.10
IP#4 = 10.10.10.20
이 상태에서 다음의 Case들을 생각해볼 수 있습니다.
Case 1) DNS Lookup 실패했다면
LDAP 주소 리스트의 갯수는 1개이며, LDAP_SERVER 값을 그대로 대입됩니다.
즉, LDAP 주소 리스트의 1번째 값 = “LDAP://adpw5004.hw.dev”
Case 2) DNS Lookup 성공하고, White IP 리스트 설정 값이 있다면 (LDAP_WHITE_IP_##=“x.x.x.x”)
White IP 리스트의 순서대로 LDAP 주소 리스트가 만들어집니다.
위의 sample의 경우, LDAP 주소 리스트의 값은 아래와 같습니다.
1번째 값 = 10.10.10.10
2번째 White IP 10.10.10.30 은 DNS Lookup 결과에 없기 때문에 LDAP 주소 리스트에 반영하지 않습니다.
Case 3) DNS Lookup 성공하고, White IP 리스트 설정 값이 없다면 (LDAP_WHITE_IP_##=”" 또는 LDAP_WHITE_IP_## 없음)
DNS Lookup 결과를 LDAP 주소 리스트에 반영합니다.
위의 sample의 경우, LDAP 주소 리스트의 값은 아래와 같습니다.
1번째 값 = fe80::644b:3c9f:c5ac:ce1c%10
2번째 값 = fe80::f03d:b045:8dc3:f5ed%3
3번째 값 = 10.10.10.10
4번째 값 = 10.10.10.20
LDAP_DNS_IF_FAIL_USE_NEXT
LDAP_DNS_IF_FAIL_USE_NEXT=0
LDAP 주소 리스트가 아래와 같다고 가정합니다.
1번째 값 = 10.10.10.10
2번째 값 = 10.10.10.20
1번째 주소 10.10.10.10 으로 접속시도 후 실패하면 더 이상 진행하지 않습니다.
LDAP 검색 결과(사용자 정보)는 빈 값으로 설정합니다.
LDAP_DNS_IF_FAIL_USE_NEXT=1
LDAP 주소 리스트가 아래와 같다고 가정합니다.
1번째 값 = 10.10.10.10
2번째 값 = 10.10.10.20
1번째 주소 10.10.10.10 으로 접속시도 후 실패하면 2번째 주소로 접속시도 합니다.
2번째 접속까지 실패하면, LDAP 검색 결과(사용자 정보)는 빈 값으로 설정합니다.
LDAP_USE_IDPW
LDAP_USE_IDPW=0
LDAP_ID="******"
LDAP_PW="******"
LDAP_USE_IDPW가 0 이면, LDAP_ID, LDAP_PW 값은 사용되지 않습니다.
즉, LDAP_USE_IDPW가 0 이면, LDAP_ID, LDAP_PW를 빈 값으로 하거나 삭제해도 됩니다.
LDAP_USE_IDPW=1
LDAP_ID=""
LDAP_PW=""
LDAP_USE_IDPW가 1 이면, LDAP_ID, LDAP_PW 값이 반드시 필요합니다.
따라서, 위의 sample처럼 LDAP_ID, LDAP_PW 값을 비워두거나 삭제하면, LDAP 서버에 접속이 되지 않습니다.
LDAP_USE_IDPW=1
LDAP_ID="******"
LDAP_PW="******"
LDAP 접속에 id/pw를 사용한다는 의미인데, 접속이 실패한다면 id/pw가 정확한지 확인해 봅니다.
INI 파일은 plain text 이므로, id/pw가 노출될 우려가 있습니다.
따라서, 가급적 id/pw 사용하지 않아도 LDAP 접속이 되도록 서버 환경 구성이 필요합니다.
MFA_VERIFY_TYPE
MFA_VERIFY_TYPE=0
어댑터 관점에서의 MFA 결과 검증이란,
사용자의 MFA 수행은 MFA API를 통해서 하는 것인데, 그 결과를 어댑터가 재확인하는 것을 의미합니다.
MFA_VERIFY_TYPE 값이 0 이면, MFA 결과 검증을 안한다는 의미입니다.
정상적인 운영상태에서는 0 으로 설정하지 않습니다.
ADFSadapter.ini 설정에서 LOG_LEVEL 값을 조정하면, 에러, 경고, 일반로그를 선택적으로 기록할 수 있습니다.
ADFSadapter.ini 에서 LOG_LEVEL 설정
값 설정
기록하는 로그
LOG_LEVEL=0
에러 기록
LOG_LEVEL=1
에러, 경고 기록
LOG_LEVEL=2
에러, 경고, 일반 메시지 모두 기록
윈도우 이벤트 로그 위치
컴퓨터 관리(로컬) > 시스템 도구 > 이벤트 뷰어 > 응용 프로그램 및 서비스 로그 > MFA_Adapter
계정별 로그의 시작에는 MFA 버전과 계정명이 표시되어 있음 → 로그 분석/추적에 참고
운영시에는, “오류” 또는 “경고” 로 표시된 부분을 집중적으로 모니터링
윈도우 이벤트 로그 설명 및 조치방법
[#0000] Success
Err.Success
에러가 아니고, 단순한 로그입니다.
불필요한 로그이며, 이 로그가 보인다면 개발자에게 해당 로그 삭제하라고 하시면 됩니다.
[#0001] Invalid Arguments
Err.InvalidArguments
에러 : adapter 프로그램 내부의 함수 호출할 때, 함수 인자(argument) 누락이 있다는 뜻입니다.
조치 : 심각한 에러이며, 개발자에게 즉시 전달하여 신속히 조치되도록 합니다.
참고
별다른 증상없이 adapter가 동작할 수도 있으나, 심각한 에러 잠재성이 있으므로 방치하면 안됩니다.
[#1000] identityClaim 에서 계정정보(account)를 추출할 수 없습니다.
Err.IdentityClaimHasNoAccount
에러 : adapter 실행 초기에 AD 서버로부터 현재 사용자의 정보를 받는데, account 정보를 찾을 수 없습니다.
조치 : AD 서버 상태를 확인해봅니다.
참고
LDAP에서 Query 하는 것이 아니라, ADFS 내부적으로 처리되는 정보 흐름으로서, 이 상황이 발생하면 adapter가 정상 동작할 수 없는 환경이라고 보면 됩니다.
[#1001] INI 파일을 load 할 수 없습니다.
Err.FailToLoadIni
에러 : 서버에서 MFA 환경설정 INI 파일을 읽을 수 없습니다.
조치 : 서버에 다음의 경로에 파일이 있는지 확인
C:\ ADFSadapter \ ADFSadapter.ini
참고
만일, 파일이 있다면, 파일 속성 또는 권한 확인합니다.
[#1002] HTML 파일들을 load 할 수 없습니다.
Err.FailToLoadHtml
에러 : 서버에서 HTML 파일을 읽을 수 없습니다.
조치 : 서버에 다음의 경로에 파일이 있는지 확인합니다.
C:\ ADFSadapter \ Html_*.txt
참고
만일, 파일이 있다면, 파일 속성 또는 권한 확인합니다. 1개라도 없으면 에러 발생힙니다. 어떤 것이 누락되었는지는 서버 이벤트 로그에서 알 수 있습니다.
[#1003] LDAP에서 사용자 정보를 가져올 수 없습니다.
Err.FailToLdapSearch
에러 : LDAP 서버에 Query를 헀으나, AD 사용자 정보를 가져오지 못했습니다.
조치 : AD 서버 상태를 확인해봅니다.
참고
Token 구성에 mobile, email 정보가 필요한데, 이 정보들을 가져올때 실패한 것입니다. 사용자 정보가 존재한다면, mobile, email이 빈 값이어도 에러로 처리하지 않습니다. 그래서, 본 에러가 발생한 것은 LDAP Query 자체가 안된다고 보면 됩니다.
[#1004] BeginAuthentication 함수의 request에 URL 정보가 없습니다.
Err.NoURLInRequest
에러 : Adapter 실행 초기에 실행되는 BeginAuthentication 함수의 인자 request에 URL 정보가 없습니다.
조치 : SingleID MFA API 서버가 정상적으로 response를 보내는지 확인합니다.
참고
URL 정보가 없으면, SingleID MFA API 서버가 GET 방식으로 전송한 response를 사용할 수 없습니다.
[#1005] JWT token 생성을 할 수 없습니다.
Err.FailToMakeJwtToken
에러 : GenerateRequestToken 함수가 token 생성에 실패했습니다.
조치 : 정확한 원인은 서버 이벤트 로그에서 확인 가능하며, 개발자에게 원인 분석을 요청합니다.
[#1006] ADFSadapter 디렉토리 또는 INI 파일을 찾을 수 없습니다. C to Z 드라이브 중의 한 곳에 [drive]:/ADFSadapter/ADFSadapter.ini 파일이 존재해야 합니다.
Err.CannotFindDirOrIni
에러 : adapter 버전 1.2.0.6 부터 adapter 설치 위치가 C 드라이브 고정이 아닌 C to Z 드라이브 중의 한 곳에 설치할 수 있으며, adapter는 C to Z 드라이브 스캔을 통해서 설치된 위치를 알아냅니다. [drive]:/ADFSadapter/ADFSadapter.ini 파일이 존재해야 합니다.
조치 : 서버에 adapter 설치가 제대로 되었는지, 디렉토리명과 파일명이 정확한지 확인합니다. 드라이브 억세스가 막혀있는지 확인합니다.
[#2000] TryEndAuthentication()에 계정정보(account)가 없습니다.
Err.TryEndHasNoAccount
에러 : TryEndAuthentication 단계로 넘어왔으나, 계정 정보를 알 수 없습니다. (adpater 자체 에러)
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#2001] Step 정보가 없습니다.
Err.NoStepInfo
에러 : MFA 진행 단계(step) 정보가 없습니다. (adpater 자체 에러)
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#2002] 잘못된 Step 정보입니다.
Err.InvalidStepInfo
에러 : MFA 진행 단계(step) 정보가 잘 못 되었습니다. (adpater 자체 에러)
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#3000] HTML 문자열을 가져옵니다.
Err.SucceedInGetHtml
에러가 아니고, 단순한 로그입니다. 서버의 Html_.txt 파일을 읽은 내용을 보여줍니다. Html_.txt 파일 내용 수정 후에 adpater가 파일 내용을 제대로 읽었는지 확인할 때 도움이 됩니다.
[#3001] HTML을 가져올 수 없습니다.
Err.FailToGetHtml
에러 : 서버의 Html_*.txt 파일을 읽지 못한 것입니다.
조치 : 파일이 존재하는지, Read 권한이 있는지, Lock 걸려있는지 등을 확인해봅니다.
[#4000] Html 파일이 존재하지 않습니다.
Err.HtmlFileNotFound
에러 : 서버의 Html_*.txt 파일을 읽지 못한 것입니다.
조치 : 파일이 존재하는지, 확인해봅니다.
[#4001] Html 파일이 존재하나, 파일 내용이 없습니다.
Err.HtmlFileIsEmpty
에러 : 서버의 Html_*.txt 파일을 읽지 못한 것입니다.
조치 : 파일 Read 권한이 있는지, Lock 걸려있는지 등을 확인해봅니다.
[#4002] HtmlPrefix 리스트에 없는 step 입니다.
Err.StepNotInHtmlPrefixList
에러 : adapter 내부에는 처리 step 별로 정의해 둔 keyword 리스트가 있는데, 그 리스트에 없는 keyword가 발견되었다는 뜻입니다.
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#4003] HtmlPrefix 리스트에서 prefix 값이 비어 있습니다.
Err.EmptyPrefixInHtmlPrefixList
에러 : adapter 내부에는 처리 step 별로 정의해 둔 keyword 리스트가 있는데, 그 리스트에 아무런 내용이 없다는 뜻입니다.
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#5000] ini 파일을 읽을 수 없습니다.
Err.FailToReadIniFile
에러 : INI 파일을 읽을 수 없습니다.
조치 : 서버에 다음의 경로에 파일이 있는지 확인
C:\ ADFSadapter \ ADFSadapter.ini
참고
만일, 파일이 있다면, 파일 속성 또는 권한 확인합니다.
[#5001] 시스템명칭(API_SYSTEMNAME)이 ini 에 없습니다.
Err.NoSystemNameInIni
에러 : INI 파일에 "API_SYSTEMNAME" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5002] claim1(MAIN_CLAIM1)이 ini 에 없습니다.
Err.NoClaim1InIni
에러 : INI 파일에 "MAIN_CLAIM1" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5003] claim2(MAIN_CLAIM2)가 ini 에 없습니다.
Err.NoClaim2InIni
에러 : INI 파일에 "MAIN_CLAIM2" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5004] ini 파일이 존재하지 않습니다.
Err.IniFileNotFound
에러 : 서버에서 MFA 환경설정 INI 파일을 찾을 수 없습니다.
조치 : 서버에 다음의 경로에 파일이 있는지 확인
C:\ ADFSadapter \ ADFSadapter.ini
[#5005] ini 리스트에 AddToList() 실패했습니다.
Err.FailToAddIniList
에러 : adapter 내부 에러입니다.
조치 : 개발자에게 신속히 상황 전달 및 원인 분석을 요청합니다.
참고
이러한 경우는 절대 발생할 수 없으며, 발생해서도 안됩니다.
[#5006] ini 파일에서 읽어온 key, value가 아무것도 없습니다.
Err.NoKeyValueInIni
에러 : INI 파일을 읽었으나, key, value 조합으로 설정된 것이 전혀 없습니다.
조치 : INI 파일 내용을 확인힙니다.
[#5007] LDAP 서버 정보가 ini 에 없습니다. (LDAP_SERVER)
Err.NoLdapServerValueInIni
에러 : INI 파일에 "LDAP_SERVER" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5008] MFA API URL이 ini 에 없습니다. (MFA_API_URL)
Err.NoMfaApiUrlValueInIni
에러 : INI 파일에 "MFA_API_URL" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5009] Consumer Key 값이 ini 에 없습니다. (CONSUMER_KEY)
Err.NoConsumerKeyValueInIni
에러 : INI 파일에 "CONSUMER_KEY" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5010] Secret Key 값이 ini 에 없습니다. (SECRET_KEY)
Err.NoSecretKeyValueInIni
에러 : INI 파일에 "SECRET_KEY" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5011] Cache Attribute 값이 ini 에 없습니다. (CACHE_ATTRIBUTE)
Err.NoCacheAttributeValueInIni
에러 : INI 파일에 "CACHE_ATTRIBUTE" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5012] Cache Delimeter 값이 ini 에 없습니다. (CACHE_DELIMETER)
Err.NoCacheDelimeterValueInIni
에러 : INI 파일에 "CACHE_DELIMETER" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5013] Skew Seconds 값이 ini 에 없습니다. (SKEW_SECONDS)
Err.NoSkewSecondsValueInIni
에러 : INI 파일에 "SKEW_SECONDS" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5014] Token expiration time 값이 ini 에 없습니다. (TOKEN_EXP_TIME)
Err.NoTokenExpTimeInIni
에러 : INI 파일에 "TOKEN_EXP_TIME" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5015] Cache life time 값이 ini 에 없습니다. (CACHE_LIFE_TIME)
Err.NoCacheLifeTimeInIni
에러 : INI 파일에 "CACHE_LIFE_TIME" 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#5016] 사용자 정보 claim 리스트가 ini 에 없습니다. (USERINFO_##)
Err.NoUserinfoListInIni
reserved (예약된 에러 코드이며, 향후 사용 예정)
[#5017] LDAP 연결시 id/pw 사용하도록 설정되어 있으나(LDAP_USE_IDPW=1), LDAP id 또는 pw가 ini 에 없습니다. (LDAP_ID, LDAP_PW)
Err.NoLdapIdPwInIni
에러 : LDAP 접속시 id/pw 사용하도록 설정되어 있으나, INI 파일에 LDAP_ID, LDAP_PW 설정 값이 없습니다.
조치 : INI 전체적으로 누락된 것이 없는지, INI 가 구버전의 것인지 등을 확인힙니다.
[#6000] AD(LDAP)에서 사용자 정보를 검색하는 과정에 Exception이 발생했습니다.
Err.ExceptionInAD
에러 : LDAP 서버에 Query를 헀으나, 그 과정 중에 Exception이 발생했습니다.
조치 : INI에 설정한 AD 서버 주소가 정확한지 확인해봅니다. 그리고, AD 서버 상태를 확인해봅니다.
참고
이벤트 로그에 있는 자세한 Exception 내용을 개발자에게 전달합니다.
[#6001] AD(LDAP)에서 사용자 정보를 찾을 수 없습니다.
Err.CannotFindUserInAD
에러 : LDAP 서버에 Query를 헀으나, AD 사용자 정보를 가져오지 못했습니다.
조치 : AD 서버 상태를 확인해봅니다.
참고
Token 구성에 mobile, email 정보가 필요한데, 이 정보들을 가져올때 실패한 것입니다. 사용자 정보가 존재한다면, mobile, email이 빈 값이어도 에러로 처리하지 않습니다. 그래서, 본 에러가 발생한 것은 LDAP Query 자체가 안된다고 보면 됩니다
사용자 에러 메시지
MFA 진행 과정에 에러가 발생하면, 사용자 PC 화면에 에러 메시지를 표시합니다.
에러 메시지는 “Internal error occurred. Contact administrator.” 로 고정되어 있으며, 다음 라인에 에러코드가 함께 표시됩니다.
아래는 에러코드에 대한 원인과 조치방법에 대한 설명입니다. ※ 사용자 에러 메시지 이외의 서버 내부처리 과정의 이벤트 로그 참고
ErrorCode : 0001
* Err.IdentityClaimHasNoAccount
* 함수 호출시 인자(arguments)가 잘 못 되었음
* 사용자에게 보여주는 에러는 아님
+ → 혹시 보인다면, 개발자에게 문의
+ → 이 시점의 서버 이벤트 로그를 봐야 함
ErrorCode : 1000
* Err.IdentityClaimHasNoAccount
* "identityClaim 에서 계정정보(account)를 추출할 수 없습니다."
* adapter 실행 초기에 AD 서버로부터 현재 사용자의 정보를 받는데, account 정보를 찾을 수 없음
* LDAP에서 Query 하는 것이 아니라, ADFS 내부적으로 처리되는 정보 흐름으로서,
+ 이 상황이 발생하면 adapter가 정상 동작할 수 없는 환경이라고 보면 됨
* AD 서버 상태를 먼저 확인해 볼 것
ErrorCode : 1001
* Err.FailToLoadIni
* 서버에서 MFA 환경설정 INI 파일을 읽을 수 없음
* 서버에 다음의 경로에 파일이 있는지 확인
+ C:\ ADFSadapter \ ADFSadapter.ini
* 만일, 파일이 있다면, 파일 속성 또는 권한 확인
ErrorCode : 1002
* Err.FailToLoadHtml
* 서버에서 HTML 파일을 읽을 수 없음
* 서버에 다음의 경로에 파일이 있는지 확인
+ C:\ ADFSadapter \ Html_*.txt
* 만일, 파일이 있다면, 파일 속성 또는 권한 확인
* 1개라도 없으면 에러 발생함 → 어떤 것이 누락되었는지는 서버 이벤트 로그에서 알 수 있음
ErrorCode : 1003
* Err.FailToLdapSearch
* "LDAP에서 사용자 정보를 가져올 수 없습니다."
* LDAP 서버에 Query를 헀으나, AD 사용자 정보를 가져오지 못함
* Token 구성에 mobile, email 정보가 필요한데, 이 정보들을 가져올때 실패하였음
* mobile, email이 빈 값이어도 에러로 처리하지 않음
* 그래서, 본 에러가 발생한 것은 LDAP Query 자체가 안된다고 보면 됨
ErrorCode : 1004
* Err.NoURLInRequest
* "BeginAuthentication 함수의 request에 URL 정보가 없습니다."
* Adapter 실행 초기에 실행되는 BeginAuthentication 함수의 인자 request에 URL 정보가 없음
* URL 정보가 없으면, SingleID MFA API 서버가 GET 방식으로 전송한 response를 사용할 수 없음
* SingleID MFA API 서버가 정상적으로 response를 보내는지 확인 필요
ErrorCode : 1005
* Err.FailToMakeJwtToken
* "JWT token 생성을 할 수 없습니다."
* GenerateRequestToken 함수가 token 생성에 실패하였음
* 정확한 원인은 서버 이벤트 로그에서 확인
ErrorCode : 1006
* Err.CannotFindDirOrIni
* "JWT token 생성을 할 수 없습니다."
* ADFSadapter 디렉토리 또는 INI 파일을 찾을 수 없음
* adapter 버전 1.2.0.6 부터 adapter 설치 위치가 C 드라이브 고정이 아닌 C to Z 드라이브 중의 한 곳에 설치할 수 있으며,
+ adapter는 C to Z 드라이브 스캔을 통해서 설치된 위치를 알아냄
* [drive]:/ADFSadapter/ADFSadapter.ini 파일이 존재해야 함
* 서버에 adapter 설치가 제대로 되었는지, 디렉토리명과 파일명이 정확한지 확인
* 드라이브 억세스가 막혀있는지 확인
ErrorCode : 2000
* Err.TryEndHasNoAccount
* "TryEndAuthentication()에 계정정보(account)가 없습니다."
* TryEndAuthentication 단계로 넘어왔으나, 계정 정보를 알 수 없음
* 이러한 경우는 절대 발생할 수 없음 (발생하였다면, 개발자에게 문의)
ErrorCode : 2001
* Err.NoStepInfo
* MFA 진행 단계(step) 정보가 없음
* 상세 정보와 원인은 서버의 이벤트 로그를 확인할 것
ErrorCode : 2002
* Err.InvalidStepInfo
* MFA 진행 단계(step) 정보가 잘 못 되었음
* 상세 정보와 원인은 서버의 이벤트 로그를 확인할 것
ADFS 로그인 페이지 수정
onload.js 편집
배경
MFA를 여러 개 설정한 경우, 사용자는 아래와 같은 선택 화면을 보게 됩니다.
화면을 처음 보는 상황에서는(MFA를 아직 완료하지 않음), 이 화면에서 선택이 필요합니다.
ADFS 로그인 페이지 수정
문제점은, MFA를 거친 후에 선택 화면이 다시 표시된다는 것이며, 사용자가 선택하는 행위를 다시 해줘야 합니다.
이는 사용자 불편 사항이 되며, 두번째 선택에 다른 MFA를 선택하면 원치않은 결과가 나올 것입니다.
MFA가 완료된 후에 위의 선택 화면이 나올때, 자동으로 넘어가는 기능이 필요합니다. (auto submit)
이를 위해서, ADFS에 이미 존재하는 onload.js 파일의 내용을 편집하는 것입니다.
Multi MFA가 아닌 경우에는 onload.js 파일 편집이 필요없습니다.
파일 경로
AD 서버의 아래 경로에 존재합니다.
디렉토리 = C:/default_WebTheme/script
파일명 = onload.js
파일 편집
파일 내용의 끝부분에 아래의 스크립트를 추가합니다.
주의
아래 예시의 Script Text를 복사 붙여넣기로 사용하면 안됩니다.
다국어 메시지가 아래 Text에서는 정상적으로 입력이 안되어 있습니다.
정상적인 Script Text가 포함된 파일을 별도로 준비하여야 합니다.
onload.js 는 UTF-8로 저장되어야 합니다.
// ------------------------------------------ SingleID MFA : begin
function singleidMfa() {
var authOptions = document.getElementById('authOptions')
if (authOptions) {
var noticeflag = document.getElementById('mfaGreeting');
var url = document.location.href;
var isToken = url.indexOf('jwtTokenResponse');
if (noticeflag && isToken < 1) {
var browserLang = navigator.language || navigator.userLanguage;
// 다국어 처리
// 한국어
if (lang == 'ko-KR' || lang == 'ko') {
document.getElementById('footerPlaceholder').innerHTML="<h3 style='font-weight: bold;'><br/> <br/> ※ 신규 복합인증솔루션 테스트 중 (13:00~15:00) <br/> 'My Authentication Provider' 메뉴를 이용해주세요. </h3>";
}
// 중국어
else if (lang == "zh" || lang.indexOf("zh-") > -1) {
document.getElementById('footerPlaceholder').innerHTML="<h3 style='font-weight: bold;'><br/> <br/> ※ 正在??新的?合??解?方案 (13:00~15:00) <br/> ?登? 'My Authentication Provider' 菜?。 </h3>";
}
// 베트남어
else if (lang == "vi") {
document.getElementById('footerPlaceholder').innerHTML="<h3 style='font-weight: bold;'><br/> <br/> ※ đang ki?m tra gi?i phap xac th?c k?t h?p m?i (13:00~15:00) <br/> Xin vui long đ?ng nh?p vao trinh đ?n 'My Authentication Provider'. </h3>";
}
// 스페인어
else if (lang == "es" || lang.indexOf("es-") > -1) {
document.getElementById('footerPlaceholder').innerHTML="<h3 style='font-weight: bold;'><br/> <br/> ※ Prueba de una nueva solucion de autenticacion compleja (13:00~15:00) <br/> Inicie sesion en el menu 'My Authentication Provider'. </h3>";
}
// 영어
else {
document.getElementById('footerPlaceholder').innerHTML="<h3 style='font-weight: bold;'><br/> <br/> ※ Testing a new MFA solution (13:00~15:00) <br/> Please use 'My Authentication Provider' menu. </h3>";
}
}
var opt = document.getElementById('optionSelection');
if (opt && isToken > 0) {
opt.value = 'ADFSadapter';
document.forms['options'].submit();
}
}
}
window.addEventListener('load', function () {
singleidMfa();
});
// ------------------------------------------ SingleID MFA : end
스크립트의 기능
페이지의 컨트롤 중에 authOptions 가 있는 경우에 해당됩니다.
페이지 load가 모두 완료된 이후에 동작하는 방식입니다. (그 전에 실행되면 에러가 발생하기 때문)
window.addEventListener 를 이용해서 load 이벤트에 추가 (window.onload 이벤트와 동일)
Case 1 : 컨트롤 중에 mfaGreeting 이 있고, URL에 jwtTokenResponse 가 없는 경우 브라우저 언어 설정에 맞추어 사용자 안내 메시지 출력 (다국어)
Case 2 : 컨트롤 중에 optionSelection 이 있고, URL에 jwtTokenResponse 가 있는 경우 optionSelection 에 ADFSadapter를 할당하고, options form을 강제로 submit 처리
스크립트 추가시 주의 사항
기존 스크립트에 영향을 주지 않고 관리가 용이하도록, 스크립트의 마지막 부분에 넣는 것이 안전합니다.
onload.js 적용
onload.js 파일을 수정 반영하여 ADFS Sign-in Page customization 가능
주의
악성스크립트로 오탐 가능한 명령어가 포함되어있어, 실제 입력하셔야 하는 명령어와 다르게 표기된 명령어가 있습니다.
-ON-LOADScriptPath 는 실제로 다음의 명령어이니 혼선 없으시길 바랍니다.
적용 방법
현황 확인
PS> Get-AdfsWebConfig ## 적용된(활성화 상태인) WebTheme 확인
PS> Get-AdfsWebTheme ## 생성된 WebTheme 리스트 확인
테마 적용
테마 적용 방법 1) default 테마에서 새로 만들기
PS> New-AdfsWebTheme -Name "custom_stg" -SourceName default ## 새로운 WebTheme 생성
PS> Set-AdfsWebTheme -TargetName "custom_stg" -Illustration @{Path="C:\adfs_Login_dev\illustration\image_0624\8.jpg"} -Logo @{Path="C:\adfs_Login_dev\images\logo.png"} -StyleSheet @{Path="C:\adfs_Login_dev\css\style.css"} -ON-LOADScriptPath "C:\adfs_Login_dev\script\ON-LOAD_new.js" ## custom 한 js 파일 적용
테마 적용 방법 2) 전자 테마에서 업데이트 하기
PS> New-AdfsWebTheme -Name "custom_stg" -SourceName [전자테마] ## 새로운 WebTheme 생성
PS > Set-AdfsWebTheme -TargetName "custom_stg" -OnLoadScriptPath "C:\adfs_Login_dev\script\onload_stg.js" ## custom 한 js 파일 적용
그림. 테마 적용
※ 테마 적용 방법 1), 2) 방법 서버 명령어 캡쳐본. Confluence 정리 시 OnLoad 명령어가 자동 변경되어 캡처본 첨부
PS> Set-AdfsWebConfig -ActiveThemeName "custom_stg" ## 생성된 WebTheme 활성화
기존 테마 복구
PS> Set-AdfsWebConfig -ActiveThemeName "default" ## 기존 WebTheme 활성화
참고
하나의 WebTheme 에는 custom js 파일 하나만 적용 가능
MS에도 문의하였으나, 공식적으로 한 개의 onload.js 파일만 적용 가능하며, 추가적으로 제시한 방법은 적용 안됨
“the ON-LOAD.js is an integrated part of the HTML (the last script in the body) which always executes when the ADFS Page is loaded
There can be only one named ON-LOAD.JS per Web theme.
What is possible though is that additional ('external') scripts can be loaded as part of the actual ON-LOAD.js execution
let’s say in a specific part of your ON-LOAD.JS you want to load a bootstap.js which implements additional functionality
you would firstly import that additional JS to the webpage as AdditionalFileResource //it should not be named ON-LOAD.js
eg
Set-AdfsWebTheme -TargetName custom -AdditionalFileResource @{Uri='/adfs/portal/script/bootstrap.js';path="c:\theme\script\bootstrap.js"}
then you implement a loading functionality in the ON-LOAD.js which dynamically loads your additional script as needed”
주의사항 : 단 1개의 드라이브에만 설치해야 하며, 만일 여러 개의 드라이브에 설치된 경우 C to Z 스캔하면서 가장 먼저 발견된 디렉토리를 사용함
아래의 예시는, adapter를 C:\ADFSadapter 디렉토리에 설치한 경우입니다. C 이외의 다른 드라이브에 설치한 경우, 아래의 예시에서 드라이브명(drive letter)만 변경하면 됩니다.
예시: D:\ADFSadapter 에 설치한 경우 ini 경로 → D:\ADFSadapter\ADFSadapter.ini
파일명 및 경로
파일명: ADFSadapter.ini
전체 경로: C:\ADFSadapter\ADFSadapter.ini
파일 인코딩: 반드시 UTF-8 로 저장할 것 (한글이 깨짐현상 발생)
알아두어야 할 점
* 값을 표현할때 "와" 를 사용할 수 있으며 = 좌우에 빈칸을 입력해도 됩니다.
+ Value 의 앞뒤에 있는 공백은 Trim 처리 됩니다.
+ 아래의 Value는 모두 동일함
+ 예1) MAIN_TITLE = DWP MFA Adapter
+ 예2) MAIN_TITLE = DWP MFA Adapter
+ 예3) MAIN_TITLE = "DWP MFA Adapter"
+ 예4) MAIN_TITLE = " DWP MFA Adapter "
* 섹션 이름들 중에 뒷부분에 -1033, -1042 가 붙는 것들은 locale 을 의미합니다.
+ 최소한 1033 은 반드시 있어야 합니다.
+ locale number : 1033 (en-us), 1042 (ko)
+ locale section : MFA-1033, MFA-1042, TXT-1033, TXT-1042, MSG-1033, MSG-1042
ini 파일 구조 예시
아래의 설정 값 예시 중에 보안 목적으로 masking 한 값들이 있으며, 실제 값은 asterisk 가 아닙니다.
# ADFS MFA Adapter 환경 설정
# 설치위치 변경 사항
# - v1.2.0.6 이전 : C:\ADFSadapter\ADFSadapter.ini
# - v1.2.0.6 부터 : C 이외의 다른 드라이브에 설치할 수 있음 (adapter 리소스 설치한 위치와 동일)
# 예시: C:\ADFSadapter\ADFSadapter.ini , D:\ADFSadapter\ADFSadapter.ini , E:\ADFSadapter\ADFSadapter.ini
# 주의 : DLL 파일명은 ADFSadapter.dll 이며, 기존의 Nexsign 연계한 MFAadapter.dll과는 다름
# 값을 표현할때 " 와 ' 를 사용할 수 있으며 = 좌우에 빈칸을 입력해도 됩니다
# Value 의 앞뒤에 있는 공백은 Trim 처리 됩니다.
# 아래의 Value는 모두 동일합니다.
# 예1) MAIN_TITLE=ADFS MFA Adapter
# 예2) MAIN_TITLE = ADFS MFA Adapter
# 예3) MAIN_TITLE = "ADFS MFA Adapter"
# 예4) MAIN_TITLE = " ADFS MFA Adapter "
# 섹션 이름들 중에 뒷부분에 -1033, -1042 가 붙는 것들은 locale 을 의미합니다
# 최소한 1033 은 반드시 있어야 합니다
# locale number : 1033 (en-us), 1042 (ko)
# locale section : MFA-1033, MFA-1042, TXT-1033, TXT-1042, MSG-1033, MSG-1042
# LOG_LEVEL (Windows 이벤트 로그에 기록하는 기준)
# 0 : Error
# 1 : Error + Warning
# 2 : Error + Warning + Information + Debug
[MAIN]
MAIN_MFA_TITLE="ADFS MFA Adapter"
MAIN_CLAIM1=http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod
MAIN_CLAIM2=http://schemas.microsoft.com/ws/2012/12/authmethod/otp
# MFA API 정보
# URL 끝부분에 "/" 붙이지 말 것
#MFA_API_URL="https://stg2-cloud.singleid.samsung.net/test/common-api/open/v1.1/mfa/request"
MFA_API_URL="https://stg1-cloud.singleid.samsung.net/test/common-api/open/v1.1/mfa/request"
CONSUMER_KEY="**************************************"
SECRET_KEY="**************************************"
# Donmain vs Consumer Key 리스트
# 도메인별로 Consumer Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 CONSUMER_KEY 값을 비울 것)
# Reqeust Token의 sys 값에 대입
# 형태 : DOMAIN_CONSUMER_KEY_##=domain;consumerKey
# 예시: DOMAIN_CONSUMER_KEY_01=aaa.com;**************************************
# DOMAIN_CONSUMER_KEY_02=bbb.com;**************************************
# (주의) CONSUMER_KEY 값과 리스트 값이 모두 있다면, CONSUMER_KEY 값만 사용함
DOMAIN_CONSUMER_KEY_01=aaa.com;**************************************
DOMAIN_CONSUMER_KEY_02=bbb.com;**************************************
# Donmain vs Secret Key 리스트
# 도메인별로 Secret Key가 다른 경우에는 리스트로 나열 (이런 경우, 위의 SECRET_KEY 값을 비울 것)
# 형태 : DOMAIN_SECRET_KEY_##=domain;secretKey
# 예시: DOMAIN_SECRET_KEY_01=aaa.com;**************************************
# DOMAIN_SECRET_KEY_02=bbb.com;**************************************
# (주의) SECRET_KEY 값과 리스트 값이 모두 있다면, SECRET_KEY 값만 사용함
DOMAIN_SECRET_KEY_01=aaa.com;**************************************
DOMAIN_SECRET_KEY_02=bbb.com;**************************************
# LDAP Search 결과에 따른, MFA 진행 여부
# 0 : LDAP Search를 하지 않음 (아래의 LDAP_SERVER, LDAP_USE_IDPW, ... 등의 정보 사용하지 않음. token에는 빈 값 대입)
# 1 : LDAP Search를 시도하지만 실패해도 관계없음 (서버 실패, 정보 없음 등이 발생하여도 MFA 진행함. token에는 빈 값 대입)
# 2 : LDAP Search가 성공 & 사용자 정보가 존재해야 함 (사용자 정보가 존재할 경우에만 진행함. 단, 결과 값이 빈 값이어도 진행함)
USE_LDAP_SEARCH=1
# LDAP 주소와 ID/PW
# LDAP_SERVER는 domain, ipv4, ipv6 등의 3가지 모두 가능하며, 앞부분에 대문자 "LDAP://" 을 붙여야 함 (반드시 대문자)
# 예시: LDAP://adpw5004.hw.dev , LDAP://70.2.180.218 , LDAP://fe80::644b:3c9f:c5ac:ce1c%10
# ID/PW를 사용하려면 LDAP_USE_IDPW 값을 1, 사용하지 않으려면 LDAP_USE_IDPW 값을 0 으로 설정
# SSL/TLS 사용하려면 LDAP_SSLTLS 값을 1, 사용하지 않으려면 LDAP_SSLTLS 값을 0 으로 설정 (단, LDAP_USE_IDPW=1 인 경우에만 해당)
LDAP_SERVER="LDAP://adpw5004.hw.dev"
LDAP_USE_IDPW=1
LDAP_SSLTLS=1
LDAP_ID="isadmin"
LDAP_PW="sds*****"
# DNS Lookup을 하여 LDAP 서버(LDAP_SERVER)의 IP 주소를 확인하고, IP 주소 기반으로 접속 여부
# LDAP_SERVER 값이 IP(ipv4, ipv6)로 설정되어 있어도 DNS Lookup을 수행하며, IP 그대로 리턴됨
# 만약, DNS Lookup을 실패하면, LDAP_SERVER 값 그대로 접속
# 0 : LDAP_SERVER 값 그대로 서버에 접속 (DNS lookup 하지 않음)
# 1 : DNS lookup으로 IP 주소를 확인하여 LDAP 서버에 접속 (DNS lookup 결과 리스트에서 첫번째 IP 사용)
# 2 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP_SERVER 사용)
# 3 : DNS lookup으로 IP 주소를 확인하고, LDAP_WHITE_IP_## 리스트에서 가장 먼저 해당되는 IP를 사용 (리스트에 없으면, LDAP 접속 안함)
LDAP_DNS_LOOKUP=1
# DNS Lookup 결과가 여러 개일때, 첫번째 IP 주소로 연결이 안되면 그 다음 IP 주소로 시도할지 여부
# 예시: lookup 결과가 4개 : 1차 IP 연결 실패 -> 2차 IP 연결 시도 & 싪패 -> 3차 IP 연결 시도 & 싪패 -> 4차 IP 연결 시도
LDAP_DNS_IF_FAIL_USE_NEXT=1
# DNS Lookup 결과와 비교하는 접속 허용된 LDAP 서버 IP 리스트 (LDAP_DNS_LOOKUP = 2 or 3 인 경우에만 해당)
# LDAP_WHITE_IP_## 형태이며, 01부터 99까지 순차적으로 기록
# DNS Lookup 결과와 리스트를 순차적으로 비교
# IPv4, IPv6 형태로 기록 (동일한 서버의 IPv4, IPv6가 있다면 리스트의 앞순위에 있는 IP가 적용됨)
# DNS Lookup 결과 순서와 White IP 리스트 순서가 다르다면 -> White IP 리스트 순서를 따름
LDAP_WHITE_IP_01="70.2.180.218"
LDAP_WHITE_IP_02="fe80::644b:3c9f:c5ac:ce1c%10"
# 사용자 정보를 암호화할지 여부 (예: mobile, email 등)
# 대상 : USERINFO_## 리스트
# 암호화 여부에 따라 API 서버에 전송하는 token의 claim 이름이 다름
# 0 : 암호화 하지 않음 -> token의 claim 이름이 plainMobile, plainEmail
# 1 : 암호화 -> token의 claim 이름이 mobile, email
USERINFO_ENCRYPT=0
# LDAP Search할 사용자 정보 attribute name과 JWT token에 사용할 claim name (2개 값을 구분하는 delimeter = ";")
# 형태: USERINFO_## = attribute;encryptedClaim;plainClaim
# 예시: LDAP에서 "mail" 속성을 읽어서, JWT에 "email" claim으로 사용된다면 -> "mail;email;plainEmail"
# key 명칭은 "USERINFO_##" 형태로 하고, 시작은 USERINFO_01
# key 갯수 : 0개 ~ 최대 99개 (0개인 경우, ini에 아무것도 적지 않으면 되며, USERINFO_00 이라고 적지 말 것)
# 주의사항) USERINFO_##에서 ## 에 해당되는 숫자는 반드시 01부터 시작하며, 여러 개인 경우 번호가 끊어지지 않아야 함
# USERINFO_01, USERINFO_02, USERINFO_03 : OK (01, 02, 03 정보가 사용됨)
# USERINFO_01, USERINFO_02, USERINFO_05 : 02까지 읽고, 끊어진 번호 이후는 사용하지 않음 (01, 02 정보가 사용됨)
USERINFO_01=mobile;mobile;plainMobile
USERINFO_02=mail;email;plainEmail
# MFA API 서버가 Callback 해줄때, 결과 Parameter에 사용되는 Key 이름
# 예시: https://adpw5004.hw.dev/adfs/ls?client-request-id=xxxxxx&pullStatus=0&jwtTokenResponse=yyyyyy
KEY_NAME_IN_RESPONSE="jwtTokenResponse"
# JWT Token의 exp에 적용될 더하기 값
# 형테 : 일시분초(dhms) 형태의 문자열 -> 1d=86400, 1h=3600, 1m=60 (dhms 가 전혀 없는 단순 숫자는 초로 판단함)
# 예시1 : 1d02h38m27s -> 95907 초
# 예시2 : 12345 -> 12345 초
TOKEN_EXP_TIME=1d
# API 호출할때 구성하는 token에 client claim을 추가할지 여부
# client : SAML인 경우 issuer, OIDC인 경우 client-id
# 0 : token에 client 포함시키지 않음
# 1 : token에 client 포함
TOKEN_CLAIM_CLIENT=0
# MFA nonce(guid, requset-id) 검증 방법
# 0 : 검증 안함
# 1 : adapter가 생성한 guid를 LDAP에 저장/비교하는 방식 (adapter가 검증)
# -> 관련 설정 값 : CACHE_ATTRIBUTE, CACHE_DELIMETER, SKEW_SECONDS, CACHE_LIFE_TIME
# 2 : API 서버가 생성한 requeset-id를 adapter가 받아서 호출 URL에 사용하는 방식 (API 서버가 검증)
# -> 관련 설정 값 : MFA_VERIFY_URL
MFA_VERIFY_TYPE=2
# MFA 결과검증 URL (서버 to 서버 통신) : URL 뒷부분에 API 서버로부터 받은 {request-id}를 덧붙여서 호출함
# adapter는 리턴 200 (OK) 인지 확인하여 MFA 결과 처리
# URL 끝부분에 "/" 붙이지 말 것
MFA_VERIFY_URL="https://stg1-cloud.iam.samsung.net/test/common-api/open/v1.1/mfa/request/status"
# MFA 결과검증할때 사용할 보안 프로토콜
# 선택 가능한 프로토콜 (대소문자 구분 없음) : TLS12, TLS13
# (주의) SSL3, TLS, TLS11 은 사용하지 않음
MFA_VERIFY_SECURE_PROTOCOL="TLS12"
# 사용자의 req guid 값을 저장할 LDAP attribute의 이름
# (주의) LDAP에 write 권한이 있어야 함
CACHE_ATTRIBUTE="otherPager"
# LDAP에 저장하는 req + 시간 정보를 조합할때 사용하는 delimeter -> "req;시간"
CACHE_DELIMETER=";"
# LDAP에 저장된 req의 시간과 JWT 수신시 시간의 차이 허용치 (초단위)
# MFA 선택화면 누를 때가 아니라, AD 로그인 직후의 시간이므로 (MFA 선택화면 보일때 이미 시간이 저장되었음)
# 사용자가 MFA 선택화면 누르고 Passcode 입력할 때까지의 시간이 아님
# 따라서, tight 하게 시간을 설정하면 안되며, 1시간 정도가 적당?? (MFA 선택을 1시간 고민하는 사람이 있나?)
SKEW_SECONDS=3600
# LDAP에 저장된 req의 수명 -> 다음 access시 시간 확인해서 이전의 오래된 것들 삭제
# 형태 : 일시분초(dhms) 형태의 문자열 -> 1d=86400, 1h=3600, 1m=60 (dhms 가 전혀 없는 단순 숫자는 초로 판단함)
# 예시1 : 1d02h38m27s -> 95907 초
# 예시2 : 12345 -> 12345 초
CACHE_LIFE_TIME=1d
# Adapter 기능을 ByPass 할 것인지 여부 (0=정상 사용, 283901=무력화, 그 외 값들=정상 사용)
# MFA 기능 문제로 급하게 adapter 기능의 무력화가 필요한 비상 상황에서 사용
# 평상시에는 절대로 수정하지 말 것 -> 평상시 값은 0
# 주의 : 무력화하려면 반드시 정확한 값을 설정해야 함 (0 이외의 숫자가 해당되는 것이 아니며 정확한 숫자 필요함. noise 우려)
BYPASS_ADAPTER=0
[API]
API_SYSTEMNAME=SingleID
[MSG-1033]
MSG_INTERNAL_ERROR="Internal error occurred. Contact administrator."
[MSG-1042]
MSG_INTERNAL_ERROR="Internal error occurred. Contact administrator."
[MANAGE]
LOG_LEVEL=2
설정 값 설명
값 고정 : 하단 테이블의 설정 값 컬럼에 표시된 값을 ADFS 서버에 설치시에도 그대로 사용한다는 의미합니다.
영문, 한국어 이외의 언어를 추가하고자 한다면, 2개 Section에 대해서는 추가가 가능합니다.