5.3 KiB
5.3 KiB
Headless 사번 로그인 로직
이 문서는 사용자가 데모 애플리케이션에서 사번과 비밀번호를 이용해 로그인할 때 발생하는 내부 OIDC (OpenID Connect) Headless 인증 흐름을 설명합니다.
핵심 개념
- Headless Login: 사용자가 IdP(Identity Provider, Baron SSO)의 로그인 화면을 거치지 않고, RP(Relying Party, 데모 앱) 내에서 직접 아이디와 비밀번호를 입력받아 백채널(Back-channel)로 인증을 수행하는 방식입니다.
- Client Assertion: 보안을 위해 데모 앱은 사번/비밀번호를 전송할 때 자신이 신뢰할 수 있는 앱임을 증명하는 JWT(
client_assertion)를 생성하여 함께 전송합니다.
1. 사번 로그인 시퀀스 다이어그램
sequenceDiagram
autonumber
actor User as 사용자
participant RP as 데모 앱 (RP)
participant OIDC as Baron SSO (OIDC/Hydra)
participant Auth as Baron SSO (Headless API)
User->>RP: 1. 사번 / 비밀번호 입력 후 로그인 요청
note over RP: [1단계: 신호 요청]
RP->>OIDC: 2. OIDC Discovery 및 Authorization Request<br/>(GET /oauth2/auth?response_type=code...)
OIDC-->>RP: 3. login_challenge 발급 및 302 Redirect
note over RP: [2단계: 본인 인증]
RP->>RP: 4. Private Key로 client_assertion (JWT) 생성
RP->>Auth: 5. Headless 로그인 API 호출<br/>(POST /api/v1/auth/headless/password/login)<br/>[client_assertion, login_challenge, 사번, 비밀번호 포함]
Auth-->>RP: 6. 인증 성공 및 리다이렉트 URL 반환
note over RP: [3단계: 권한 획득]
RP->>OIDC: 7. 리다이렉트 URL 추적 (Cookie 유지)
OIDC-->>RP: 8. Consent 화면 (필요 시 자동 승인 API 호출)
OIDC-->>RP: 9. 최종 Authorization Code 발급 (code=...)
note over RP: [4단계: 인증키 발급]
RP->>OIDC: 10. Token Endpoint 호출 (Authorization Code Grant)<br/>[client_assertion 포함]
OIDC-->>RP: 11. id_token, access_token 발급
note over RP: [5단계: 로그인 완료]
RP->>RP: 12. id_token 검증 및 사용자 세션 생성
RP-->>User: 13. 홈 화면 리다이렉트 및 로그인 성공
2. 단계별 상세 로직 설명
위 다이어그램의 주요 단계를 데모 애플리케이션(server.js의 runHeadlessSsoLogin 함수) 로직을 중심으로 설명합니다.
[1단계] 신호 요청 (Authorization Request)
- 목적: SSO 서버와의 세션을 시작하고, 인증 컨텍스트를 식별할 수 있는 고유값(
login_challenge)을 획득합니다. - 동작:
- OIDC Discovery를 통해 엔드포인트들을 가져옵니다.
response_type=code,client_id,state,nonce등을 포함하여 Authorization Endpoint(/oauth2/auth)로fetch요청(리다이렉트 수동 추적 모드)을 보냅니다.- 응답 헤더의
Location에 포함된login_challenge값을 추출합니다.
[2단계] 본인 인증 (Headless Password Login)
- 목적: 사용자가 입력한 자격 증명(사번, 비밀번호)을 SSO 서버에 직접 전달하여 인증을 승인받습니다.
- 동작:
- RP의 **Private Key(
keys.json)**를 사용하여client_assertionJWT를 서명합니다. (이때aud값은 SSO 서버의 Headless API URL이어야 합니다.) POST /api/v1/auth/headless/password/login엔드포인트로 JSON 페이로드를 전송합니다.{ "client_id": "...", "login_challenge": "...", "loginId": "사번", "password": "비밀번호", "client_assertion": "..." }- 인증이 성공하면 서버는 OIDC 로그인 흐름을 계속할 수 있는
redirectTo주소를 반환합니다.
- RP의 **Private Key(
[3단계] 권한 획득 (Redirect Resolution & Consent)
- 목적: 인증 성공 후, OIDC 프로토콜에 따라 최종적으로
Authorization Code를 획득합니다. - 동작:
- 2단계에서 받은
redirectTo주소를 따라가며 쿠키(Cookie)를 계속 유지시킵니다. - 만약 경로 중에 정보 제공 동의(
consent) 화면이 감지되면, 데모 앱이 사용자 대신 백그라운드에서 동의 API(POST /api/v1/auth/consent/accept)를 호출하여 자동 승인합니다. - 최종적으로 URL에
code=...가 포함된 리다이렉트를 찾습니다.
- 2단계에서 받은
[4단계] 인증키 발급 (Token Exchange)
- 목적: 획득한
Authorization Code를 안전한 토큰들로 교환합니다. - 동작:
- Token Endpoint로 코드를 전송합니다.
- 이때도 보안을 위해
private_key_jwt방식이 사용되므로, 새로 생성한client_assertion을 요청 본문에 포함시킵니다. - 검증이 완료되면
access_token과 사용자 정보가 담긴id_token을 받게 됩니다.
[5단계] 로그인 완료 (Session Creation)
- 목적: 받은 토큰을 검증하고, 브라우저가 인식할 수 있는 로컬 세션을 만듭니다.
- 동작:
jose라이브러리를 통해id_token의 서명을 검증하고 payload(사번, 이름, 부서 등)를 추출합니다.- 추출된 사용자 정보를
express-session의req.session.user에 저장합니다. - 클라이언트 브라우저에게 세션 쿠키를 발급하며 홈 화면(
/home.html)으로 리다이렉트 시킵니다.