diff --git a/docs/consent_reject_flow.md b/docs/consent_reject_flow.md new file mode 100644 index 00000000..9de1a0c9 --- /dev/null +++ b/docs/consent_reject_flow.md @@ -0,0 +1,62 @@ +# Consent 거부(Reject) 및 리다이렉트 흐름 상세 + +이 문서는 사용자가 권한 동의(Consent) 화면에서 '취소' 버튼을 클릭했을 때, 시스템이 어떻게 이를 처리하고 원래 로그인 시도를 했던 서비스(RP, 예: Gitea)로 되돌려보내는지에 대한 기술적 흐름을 설명합니다. + +## 전체 시퀀스 다이어그램 + +1. **사용자**: Consent 화면에서 '취소' 클릭 +2. **프론트엔드 (Flutter)**: 취소 확인 다이얼로그 표시 -> 확인 시 백엔드 API 호출 +3. **백엔드 (Go)**: Hydra Admin API 'Reject' 호출 +4. **Hydra**: 거부 처리 및 서비스(RP)로 돌아갈 리다이렉트 URL 생성 +5. **백엔드 (Go)**: Hydra가 준 URL을 프론트엔드에 전달 +6. **프론트엔드 (Flutter)**: 브라우저 주소를 해당 URL로 변경 (리다이렉트) +7. **서비스 (RP)**: 에러 파라미터를 수신하여 로그인 실패 처리 + +--- + +## 단계별 상세 흐름 및 관련 파일 + +### 1. 사용자 액션 및 확인 (프론트엔드 UI) +- **파일**: `userfront/lib/features/auth/presentation/consent_screen.dart` +- **로직**: `_onCancel()` 메서드가 실행됩니다. + - `showDialog`를 통해 사용자에게 정말 취소할 것인지 묻습니다. + - 사용자가 승인하면 `AuthProxyService.rejectConsent(widget.consentChallenge)`를 호출합니다. + +### 2. 백엔드 통신 (프론트엔드 서비스) +- **파일**: `userfront/lib/core/services/auth_proxy_service.dart` +- **로직**: `rejectConsent` 메서드가 백엔드의 `/api/v1/auth/consent/reject` 엔드포인트로 `POST` 요청을 보냅니다. 이때 `consent_challenge` 값이 바디에 포함됩니다. + +### 3. 거부 요청 접수 및 처리 (백엔드 핸들러) +- **파일**: `backend/internal/handler/auth_handler.go` +- **로직**: `RejectConsentRequest(c *fiber.Ctx)` 함수가 동작합니다. + - 프론트엔드에서 보낸 챌린지 코드를 추출합니다. + - `h.Hydra.RejectConsentRequest(ctx, challenge)`를 호출하여 실제 거부 로직을 서비스 레이어로 위임합니다. + +### 4. Hydra Admin API 호출 (백엔드 서비스) +- **파일**: `backend/internal/service/hydra_admin_service.go` +- **로직**: `RejectConsentRequest` 메서드가 실행됩니다. + - Ory Hydra의 Admin API인 `PUT /oauth2/auth/requests/consent/reject`를 호출합니다. + - 요청 바디에 `error: "access_denied"`와 설명을 포함하여 Hydra에게 사용자가 거부했음을 알립니다. + - **핵심**: Hydra는 이 요청을 받으면 해당 OAuth2 플로우를 에러 상태로 종료시키고, 서비스(Gitea 등)의 `redirect_uri`에 에러 정보를 붙인 최종 URL(`redirect_to`)을 응답으로 줍니다. + - 예: `https://gitea.com/callback?error=access_denied&error_description=...` + +### 5. 최종 리다이렉트 실행 (프론트엔드) +- **파일**: `userfront/lib/features/auth/presentation/consent_screen.dart` +- **로직**: 백엔드로부터 전달받은 `redirectTo` URL을 확인합니다. + - `webWindow.redirectTo(redirectTo)` (또는 `html.window.location.href`)를 호출하여 브라우저의 페이지를 이동시킵니다. + +### 6. 서비스(RP)의 수신 +- **결과**: 사용자는 Gitea 로그인 화면 또는 에러 페이지로 돌아가게 됩니다. +- URL에 포함된 `error=access_denied` 파라미터를 통해 Gitea는 "사용자가 동의를 거부하여 로그인이 취소됨"을 인지하고 적절한 안내 문구를 보여줍니다. + +--- + +## 요약 가이드 (참조 파일 목록) + +| 레이어 | 관련 파일 경로 | 주요 역할 | +| :--- | :--- | :--- | +| **UI** | `consent_screen.dart` | 취소 버튼 이벤트, 확인창 UI, 브라우저 주소 이동 | +| **API Client** | `auth_proxy_service.dart` | 백엔드 `/consent/reject` 호출 인터페이스 | +| **Handler** | `auth_handler.go` | HTTP 요청 수신, 서비스 레이어 호출 및 응답 반환 | +| **Service** | `hydra_admin_service.go` | Ory Hydra Admin API(`.../reject`)와 직접 통신 | +| **Router** | `backend/cmd/server/main.go` | `/api/v1/auth/consent/reject` 라우트 정의 |