From 9168a5f734184fee4df183ed2d9def1b5a3f9a25 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Mon, 12 Jan 2026 16:59:06 +0700 Subject: [PATCH] feat(docs): Update authentication flow documentation and improve clarity - Revised IAM service documentation to reflect recent changes in the authentication flow, including user registration and token management. - Enhanced API documentation with clearer examples and updated architecture diagrams for better understanding. - Added comprehensive sections on OAuth2 grant types and user management to assist developers. - Streamlined Vietnamese documentation for consistency and improved accessibility. --- docs/en/guides/iam-authentication.md | 237 +++++++++++++++++++++++++++ docs/vi/guides/iam-authentication.md | 237 +++++++++++++++++++++++++++ 2 files changed, 474 insertions(+) create mode 100644 docs/en/guides/iam-authentication.md create mode 100644 docs/vi/guides/iam-authentication.md diff --git a/docs/en/guides/iam-authentication.md b/docs/en/guides/iam-authentication.md new file mode 100644 index 00000000..e0f1a98c --- /dev/null +++ b/docs/en/guides/iam-authentication.md @@ -0,0 +1,237 @@ +# IAM Service Authentication Guide + +> Complete guide for authentication using GoodGo IAM Service with OAuth2/OpenID Connect. + +## Overview + +The IAM Service provides OAuth2/OIDC authentication using OpenIddict: +- **Password Grant** - User login with email/password +- **Refresh Token** - Token renewal without re-authentication +- **Client Credentials** - Service-to-service authentication + +## Quick Start + +### 1. Register a User + +```bash +curl -X POST http://localhost:5001/api/v1/auth/register \ + -H "Content-Type: application/json" \ + -d '{ + "email": "user@example.com", + "password": "Password123!", + "firstName": "John", + "lastName": "Doe" + }' +``` + +### 2. Login (Get Tokens) + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "username=user@example.com" \ + -d "password=Password123!" \ + -d "scope=openid profile email offline_access" +``` + +**Response:** +```json +{ + "access_token": "eyJhbGciOiJSUzI1NiIs...", + "token_type": "Bearer", + "expires_in": 900, + "refresh_token": "eyJhbGciOiJSUzI1NiIs...", + "scope": "openid profile email offline_access" +} +``` + +### 3. Use Access Token + +```bash +curl http://localhost:5001/api/v1/users/me \ + -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." +``` + +## OAuth2 Grant Types + +### Password Grant (User Login) + +For trusted first-party applications where users enter credentials directly. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "username=user@example.com" \ + -d "password=Password123!" \ + -d "scope=openid profile email offline_access" +``` + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `grant_type` | Yes | Must be `password` | +| `username` | Yes | User's email | +| `password` | Yes | User's password | +| `scope` | No | Space-separated scopes | + +### Refresh Token + +Renew access token without re-entering credentials. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=refresh_token" \ + -d "refresh_token=eyJhbGciOiJSUzI1NiIs..." +``` + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `grant_type` | Yes | Must be `refresh_token` | +| `refresh_token` | Yes | Valid refresh token | + +### Client Credentials (Service-to-Service) + +For backend services authenticating without user context. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=goodgo-service" \ + -d "client_secret=service-secret" \ + -d "scope=api" +``` + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `grant_type` | Yes | Must be `client_credentials` | +| `client_id` | Yes | Registered client ID | +| `client_secret` | Yes | Client secret | +| `scope` | No | Requested scopes | + +> **Note:** Client applications must be registered in the database before use. + +## Token Lifetimes + +| Token Type | Lifetime | Use | +|------------|----------|-----| +| Access Token | 15 minutes | API authorization | +| Refresh Token | 7 days | Token renewal | + +## Available Scopes + +| Scope | Description | +|-------|-------------| +| `openid` | Required for OIDC | +| `profile` | User profile (name) | +| `email` | User email | +| `roles` | User roles | +| `offline_access` | Get refresh token | +| `api` | API access | + +## API Endpoints + +### Authentication + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `POST` | `/api/v1/auth/register` | Register new user | +| `POST` | `/connect/token` | OAuth2 token endpoint | +| `POST` | `/api/v1/auth/change-password` | Change password (auth required) | +| `POST` | `/api/v1/auth/logout` | Revoke tokens (auth required) | + +### User Management + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/api/v1/users` | List users (paginated) | +| `GET` | `/api/v1/users/me` | Current user info | +| `GET` | `/api/v1/users/{id}` | Get user by ID | +| `PUT` | `/api/v1/users/{id}` | Update user | +| `DELETE` | `/api/v1/users/{id}` | Delete user (soft) | + +## Integration Examples + +### JavaScript/TypeScript + +```typescript +// Login +const response = await fetch('http://localhost:5001/connect/token', { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'password', + username: 'user@example.com', + password: 'Password123!', + scope: 'openid profile email offline_access' + }) +}); +const { access_token, refresh_token } = await response.json(); + +// Use token +const user = await fetch('http://localhost:5001/api/v1/users/me', { + headers: { 'Authorization': `Bearer ${access_token}` } +}).then(r => r.json()); +``` + +### C# / .NET + +```csharp +// Login +var client = new HttpClient(); +var content = new FormUrlEncodedContent(new Dictionary +{ + ["grant_type"] = "password", + ["username"] = "user@example.com", + ["password"] = "Password123!", + ["scope"] = "openid profile email offline_access" +}); +var response = await client.PostAsync("http://localhost:5001/connect/token", content); +var tokens = await response.Content.ReadFromJsonAsync(); + +// Use token +client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", tokens.AccessToken); +var user = await client.GetFromJsonAsync("/api/v1/users/me"); +``` + +## Error Responses + +### Common Errors + +| Error | HTTP Code | Description | +|-------|-----------|-------------| +| `invalid_grant` | 400 | Invalid credentials | +| `invalid_client` | 400 | Unknown client_id | +| `invalid_scope` | 400 | Invalid scope requested | +| `unauthorized` | 401 | Invalid/expired token | + +### Error Response Format + +```json +{ + "error": "invalid_grant", + "error_description": "The username or password is incorrect." +} +``` + +## Security Best Practices + +1. **Store tokens securely** - Use httpOnly cookies or secure storage +2. **Refresh tokens proactively** - Before access token expires +3. **Use HTTPS in production** - Never send credentials over HTTP +4. **Logout properly** - Call logout endpoint to revoke tokens +5. **Validate tokens server-side** - Don't trust client-side validation + +## Swagger UI + +Access interactive API documentation: +- **Local**: http://localhost:5001/swagger + +## Related Documentation + +- [IAM Migration Guide](./iam-migration.md) +- [Local Development](./local-development.md) +- [Security Architecture](../architecture/security-architecture.md) diff --git a/docs/vi/guides/iam-authentication.md b/docs/vi/guides/iam-authentication.md new file mode 100644 index 00000000..07b46371 --- /dev/null +++ b/docs/vi/guides/iam-authentication.md @@ -0,0 +1,237 @@ +# Hướng Dẫn Xác Thực IAM Service + +> Hướng dẫn đầy đủ về xác thực sử dụng GoodGo IAM Service với OAuth2/OpenID Connect. + +## Tổng Quan + +IAM Service cung cấp xác thực OAuth2/OIDC sử dụng OpenIddict: +- **Password Grant** - Đăng nhập user với email/password +- **Refresh Token** - Làm mới token mà không cần xác thực lại +- **Client Credentials** - Xác thực service-to-service + +## Bắt Đầu Nhanh + +### 1. Đăng Ký User + +```bash +curl -X POST http://localhost:5001/api/v1/auth/register \ + -H "Content-Type: application/json" \ + -d '{ + "email": "user@example.com", + "password": "Password123!", + "firstName": "John", + "lastName": "Doe" + }' +``` + +### 2. Đăng Nhập (Lấy Tokens) + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "username=user@example.com" \ + -d "password=Password123!" \ + -d "scope=openid profile email offline_access" +``` + +**Response:** +```json +{ + "access_token": "eyJhbGciOiJSUzI1NiIs...", + "token_type": "Bearer", + "expires_in": 900, + "refresh_token": "eyJhbGciOiJSUzI1NiIs...", + "scope": "openid profile email offline_access" +} +``` + +### 3. Sử Dụng Access Token + +```bash +curl http://localhost:5001/api/v1/users/me \ + -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." +``` + +## Các Loại OAuth2 Grant + +### Password Grant (Đăng Nhập User) + +Cho các ứng dụng đáng tin cậy nơi users nhập thông tin đăng nhập trực tiếp. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "username=user@example.com" \ + -d "password=Password123!" \ + -d "scope=openid profile email offline_access" +``` + +| Tham số | Bắt buộc | Mô tả | +|---------|----------|-------| +| `grant_type` | Có | Phải là `password` | +| `username` | Có | Email của user | +| `password` | Có | Mật khẩu của user | +| `scope` | Không | Các scopes cách nhau bằng dấu cách | + +### Refresh Token + +Làm mới access token mà không cần nhập lại thông tin đăng nhập. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=refresh_token" \ + -d "refresh_token=eyJhbGciOiJSUzI1NiIs..." +``` + +| Tham số | Bắt buộc | Mô tả | +|---------|----------|-------| +| `grant_type` | Có | Phải là `refresh_token` | +| `refresh_token` | Có | Refresh token hợp lệ | + +### Client Credentials (Service-to-Service) + +Cho các backend services xác thực mà không cần user context. + +```bash +curl -X POST http://localhost:5001/connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=goodgo-service" \ + -d "client_secret=service-secret" \ + -d "scope=api" +``` + +| Tham số | Bắt buộc | Mô tả | +|---------|----------|-------| +| `grant_type` | Có | Phải là `client_credentials` | +| `client_id` | Có | Client ID đã đăng ký | +| `client_secret` | Có | Client secret | +| `scope` | Không | Các scopes yêu cầu | + +> **Lưu ý:** Client applications phải được đăng ký trong database trước khi sử dụng. + +## Thời Hạn Token + +| Loại Token | Thời hạn | Sử dụng | +|------------|----------|---------| +| Access Token | 15 phút | API authorization | +| Refresh Token | 7 ngày | Làm mới token | + +## Các Scopes Hỗ Trợ + +| Scope | Mô tả | +|-------|-------| +| `openid` | Bắt buộc cho OIDC | +| `profile` | Thông tin profile (tên) | +| `email` | Email của user | +| `roles` | Các roles của user | +| `offline_access` | Nhận refresh token | +| `api` | Truy cập API | + +## API Endpoints + +### Xác Thực + +| Method | Endpoint | Mô tả | +|--------|----------|-------| +| `POST` | `/api/v1/auth/register` | Đăng ký user mới | +| `POST` | `/connect/token` | OAuth2 token endpoint | +| `POST` | `/api/v1/auth/change-password` | Đổi mật khẩu (cần auth) | +| `POST` | `/api/v1/auth/logout` | Thu hồi tokens (cần auth) | + +### Quản Lý User + +| Method | Endpoint | Mô tả | +|--------|----------|-------| +| `GET` | `/api/v1/users` | Danh sách users (phân trang) | +| `GET` | `/api/v1/users/me` | Thông tin user hiện tại | +| `GET` | `/api/v1/users/{id}` | Lấy user theo ID | +| `PUT` | `/api/v1/users/{id}` | Cập nhật user | +| `DELETE` | `/api/v1/users/{id}` | Xóa user (soft) | + +## Ví Dụ Tích Hợp + +### JavaScript/TypeScript + +```typescript +// Đăng nhập +const response = await fetch('http://localhost:5001/connect/token', { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'password', + username: 'user@example.com', + password: 'Password123!', + scope: 'openid profile email offline_access' + }) +}); +const { access_token, refresh_token } = await response.json(); + +// Sử dụng token +const user = await fetch('http://localhost:5001/api/v1/users/me', { + headers: { 'Authorization': `Bearer ${access_token}` } +}).then(r => r.json()); +``` + +### C# / .NET + +```csharp +// Đăng nhập +var client = new HttpClient(); +var content = new FormUrlEncodedContent(new Dictionary +{ + ["grant_type"] = "password", + ["username"] = "user@example.com", + ["password"] = "Password123!", + ["scope"] = "openid profile email offline_access" +}); +var response = await client.PostAsync("http://localhost:5001/connect/token", content); +var tokens = await response.Content.ReadFromJsonAsync(); + +// Sử dụng token +client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", tokens.AccessToken); +var user = await client.GetFromJsonAsync("/api/v1/users/me"); +``` + +## Xử Lý Lỗi + +### Các Lỗi Thường Gặp + +| Lỗi | HTTP Code | Mô tả | +|-----|-----------|-------| +| `invalid_grant` | 400 | Thông tin đăng nhập không hợp lệ | +| `invalid_client` | 400 | client_id không xác định | +| `invalid_scope` | 400 | Scope yêu cầu không hợp lệ | +| `unauthorized` | 401 | Token không hợp lệ/hết hạn | + +### Định Dạng Lỗi + +```json +{ + "error": "invalid_grant", + "error_description": "The username or password is incorrect." +} +``` + +## Best Practices Bảo Mật + +1. **Lưu trữ tokens an toàn** - Sử dụng httpOnly cookies hoặc secure storage +2. **Làm mới tokens chủ động** - Trước khi access token hết hạn +3. **Sử dụng HTTPS trong production** - Không bao giờ gửi credentials qua HTTP +4. **Đăng xuất đúng cách** - Gọi logout endpoint để thu hồi tokens +5. **Validate tokens phía server** - Không tin tưởng validation phía client + +## Swagger UI + +Truy cập tài liệu API tương tác: +- **Local**: http://localhost:5001/swagger + +## Tài Liệu Liên Quan + +- [Hướng Dẫn IAM Migration](./iam-migration.md) +- [Local Development](./local-development.md) +- [Security Architecture](../architecture/security-architecture.md)