5.8 KiB
5.8 KiB
// ...existing code...
6.5 서버 검증 및 로그인 완료 프로세스
프로세스(서버 측 상세 작업 — 앱에서 승인(decision=approve) 제출 후 Baron SSO가 수행할 처리 로직):
-
수신 검증(입력 유효성)
- 수신된 payload에서 authReqId, deviceId, decision, nonce, approvedAt, (선택)devicePhoneNumberLast4, signature 등을 파싱.
- 필수 필드 누락 시 400 반환 및 감사로그 기록.
-
권한·상태 확인(원자적 검사/전이)
- DB/Redis에서 auth_req 레코드를 조회(행 잠금/트랜잭션 사용).
- 현재 상태가 pending인지 확인. pending이 아니면 idempotent 응답(이미 approved/rejected/expired 등) 반환.
- expires_at 검증(만료된 요청이면 상태를 expired로 전이하고 거부 처리).
-
기기 등록·일치 확인
- 제출된 deviceId가 auth_req에 연관된 user_id에 등록된 기기인지 확인.
- DB에 저장된 push_token/플랫폼/등록 전화번호 해시 등과 기본 일치 검사 수행.
- 불일치 시 거부 및 보안 경고(로그, 관리자 알림).
-
서명 검증(앱이 서명하는 구현인 경우)
- 저장된 public_key(JWK)로 JWS/COSE 서명 검증.
- signature 불일치 시:
- 해당 deviceId의 시도 횟수 증가 및 임계치 초과 시 기기 차단.
- 감사로그와 알림 생성.
- 거부 응답 반환.
대체(앱이 서명하지 않는 모델인 경우):
- 서명 검증 대신 다음 신호들을 결합한 위험평가 수행:
- push 전송 성공 기록(FCM/APNs 응답)과 앱의 approvedAt 타임스탬프의 시간차(허용 보정값, 권장 60–180초).
- 앱에서 제출한 전화번호 일부(예: 마지막4자리)와 서버 저장 번호 확인.
- 요청 IP/UA/위치와 기존 프로필의 일치도.
- device attestation(Play Integrity/App Attest) 결과 유무.
- 비정상 반복/속도 패턴 탐지.
-
nonce/재사용 방지
- 제출 nonce가 auth_req에 기록된 nonce와 일치하는지 검사.
- nonce 재사용 시 거부 및 보안 처리(로그·차단).
-
리스크 스코어링 및 정책 결정
- 위 항목들(서명 검증 결과, push 타임스탬프, 전화번호 매칭, attestation, IP/위치 일치, rate-limit)으로 리스크 점수 산출.
- 리스크가 허용 임계값 이하이면 승인 진행, 초과 시 추가 인증(예: SMS OTP) 요구 또는 거부 처리.
-
인증 상태 전이 및 세션 수립
- auth_req 상태를 approved로 전이(원자적 업데이트).
- Kratos 사용 시:
- 기존 세션 확인: 이미 유효한 세션이 있으면 세션 정보 갱신.
- 세션이 없으면 Kratos Admin API를 통해 세션 생성(또는 필요한 identity 확인 후 세션 수립).
- Hydra와 연동:
- Hydra의 AcceptLoginRequest 호출:
- subject: Kratos identity id
- context: amr, acr, auth_time, sid 등 (권장)
- remember / remember_for 등은 정책에 따라 설정
- Hydra가 반환한 redirect URL 또는 authorization result를 poll 응답에 반영.
- Hydra의 AcceptLoginRequest 호출:
-
토큰 발행 흐름(표준 유지)
- 이후 RP는 기존 OIDC Authorization Code + PKCE 교환 절차를 통해 토큰을 발급받음(Hydra 책임).
- Baron SSO는 발급 관련 추가 제어(특정 RP에 대해 acr 조건 검증 등)를 수행.
-
감사·알림·정리
- 승인 이벤트를 감사 로그에 남김(필수 항목: auth_req_id, user_id, client_id, device_id, request_ip, request_user_agent, decision, user_verification, signature_valid 여부, completed_at).
- 사용자(및 필요 시 관리자)에게 승인 완료 알림(선택) 발송.
- auth_req 레코드 정리(만료/완료 후 TTL 후 삭제 또는 아카이빙).
- 모니터링/metrics(승인율, 실패율, 서명 불일치 건수 등) 수집.
-
실패/이상 처리
- 검증 실패(서명 불일치, device 미등록, nonce 불일치 등)는 상태를 failed/blocked로 전이.
- 실패 사유에 따라:
- 즉시 사용자에게 거부 알림.
- 고위험 징후 시 기기 즉시 차단 및 관리자 알림.
- 폴백 흐름(예: SMS OTP 발송, 이메일 확인) 트리거 가능.
- 반복적 실패 시 rate-limit 및 계정 잠금 정책 적용.
운영·구현 권장사항(간단 요약):
- 모든 상태 전이는 원자적이어야 하며 동시성 경합을 막기 위해 DB 락 또는 CAS 사용.
- idempotency 처리: 동일 승인 제출이 여러번 들어와도 안전하게 처리.
- TTL과 시간 동기 허용 오차(예: 서버-앱 간 시차 30초) 정책 정의.
- 서명 미사용 시 리스크 보정(더 짧은 TTL, 강한 attestation, 추가 인증 폴백).
- 감사 로그는 비가역 저장소(immutable)로 보관하고, 관련 이벤트는 SIEM으로 전송.
- 민감 RP의 경우 서버에서 추가 확인이 필요한 정책(예: 서명 필수, attestation 필수)을 강제.
간단한 의사 코드(pseudocode):
// POST /api/v1/auth/baron-safe/requests/{authReqId}/decision handler
payload = parse(request.body)
auth = db.getAuthReq(payload.authReqId)
if auth == null or auth.status != "pending": return idempotentResponse(auth.status)
if auth.expires_at < now(): db.update(authReqId, status="expired"); return expiredResponse()
device = db.getDevice(payload.deviceId)
if device.user_id != auth.user_id: return error("device mismatch")
if payload.signature:
if not verifySignature(payload, device.public_key): handleSignatureFailure()
else:
score = riskScore(payload, auth, device, pushLogs, attestation)
if score > threshold: triggerFallbackOrReject()
// all checks passed
db.update(authReqId, status="approved", approved_at=now(), approver_device=device.id)
kratos.ensureSession(auth.user_id)
hydra.acceptLogin(auth.login_challenge, subject=auth.user_id, acr=selected_acr, amr=selected_amr)
audit.log(approved event)
return { status: "approved" }
// ...existing code...