1
0
forked from baron/baron-sso
Files
baron-sso/backend_architecture.md

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 웹 프레임워크의 요청을 처리하는 핸들러. DescopeClientIdpProvider (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 폼이 포함되어 있습니다.
  • 응답: 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_token URL로 프론트엔드에 리다이렉트합니다.

4. POST /api/v1/auth/password/reset/complete (비밀번호 재설정 완료)

  • 요청: 프론트엔드 (리다이렉트된 /reset-password 페이지)에서 새로운 newPasswordloginId를 포함하여 백엔드로 비밀번호 재설정 완료 요청을 보냅니다.
  • 백엔드 (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 오류가 발생한 지점입니다.