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.
This commit is contained in:
Ho Ngoc Hai
2026-01-12 16:59:06 +07:00
parent 4ae24a7bc8
commit 9168a5f734
2 changed files with 474 additions and 0 deletions

View File

@@ -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<string, string>
{
["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<TokenResponse>();
// Sử dụng token
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
var user = await client.GetFromJsonAsync<UserDto>("/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)