- FastAPI 백엔드 + MongoDB + Redis 구성 - React + Vite + TypeScript + shadcn/ui 프론트엔드 - Apache APISIX API Gateway 통합 - Docker Compose 기반 개발 환경 - 3단계 권한 체계 (System Admin, Group Admin, User) - 동적 테마 지원 - 환경별 설정 (dev/vei/prod) 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
349 lines
6.0 KiB
Markdown
349 lines
6.0 KiB
Markdown
# OAuth API 명세서
|
|
|
|
## Base URL
|
|
- Development: `http://localhost:8000/api/v1`
|
|
- Verification: `https://vei-oauth-api.example.com/api/v1`
|
|
- Production: `https://api-oauth.example.com/api/v1`
|
|
|
|
## 인증 헤더
|
|
```
|
|
Authorization: Bearer {access_token}
|
|
```
|
|
|
|
## API 엔드포인트
|
|
|
|
### 인증 (Authentication)
|
|
|
|
#### POST /auth/login
|
|
사용자 로그인
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"access_token": "eyJ...",
|
|
"refresh_token": "eyJ...",
|
|
"token_type": "bearer",
|
|
"expires_in": 1800
|
|
}
|
|
```
|
|
|
|
#### POST /auth/logout
|
|
사용자 로그아웃
|
|
|
|
**Headers:**
|
|
- Authorization: Bearer {access_token}
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Successfully logged out"
|
|
}
|
|
```
|
|
|
|
#### POST /auth/refresh
|
|
토큰 갱신
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"refresh_token": "eyJ..."
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"access_token": "eyJ...",
|
|
"token_type": "bearer",
|
|
"expires_in": 1800
|
|
}
|
|
```
|
|
|
|
#### POST /auth/authorize
|
|
OAuth 인증 요청
|
|
|
|
**Query Parameters:**
|
|
- `response_type`: "code"
|
|
- `client_id`: Application Client ID
|
|
- `redirect_uri`: Redirect URI
|
|
- `scope`: 요청 권한 (space 구분)
|
|
- `state`: CSRF 방지용 상태값
|
|
|
|
**Response:**
|
|
- 302 Redirect to `{redirect_uri}?code={auth_code}&state={state}`
|
|
|
|
#### POST /auth/token
|
|
Access Token 발급
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"grant_type": "authorization_code",
|
|
"code": "auth_code",
|
|
"client_id": "client_id",
|
|
"client_secret": "client_secret",
|
|
"redirect_uri": "redirect_uri"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"access_token": "eyJ...",
|
|
"refresh_token": "eyJ...",
|
|
"token_type": "bearer",
|
|
"expires_in": 1800,
|
|
"scope": "read write"
|
|
}
|
|
```
|
|
|
|
### 사용자 관리 (Users)
|
|
|
|
#### GET /users/me
|
|
현재 사용자 정보 조회
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "user_id",
|
|
"email": "user@example.com",
|
|
"username": "username",
|
|
"full_name": "John Doe",
|
|
"role": "user",
|
|
"profile_picture": "https://...",
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"last_login": "2024-01-01T00:00:00Z"
|
|
}
|
|
```
|
|
|
|
#### PUT /users/me
|
|
사용자 정보 수정
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"full_name": "Jane Doe",
|
|
"phone_number": "+1234567890",
|
|
"birth_date": "1990-01-01",
|
|
"gender": "female"
|
|
}
|
|
```
|
|
|
|
#### POST /users/me/password
|
|
패스워드 변경
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"current_password": "old_password",
|
|
"new_password": "new_password"
|
|
}
|
|
```
|
|
|
|
#### POST /users/me/profile-picture
|
|
프로필 사진 업로드
|
|
|
|
**Request:**
|
|
- Content-Type: multipart/form-data
|
|
- File: image file
|
|
|
|
#### GET /users/me/permissions
|
|
사용자 권한 조회
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"single_sign_on": true,
|
|
"share_name": true,
|
|
"share_gender": false,
|
|
"share_birth_date": false,
|
|
"share_email": true,
|
|
"share_phone": false
|
|
}
|
|
```
|
|
|
|
#### PUT /users/me/permissions
|
|
사용자 권한 수정
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"share_gender": true,
|
|
"share_birth_date": true
|
|
}
|
|
```
|
|
|
|
#### GET /users/me/applications
|
|
인증된 애플리케이션 목록
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"applications": [
|
|
{
|
|
"id": "app_id",
|
|
"name": "Application Name",
|
|
"logo_url": "https://...",
|
|
"authorized_at": "2024-01-01T00:00:00Z",
|
|
"last_used": "2024-01-01T00:00:00Z",
|
|
"permissions": ["read", "write"]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### DELETE /users/me/applications/{app_id}
|
|
애플리케이션 인증 해제
|
|
|
|
### 애플리케이션 관리 (Applications)
|
|
|
|
#### GET /applications
|
|
애플리케이션 목록 조회 (Admin only)
|
|
|
|
#### POST /applications
|
|
애플리케이션 등록 (Admin only)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"app_name": "My Application",
|
|
"description": "Application description",
|
|
"redirect_uris": ["https://app.example.com/callback"],
|
|
"allowed_origins": ["https://app.example.com"],
|
|
"theme": {
|
|
"primary_color": "#1976d2",
|
|
"secondary_color": "#dc004e",
|
|
"logo_url": "https://...",
|
|
"background_image_url": "https://..."
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "app_id",
|
|
"client_id": "generated_client_id",
|
|
"client_secret": "generated_client_secret",
|
|
"app_name": "My Application",
|
|
"created_at": "2024-01-01T00:00:00Z"
|
|
}
|
|
```
|
|
|
|
#### GET /applications/{app_id}
|
|
애플리케이션 상세 조회
|
|
|
|
#### PUT /applications/{app_id}
|
|
애플리케이션 수정 (Admin only)
|
|
|
|
#### DELETE /applications/{app_id}
|
|
애플리케이션 삭제 (Admin only)
|
|
|
|
#### POST /applications/{app_id}/regenerate-secret
|
|
Client Secret 재생성 (Admin only)
|
|
|
|
### 관리자 (Admin)
|
|
|
|
#### GET /admin/users
|
|
전체 사용자 목록 (System Admin only)
|
|
|
|
**Query Parameters:**
|
|
- `page`: 페이지 번호 (default: 1)
|
|
- `limit`: 페이지당 항목 수 (default: 20)
|
|
- `role`: 역할 필터
|
|
- `search`: 검색어
|
|
|
|
#### GET /admin/users/{user_id}
|
|
사용자 상세 조회 (Admin only)
|
|
|
|
#### PUT /admin/users/{user_id}/role
|
|
사용자 역할 변경 (System Admin only)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"role": "group_admin"
|
|
}
|
|
```
|
|
|
|
#### GET /admin/audit-logs
|
|
감사 로그 조회 (Admin only)
|
|
|
|
**Query Parameters:**
|
|
- `user_id`: 사용자 ID
|
|
- `app_id`: 애플리케이션 ID
|
|
- `action`: 액션 타입
|
|
- `start_date`: 시작일
|
|
- `end_date`: 종료일
|
|
|
|
#### GET /admin/statistics
|
|
통계 정보 조회 (Admin only)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"total_users": 1000,
|
|
"active_users_today": 150,
|
|
"total_applications": 25,
|
|
"total_authentications_today": 5000,
|
|
"top_applications": [...]
|
|
}
|
|
```
|
|
|
|
## 에러 응답
|
|
|
|
### 에러 응답 형식
|
|
```json
|
|
{
|
|
"error": "error_code",
|
|
"message": "Error message",
|
|
"details": {}
|
|
}
|
|
```
|
|
|
|
### 에러 코드
|
|
- `400`: Bad Request
|
|
- `401`: Unauthorized
|
|
- `403`: Forbidden
|
|
- `404`: Not Found
|
|
- `409`: Conflict
|
|
- `422`: Unprocessable Entity
|
|
- `429`: Too Many Requests
|
|
- `500`: Internal Server Error
|
|
|
|
## Rate Limiting
|
|
- 일반 API: 100 requests/minute
|
|
- 인증 API: 10 requests/minute
|
|
- 관리자 API: 1000 requests/minute
|
|
|
|
## Webhooks
|
|
|
|
### 이벤트 타입
|
|
- `user.created`
|
|
- `user.updated`
|
|
- `user.deleted`
|
|
- `user.login`
|
|
- `user.logout`
|
|
- `application.authorized`
|
|
- `application.revoked`
|
|
|
|
### Webhook 페이로드
|
|
```json
|
|
{
|
|
"event": "user.login",
|
|
"timestamp": "2024-01-01T00:00:00Z",
|
|
"data": {
|
|
"user_id": "user_id",
|
|
"application_id": "app_id",
|
|
"ip_address": "192.168.1.1"
|
|
}
|
|
}
|
|
``` |