// ...existing code... ### 6.5 서버 검증 및 로그인 완료 프로세스 프로세스(서버 측 상세 작업 — 앱에서 승인(decision=approve) 제출 후 Baron SSO가 수행할 처리 로직): 1. 수신 검증(입력 유효성) - 수신된 payload에서 authReqId, deviceId, decision, nonce, approvedAt, (선택)devicePhoneNumberLast4, signature 등을 파싱. - 필수 필드 누락 시 400 반환 및 감사로그 기록. 2. 권한·상태 확인(원자적 검사/전이) - DB/Redis에서 auth_req 레코드를 조회(행 잠금/트랜잭션 사용). - 현재 상태가 pending인지 확인. pending이 아니면 idempotent 응답(이미 approved/rejected/expired 등) 반환. - expires_at 검증(만료된 요청이면 상태를 expired로 전이하고 거부 처리). 3. 기기 등록·일치 확인 - 제출된 deviceId가 auth_req에 연관된 user_id에 등록된 기기인지 확인. - DB에 저장된 push_token/플랫폼/등록 전화번호 해시 등과 기본 일치 검사 수행. - 불일치 시 거부 및 보안 경고(로그, 관리자 알림). 4. 서명 검증(앱이 서명하는 구현인 경우) - 저장된 public_key(JWK)로 JWS/COSE 서명 검증. - signature 불일치 시: - 해당 deviceId의 시도 횟수 증가 및 임계치 초과 시 기기 차단. - 감사로그와 알림 생성. - 거부 응답 반환. 대체(앱이 서명하지 않는 모델인 경우): - 서명 검증 대신 다음 신호들을 결합한 위험평가 수행: - push 전송 성공 기록(FCM/APNs 응답)과 앱의 approvedAt 타임스탬프의 시간차(허용 보정값, 권장 60–180초). - 앱에서 제출한 전화번호 일부(예: 마지막4자리)와 서버 저장 번호 확인. - 요청 IP/UA/위치와 기존 프로필의 일치도. - device attestation(Play Integrity/App Attest) 결과 유무. - 비정상 반복/속도 패턴 탐지. 5. nonce/재사용 방지 - 제출 nonce가 auth_req에 기록된 nonce와 일치하는지 검사. - nonce 재사용 시 거부 및 보안 처리(로그·차단). 6. 리스크 스코어링 및 정책 결정 - 위 항목들(서명 검증 결과, push 타임스탬프, 전화번호 매칭, attestation, IP/위치 일치, rate-limit)으로 리스크 점수 산출. - 리스크가 허용 임계값 이하이면 승인 진행, 초과 시 추가 인증(예: SMS OTP) 요구 또는 거부 처리. 7. 인증 상태 전이 및 세션 수립 - 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 응답에 반영. 8. 토큰 발행 흐름(표준 유지) - 이후 RP는 기존 OIDC Authorization Code + PKCE 교환 절차를 통해 토큰을 발급받음(Hydra 책임). - Baron SSO는 발급 관련 추가 제어(특정 RP에 대해 acr 조건 검증 등)를 수행. 9. 감사·알림·정리 - 승인 이벤트를 감사 로그에 남김(필수 항목: 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(승인율, 실패율, 서명 불일치 건수 등) 수집. 10. 실패/이상 처리 - 검증 실패(서명 불일치, device 미등록, nonce 불일치 등)는 상태를 failed/blocked로 전이. - 실패 사유에 따라: - 즉시 사용자에게 거부 알림. - 고위험 징후 시 기기 즉시 차단 및 관리자 알림. - 폴백 흐름(예: SMS OTP 발송, 이메일 확인) 트리거 가능. - 반복적 실패 시 rate-limit 및 계정 잠금 정책 적용. 운영·구현 권장사항(간단 요약): - 모든 상태 전이는 원자적이어야 하며 동시성 경합을 막기 위해 DB 락 또는 CAS 사용. - idempotency 처리: 동일 승인 제출이 여러번 들어와도 안전하게 처리. - TTL과 시간 동기 허용 오차(예: 서버-앱 간 시차 30초) 정책 정의. - 서명 미사용 시 리스크 보정(더 짧은 TTL, 강한 attestation, 추가 인증 폴백). - 감사 로그는 비가역 저장소(immutable)로 보관하고, 관련 이벤트는 SIEM으로 전송. - 민감 RP의 경우 서버에서 추가 확인이 필요한 정책(예: 서명 필수, attestation 필수)을 강제. 간단한 의사 코드(pseudocode): ```pseudo // 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...