# 클라이언트 비활성화(Deactivation) 및 로그인 차단 흐름

이 문서는 관리자가 개발자 포털(`devfront`)에서 특정 클라이언트(RP)를 비활성화했을 때, 해당 앱을 통한 인증 시도가 어떻게 차단되는지 상세 기술 흐름을 설명합니다.

## 1. 개요
보안 사고나 점검 등의 사유로 특정 애플리케이션의 접근을 즉시 차단해야 할 경우, 관리자는 클라이언트 목록에서 '상태' 토글을 비활성화할 수 있습니다. 이 설정은 Ory Hydra의 클라이언트 메타데이터에 저장되며, Baron SSO 백엔드 인증 핸들러에서 이를 검증하여 차단을 수행합니다.

## 2. 전체 동작 흐름

```mermaid
sequenceDiagram
    participant Admin as 관리자 (DevFront)
    participant Backend as 백엔드 (API)
    participant Hydra as Ory Hydra (OIDC 엔진)
    participant User as 사용자
    participant RP as 애플리케이션 (예: Gitea)

    Note over Admin, Hydra: [1단계: 클라이언트 비활성화 설정]
    Admin->>Admin: 상태 스위치 클릭 (활성 -> 비활성)
    Admin->>Backend: PATCH /api/v1/dev/clients/{id}/status {status: "inactive"}
    Backend->>Hydra: PATCH /admin/clients/{id} (JSON Patch 형식)
    Hydra-->>Backend: 업데이트 완료 (metadata.status = "inactive")
    Backend-->>Admin: 성공 알림

    Note over User, Backend: [2단계: 로그인 시도 및 차단]
    User->>RP: 로그인 시도 (Baron SSO 선택)
    RP->>Hydra: 인증 요청 (/oauth2/auth)
    Hydra->>User: 로그인 페이지로 리디렉션 (login_challenge 포함)
    User->>Backend: 아이디/비밀번호 입력 및 로그인 요청
    Backend->>Hydra: GetLoginRequest(challenge) 호출
    Hydra-->>Backend: 클라이언트 정보 응답 (Metadata 포함)
    
    Note right of Backend: 비활성 체크 로직 작동
    Backend->>Backend: Metadata["status"] == "inactive" 확인
    
    alt 비활성화 상태인 경우
        Backend-->>User: 403 Forbidden (비활성화된 앱 안내)
        Note over User: 로그인 프로세스 중단
    else 활성화 상태인 경우
        Backend->>Hydra: AcceptLoginRequest
        Hydra-->>User: 동의 화면 또는 RP로 리디렉션
    end
```

## 3. 상세 구현 내용

### 3.1. 관리자 UI 및 상태 변경
- **파일**: `devfront/src/features/clients/ClientsPage.tsx`
- **함수**: `updateStatusMutation`
- **로직**: 사용자가 스위치를 토글하면 `updateClientStatus` API를 호출합니다. 업데이트 중에는 중복 클릭을 방지하기 위해 스위치가 `disabled` 상태가 됩니다.

### 3.2. 백엔드 상태 업데이트 중계
- **파일**: `backend/internal/handler/dev_handler.go`
- **함수**: `UpdateClientStatus`
- **로직**: 클라이언트 ID와 변경할 상태값을 받아 `service.HydraAdminService`의 `PatchClientStatus`를 호출합니다.
- **파일**: `backend/internal/service/hydra_admin_service.go`
- **함수**: `PatchClientStatus`
- **로직**: Ory Hydra Admin API 규격에 맞춰 **JSON Patch(RFC 6902)** 형식을 생성합니다.
    ```go
    payload := []map[string]interface{}{
        {"op": "replace", "path": "/metadata/status", "value": status},
    }
    ```

### 3.3. 인증 단계별 차단 검증 (핵심 보안 로직)
백엔드는 OIDC 인증 흐름의 3가지 주요 진입점에서 클라이언트의 활성 상태를 매번 체크합니다.

#### 1) 수동 로그인 시 (`PasswordLogin`)
- **파일**: `backend/internal/handler/auth_handler.go`
- **로직**: 사용자가 직접 아이디/비밀번호를 입력했을 때, `login_challenge`가 있다면 Hydra에 해당 클라이언트 정보를 조회하여 `metadata.status`가 `inactive`인지 확인합니다.

#### 2) 자동 로그인 시 (`AcceptOidcLoginRequest`)
- **파일**: `backend/internal/handler/auth_handler.go`
- **로직**: 사용자가 이미 SSO 세션을 가지고 있어 자동으로 로그인이 진행될 때 호출됩니다. 승인(Accept)을 보내기 직전에 클라이언트 상태를 체크하여 차단합니다.

#### 3) 동의 화면 진입 시 (`GetConsentRequest`)
- **파일**: `backend/internal/handler/auth_handler.go`
- **로직**: 로그인 후 권한 동의 화면을 그리기 위해 정보를 가져오는 시점입니다. 비활성화된 앱이라면 정보를 반환하지 않고 에러를 발생시킵니다.

## 4. 예외 및 에러 처리
- 클라이언트가 비활성화된 경우 백엔드는 `403 Forbidden` 상태 코드와 함께 `"The client application is disabled."` 메시지를 반환합니다.
- 백엔드 로그에는 `slog.Warn`을 통해 `"Login rejected for inactive client"` 메시지가 기록되어 관리자가 시도 이력을 추적할 수 있습니다.

## 5. 확인 방법 (테스트 시나리오)
1. `devfront`에서 특정 앱의 스위치를 끕니다.
2. 해당 앱에서 로그인을 시도합니다.
3. 이미 로그인된 상태여도 리디렉션 과정에서 "비활성화된 애플리케이션입니다"라는 안내와 함께 차단되는지 확인합니다.
4. 백엔드 로그에서 차단 기록을 확인합니다:
   ```bash
   docker compose logs -f backend | grep "inactive client"
   ```
