# Baron SSO 권한 선택 및 동적 스코프(Scope) 처리 흐름

이 문서는 사용자가 Consent(권한 동의) 화면에서 특정 권한(Scope)을 선택하고, 그 선택된 권한들이 어떻게 백엔드와 Ory Hydra로 전달되어 처리되는지에 대한 구현 상세를 설명합니다. 또한, 개발자 포털(`devfront`)에서 설정한 권한별 설명이 어떻게 화면에 동적으로 표시되는지 설명합니다.

## 1. 개요

사용자 중심의 개인정보 제어를 위해 다음과 같은 기능이 구현되었습니다.

1.  **권한 선택**: 사용자는 필수(Mandatory)가 아닌 권한을 직접 선택하거나 해제할 수 있습니다.
2.  **동적 설명**: 개발자 포털에서 설정한 각 권한에 대한 사용자 친화적인 설명(한글 등)이 Consent 화면에 표시됩니다.
3.  **필수 권한 보장**: `openid`와 같이 서비스 동작에 필수적인 권한은 선택 해제가 불가능합니다.

## 2. 데이터 흐름 (Data Flow)

### Step 1: Consent 정보 조회 (`GET /consent`)

사용자가 `/consent` 페이지에 진입하면, 프론트엔드는 백엔드에 상세 정보를 요청합니다.

1.  **Frontend (`userfront`)**: `AuthProxyService.getConsentInfo(challenge)` 호출.
2.  **Backend (`backend`)**: `AuthHandler.GetConsentRequest` 핸들러 실행.
    *   Hydra Admin API를 호출하여 Consent Request 정보(요청된 스코프, 클라이언트 정보 등)를 가져옵니다.
    *   **핵심 로직**: Hydra Client의 `Metadata` 필드 내 `structured_scopes`를 파싱합니다.
    *   파싱된 정보를 바탕으로 `scope_details` 객체(설명, 필수 여부 포함)를 생성하여 응답에 추가합니다.

```json
// 백엔드 응답 예시
{
  "challenge": "...",
  "requested_scope": ["openid", "profile", "email"],
  "scope_details": {
    "openid": { "description": "인증 필수 정보", "mandatory": true },
    "profile": { "description": "프로필 정보", "mandatory": false }
  },
  ...
}
```

### Step 2: UI 렌더링 및 사용자 선택

1.  **Frontend (`userfront`)**: `ConsentScreen` 위젯 렌더링.
    *   백엔드에서 받은 `requested_scope` 목록을 순회하며 체크박스를 생성합니다.
    *   `scope_details`에 있는 설명을 우선적으로 표시합니다.
    *   `mandatory: true`인 스코프(예: `openid`)는 체크박스를 비활성화(선택 고정)합니다.
    *   사용자는 나머지 선택 가능한 스코프를 체크하거나 해제합니다.

### Step 3: 동의 처리 (`POST /consent/accept`)

사용자가 "동의하고 계속하기" 버튼을 클릭하면, **선택된 스코프 목록만** 백엔드로 전송됩니다.

1.  **Frontend (`userfront`)**: `AuthProxyService.acceptConsent(challenge, grantScope: [...])` 호출.
    *   `grant_scope` 파라미터에 사용자가 최종적으로 선택한 스코프 배열을 담아 보냅니다.

2.  **Backend (`backend`)**: `AuthHandler.AcceptConsentRequest` 핸들러 실행.
    *   요청 바디에서 `grant_scope`를 추출합니다.
    *   보안을 위해, 사용자가 보낸 `grant_scope`가 원래 요청된(requested) 스코프에 포함되는지 검증합니다.
    *   검증된 스코프 목록을 Hydra의 `AcceptConsentRequest` 페이로드(`grant_scope`)에 담아 호출합니다.

3.  **Hydra**:
    *   전달받은 `grant_scope`만을 포함한 Access Token 및 ID Token을 생성할 준비를 하고, 최종 리다이렉트 URL을 반환합니다.

## 3. 파일별 구현 상세

### 1. Backend (`backend/internal/handler/auth_handler.go`)

*   **`GetConsentRequest`**:
    *   Hydra Client의 Metadata(`structured_scopes`)를 읽어 `scope_details`를 응답에 주입하는 로직이 추가되었습니다.
*   **`AcceptConsentRequest`**:
    *   요청 바디 구조체에 `GrantScope []string` 필드를 추가했습니다.
    *   Hydra API 호출 시 `RequestedScope` 필드를 사용자가 선택한 스코프로 덮어씌워 전달합니다.

### 2. Frontend (`userfront/lib/features/auth/presentation/consent_screen.dart`)

*   **`_fetchConsentInfo`**:
    *   API 응답의 `scope_details`를 파싱하여 `_scopeDescriptions`와 `_mandatoryScopes` 상태를 동적으로 업데이트합니다.
*   **`_acceptConsent`**:
    *   사용자가 체크한 `_selectedScopes`를 리스트로 변환하여 API 호출 시 전달합니다.
*   **UI**:
    *   `CheckboxListTile`을 사용하여 각 권한별 선택 UI를 구성했습니다.

### 3. Frontend Service (`userfront/lib/core/services/auth_proxy_service.dart`)

*   **`acceptConsent`**:
    *   `List<String>? grantScope` 파라미터를 추가하고, API 요청 바디에 포함시키는 기능을 구현했습니다.

## 4. 메타데이터 구조 (참고)

개발자 포털(`devfront`)에서 설정된 스코프 메타데이터는 Hydra Client의 `metadata` 필드에 다음과 같이 저장됩니다.

```json
{
  "metadata": {
    "structured_scopes": [
      {
        "id": "1",
        "name": "openid",
        "description": "서비스 이용을 위한 필수 인증 정보입니다.",
        "mandatory": true
      },
      {
        "id": "2",
        "name": "email",
        "description": "이메일 알림을 받기 위해 필요합니다.",
        "mandatory": false
      }
    ]
  }
}
```

백엔드는 이 정보를 읽어서 Consent 화면에 필요한 정보로 가공하여 전달합니다.
