forked from baron/baron-sso
3.7 KiB
3.7 KiB
비밀번호 재설정 로직 분석 및 이슈 리포트
1. 전체 프로세스 흐름 (수정 후)
이메일 보안 스캐너(Link Scanner)로 인한 토큰 조기 만료 문제를 방지하기 위해 "중간 페이지(Interstitial Page)" 방식이 적용되었습니다.
-
초기화 요청 (Frontend -> Backend)
- 사용자가 아이디를 입력하고 비밀번호 재설정을 요청합니다.
- Backend는 Descope API를 호출하여 이메일을 발송합니다.
- 이때 리다이렉트 URL은 백엔드 API (
/api/v1/auth/password/reset/verify)로 설정됩니다.
-
이메일 수신 및 클릭 (User)
- 사용자가 이메일 내의 링크를 클릭합니다.
- URL 예시:
https://sso.hmac.kr/api/v1/auth/password/reset/verify?t=<TOKEN>
-
검증 대기 페이지 (Backend GET 처리)
- 보안 스캐너 방어: 백엔드가 GET 요청을 받으면 즉시 토큰을 검증하지 않습니다.
- 대신, 사용자가 직접 버튼을 클릭해야 하는 **HTML 페이지(폼)**를 반환합니다.
- 이유: Outlook, Gmail 등의 이메일 서버가 링크의 안전성을 확인하기 위해 미리 방문(GET)하여 일회성 토큰을 소모해버리는 것을 방지하기 위함입니다.
-
검증 실행 (User Click -> Backend POST)
- 사용자가 HTML 페이지의 "계속하기" 버튼을 클릭합니다.
POST요청이 백엔드로 전송됩니다.- 백엔드는 이때 Descope를 통해 토큰을 검증하고, 성공 시 **리프레시 토큰 쿠키(DSRF)**를 브라우저에 설정합니다.
- 이후 프론트엔드 페이지(
https://sso.hmac.kr/reset-password?loginId=...)로 리다이렉트합니다.
-
비밀번호 변경 (Frontend -> Backend)
- 프론트엔드는 URL 파라미터의
loginId와 사용자가 입력한새 비밀번호를 가지고 백엔드에 요청을 보냅니다. - 이때 4번 단계에서 설정된 쿠키가 함께 전송되어 인증된 상태로 비밀번호가 변경됩니다.
- 프론트엔드는 URL 파라미터의
2. 주요 사용 함수 (backend/internal/handler/auth_handler.go)
| 함수명 | HTTP Method | 역할 |
|---|---|---|
InitiatePasswordReset |
POST |
Descope에 비밀번호 재설정 이메일 발송을 요청하고 리다이렉트 URL을 백엔드로 지정합니다. |
VerifyPasswordResetPage |
GET |
토큰 검증 없이 사용자의 클릭을 유도하는 HTML 중간 페이지를 렌더링합니다. |
ProcessPasswordResetToken |
POST |
실제 Descope 토큰 검증을 수행하고 세션 쿠키를 생성한 뒤 프론트엔드로 이동시킵니다. |
CompletePasswordReset |
POST |
최종적으로 새 비밀번호를 업데이트합니다. (쿠키 기반 인증 필요) |
3. 비밀번호 변경이 안 되었던 원인
1) 토큰 조기 소모 (Token Expired / Invalid)
- 증상: 사용자가 링크를 클릭하자마자 "Invalid or expired token" 오류 발생.
- 원인: 회사 이메일 보안 시스템이 링크의 안전성을 검사하기 위해 사용자가 클릭하기 전 미리 방문(GET 요청)했습니다. Descope 토큰은 일회용이므로 스캐너 방문 시 이미 소모되어, 정작 사용자가 방문했을 때는 만료된 상태가 되었습니다.
- 해결:
GET은 페이지 로드만 수행하고, 사용자의 클릭(POST) 시에만 검증하도록 로직을 분리했습니다.
2) 파라미터 이름 불일치
- 증상:
missing_token오류 발생. - 원인: 백엔드는
token파라미터를 찾았으나, Descope는t라는 이름으로 토큰을 전달했습니다. - 해결:
token과t두 파라미터를 모두 확인하도록 수정했습니다.