forked from baron/baron-sso
8.4 KiB
8.4 KiB
Baron SSO 백엔드 인증 로직 상세 분석
Baron SSO 백엔드는 Descope IDP(Identity Provider)를 활용하여 사용자 인증 및 비밀번호 관리를 처리합니다. 주요 로직은 backend/internal/handler/auth_handler.go에 구현되어 있으며, Descope Go SDK를 통해 Descope API와 상호작용합니다.
4.1. 주요 컴포넌트
AuthHandler: Fiber 웹 프레임워크의 요청을 처리하는 핸들러.DescopeClient와IdpProvider(DescopeProvider 구현체)를 포함합니다.DescopeClient(github.com/descope/go-sdk/descope/client): Descope API와의 통신을 담당하는 SDK 클라이언트.IdpProvider(backend/internal/idp/factory.go->backend/internal/service/descope_service.go): DescopeClient를 래핑하여 Descope 관련 인증 작업을 추상화한 인터페이스.
4.2. 비밀번호 재설정 흐름 (Mermaid Diagram)
sequenceDiagram
participant Frontend
participant Backend as AuthHandler
participant Descope as Descope API
participant InternalServices as 이메일/SMS
Frontend->>AuthHandler: POST /api/v1/auth/password/reset/initiate (loginId)
AuthHandler->>AuthHandler: 비밀번호 재설정 시작 요청 유효성 검증
AuthHandler->>Descope: IdpProvider.InitiatePasswordReset(loginId, redirectURL)
note over Descope: Descope가 loginId로 재설정 링크 이메일 발송<br/>(링크는 백엔드의 /password/reset/verify를 가리킴)
Descope-->>AuthHandler: 성공 또는 오류 반환
alt 재설정 시작 성공 시
AuthHandler->>AuthHandler: 성공 로그 기록
AuthHandler-->>Frontend: 200 OK (비밀번호 재설정 링크가 성공적으로 전송되었습니다.)
else 재설정 시작 실패 시
AuthHandler->>AuthHandler: Descope 오류 로그 기록
AuthHandler-->>Frontend: 500 Internal Server Error (비밀번호 재설정 시작 실패)
end
User->>이메일/SMS: 재설정 링크 클릭
이메일/SMS->>Backend: GET /api/v1/auth/password/reset/verify?t={token} (브라우저 리다이렉트)
Backend->>Backend: 중간 HTML 페이지 제공 (POST 폼 포함)
Backend-->>Frontend: 200 OK (HTML 폼)
Frontend->>Backend: POST /api/v1/auth/password/reset/verify (폼에서 전달된 token)
Backend->>Backend: 폼 데이터에서 토큰 추출
Backend->>Descope: IdpProvider.VerifyPasswordResetToken(token)
Descope-->>Backend: 인증 정보 (세션/리프레시 토큰) 또는 오류 반환
alt 토큰 검증 성공 시
Backend->>Backend: 리프레시 토큰으로 DSRF 쿠키 설정
Backend->>Backend: JWT 페이로드에서 loginId 추출
Backend->>Frontend: /reset-password?loginId={loginId}로 리다이렉트
else 토큰 검증 실패 시 (예: 토큰 만료)
Backend->>Backend: Descope 오류 로그 기록
Backend->>Frontend: /login?error=invalid_token으로 리다이렉트
end
Frontend->>Backend: POST /api/v1/auth/password/reset/complete (loginId, newPassword)
Backend->>Backend: 요청 본문 및 비밀번호 정책 유효성 검증
Backend->>Descope: DescopeClient.Management.User().SetPassword(loginId, newPassword)
note over Descope: DESCOPE_MANAGEMENT_KEY 권한 필요
Descope-->>Backend: 성공 또는 오류 반환
alt 비밀번호 업데이트 성공 시
Backend->>Backend: 성공 로그 기록
Backend-->>Frontend: 200 OK (비밀번호가 성공적으로 재설정되었습니다.)
else 비밀번호 업데이트 실패 시
Backend->>Backend: Descope 오류 로그 기록 (예: 만료된 비밀번호, 정책 위반)
Backend-->>Frontend: 500 Internal Server Error (비밀번호 업데이트 실패)
end
4.3. 각 단계 동작 설명
이 섹션에서는 위 다이어그램에 나타난 주요 비밀번호 재설정 단계별 동작을 상세히 설명합니다.
1. POST /api/v1/auth/password/reset/initiate (비밀번호 재설정 시작)
- 요청: 프론트엔드에서 사용자
loginId를 포함하여 백엔드로 비밀번호 재설정 시작 요청을 보냅니다. - 백엔드 (
AuthHandler.InitiatePasswordReset):- 요청 본문(
loginId)의 유효성을 검사합니다. FRONTEND_URL환경 변수를 사용하여 Descope가 재설정 링크에 포함할redirectURL(백엔드의/api/v1/auth/password/reset/verify엔드포인트)을 구성합니다.h.IdpProvider.InitiatePasswordReset(loginId, redirectURL)메서드를 호출하여 Descope에 비밀번호 재설정 링크 발송을 위임합니다. (IdpProvider는 내부적으로DescopeClient.Auth.Password().SendResetPasswordLink()를 호출합니다.)
- 요청 본문(
- Descope API: Descope는 제공된
loginId에 해당하는 이메일 주소로 재설정 링크를 포함한 이메일을 발송합니다. 이 링크에는 사용자를redirectURL로 안내하고, 비밀번호 재설정 토큰이 포함됩니다. - 응답:
- 성공 시:
Password reset link sent successfully.메시지와 함께 200 OK 응답을 프론트엔드에 반환합니다. - 실패 시: Descope 오류를 로그로 기록하고 500 Internal Server Error 응답을 프론트엔드에 반환합니다.
- 성공 시:
2. GET /api/v1/auth/password/reset/verify (재설정 링크 클릭 후 중간 페이지)
- 요청: 사용자가 Descope가 보낸 재설정 이메일의 링크를 클릭하면, 브라우저는 이 백엔드 엔드포인트로
token쿼리 파라미터와 함께 GET 요청을 보냅니다. - 백엔드 (
AuthHandler.VerifyPasswordResetPage):- 링크 스캐너가 토큰을 소비하는 것을 방지하기 위한 중간 페이지를 HTML 형태로 반환합니다. 이 페이지에는
token을 숨긴 POST 폼이 포함되어 있습니다.
- 링크 스캐너가 토큰을 소비하는 것을 방지하기 위한 중간 페이지를 HTML 형태로 반환합니다. 이 페이지에는
- 응답: POST 폼이 포함된 HTML 페이지를 프론트엔드에 반환합니다.
3. POST /api/v1/auth/password/reset/verify (비밀번호 재설정 토큰 검증)
- 요청: 중간 페이지의 "계속하기" 버튼을 클릭하면 브라우저는 숨겨진
token을 포함하여 이 백엔드 엔드포인트로 POST 요청을 보냅니다. - 백엔드 (
AuthHandler.ProcessPasswordResetToken):- 폼 데이터에서
token을 추출합니다. h.IdpProvider.VerifyPasswordResetToken(token)메서드를 호출하여 Descope에 토큰 검증을 위임합니다. (내부적으로DescopeClient.Auth.MagicLink().Verify()또는 유사한 토큰 검증 API를 사용)
- 폼 데이터에서
- Descope API: 토큰의 유효성을 검증하고, 성공 시
AuthenticationInfo(세션/리프레시 토큰, 사용자 정보)를 반환하거나 실패 시 오류를 반환합니다. - 응답:
- 성공 시: Descope로부터 받은 리프레시 토큰을
DSRF쿠키로 설정하고, 세션 JWT에서loginId를 추출하여https://sso-test.hmac.kr/reset-password?loginId={loginId}URL로 프론트엔드에 리다이렉트합니다. - 실패 시: Descope 오류를 로그로 기록하고
https://sso-test.hmac.kr/login?error=invalid_tokenURL로 프론트엔드에 리다이렉트합니다.
- 성공 시: Descope로부터 받은 리프레시 토큰을
4. POST /api/v1/auth/password/reset/complete (비밀번호 재설정 완료)
- 요청: 프론트엔드 (리다이렉트된
/reset-password페이지)에서 새로운newPassword와loginId를 포함하여 백엔드로 비밀번호 재설정 완료 요청을 보냅니다. - 백엔드 (
AuthHandler.CompletePasswordReset):- 요청 본문(
newPassword)과 쿼리 파라미터(loginId)의 유효성을 검사합니다. - 비밀번호 정책(길이, 문자 포함)을 직접 검증합니다.
h.DescopeClient.Management.User().SetPassword(context.Background(), loginID, req.NewPassword)메서드를 호출하여 Descope에 비밀번호 업데이트를 위임합니다. 이때DESCOPE_MANAGEMENT_KEY의 권한이 매우 중요합니다.
- 요청 본문(
- Descope API: Descope는
loginId에 해당하는 사용자의 비밀번호를newPassword로 업데이트합니다. 이 과정에서 Descope의 비밀번호 정책 및 계정 상태(예: 만료)가 적용됩니다. - 응답:
- 성공 시:
Password has been reset successfully.메시지와 함께 200 OK 응답을 프론트엔드에 반환합니다. - 실패 시: Descope 오류를 로그로 기록하고 500 Internal Server Error 응답을 프론트엔드에 반환합니다. 현재
Expired password오류가 발생한 지점입니다.
- 성공 시: