Files
pos-system/services/iam-service-net/docs/vi
Ho Ngoc Hai 79bc566b73 docs: Expand architecture documentation for IAM Service with new aggregates and event types
- Added detailed sections for Organization, Group, Access Request, Access Review, and Audit & Compliance aggregates in both English and Vietnamese.
- Included class diagrams and enumerations to enhance understanding of the new structures and their relationships.
- Updated the AuditEventType table to reflect 18 event types, improving clarity on event handling within the IAM Service.
2026-01-14 19:31:41 +07:00
..

IAM Service .NET 10

Service IAM (Identity and Access Management) .NET 10 với OAuth2/OIDC sử dụng Duende IdentityServer.

Tổng Quan

IAM Service cung cấp các chức năng quản lý danh tính và truy cập:

  • OAuth2/OIDC - Authentication với Duende IdentityServer
  • User Management - CRUD operations cho users
  • Password Management - Đổi mật khẩu
  • Token Management - Issue, refresh, revoke tokens
  • Email Verification - Xác thực email qua SMTP
  • 2FA/MFA - Xác thực hai yếu tố với TOTP
  • Social Login - Đăng nhập qua Google và Facebook
  • CQRS Pattern - MediatR cho Commands/Queries
  • Clean Architecture - Domain, Infrastructure, API layers

Yêu Cầu

Yêu cầu Phiên bản
.NET SDK 10.0.101+
Docker 24.0+
PostgreSQL 15+

Bắt Đầu Nhanh

Chạy với Docker

cd deployments/local
docker-compose up -d

Chạy Local

cd services/iam-service-net
dotnet restore
dotnet build
dotnet run --project src/IamService.API

Database Migrations

Yêu Cầu

# Cài đặt EF Core tools (một lần)
dotnet tool install --global dotnet-ef

Tạo Migration

# Tạo migration mới
dotnet ef migrations add <TenMigration> \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

Áp Dụng Migration

# Áp dụng migrations vào database
dotnet ef database update \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

Các Lệnh Khác

# Xóa migration cuối (nếu chưa áp dụng)
dotnet ef migrations remove \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

# Tạo SQL script
dotnet ef migrations script \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API \
  --output migrations.sql

# Liệt kê migrations
dotnet ef migrations list \
  --project src/IamService.Infrastructure \
  --startup-project src/IamService.API

Thiết Lập Neon Database

  1. Tạo database trên Neon Console
  2. Sao chép connection string
  3. Cập nhật appsettings.Development.json:
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=<host>;Port=5432;Database=<db>;Username=<user>;Password=<pass>;SSL Mode=Require"
  }
}
  1. Chạy migrations: dotnet ef database update ...

API Endpoints

Authentication (/api/v1/auth)

Method Endpoint Mô Tả Auth
POST /api/v1/auth/register Đăng ký user mới
POST /connect/token OAuth2 Token (login, refresh)
POST /api/v1/auth/change-password Đổi mật khẩu
POST /api/v1/auth/logout Đăng xuất (revoke tokens)

Email Verification (/api/v1/auth)

Method Endpoint Mô Tả Auth
POST /api/v1/auth/send-verification-email Gửi email xác thực
POST /api/v1/auth/confirm-email Xác nhận email với token

Xác Thực Hai Yếu Tố (/api/v1/auth/2fa)

Method Endpoint Mô Tả Auth
POST /api/v1/auth/2fa/enable Bật 2FA (lấy QR code)
POST /api/v1/auth/2fa/verify Xác minh mã TOTP & kích hoạt
POST /api/v1/auth/2fa/disable Tắt 2FA

Đăng Nhập Mạng Xã Hội (/api/v1/auth)

Method Endpoint Mô Tả Auth
GET /api/v1/auth/external-login/{provider} Bắt đầu OAuth flow (Google/Facebook)
GET /api/v1/auth/external-callback Xử lý OAuth callback
GET /api/v1/auth/linked-accounts Lấy danh sách providers đã liên kết

User Management (/api/v1/users)

Method Endpoint Mô Tả Auth
GET /api/v1/users Lấy danh sách users (phân trang)
GET /api/v1/users/me Lấy 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 thông tin user
DELETE /api/v1/users/{id} Xóa user (soft delete)

Health Checks

Endpoint Mục Đích
/health Trạng thái health đầy đủ
/health/live Kiểm tra sống
/health/ready Kiểm tra sẵn sàng

Organizations (/api/v1/organizations) - Phase 2

Method Endpoint Mô Tả Auth
GET /api/v1/organizations/{id} Lấy tổ chức theo ID
GET /api/v1/organizations/slug/{slug} Lấy tổ chức theo slug
POST /api/v1/organizations Tạo tổ chức mới
PUT /api/v1/organizations/{id} Cập nhật tổ chức
DELETE /api/v1/organizations/{id} Lưu trữ tổ chức
GET /api/v1/organizations/{id}/hierarchy Lấy phân cấp
GET /api/v1/organizations/{id}/children Lấy tổ chức con

Groups (/api/v1/groups) - Phase 2

Method Endpoint Mô Tả Auth
GET /api/v1/groups Danh sách groups
GET /api/v1/groups/{id} Lấy group theo ID
POST /api/v1/groups Tạo group mới
DELETE /api/v1/groups/{id} Xóa group
POST /api/v1/groups/{id}/members Thêm thành viên
DELETE /api/v1/groups/{id}/members/{userId} Xóa thành viên

Access Requests (/api/v1/access-requests) - Phase 3A

Method Endpoint Mô Tả Auth
POST /api/v1/access-requests Tạo yêu cầu truy cập
GET /api/v1/access-requests Danh sách requests
GET /api/v1/access-requests/{id} Lấy request theo ID
POST /api/v1/access-requests/{id}/submit Submit request
POST /api/v1/access-requests/{id}/approve Phê duyệt
POST /api/v1/access-requests/{id}/reject Từ chối
DELETE /api/v1/access-requests/{id} Hủy request
GET /api/v1/access-requests/pending Requests đang chờ

Access Reviews (/api/v1/access-reviews) - Phase 3B

Method Endpoint Mô Tả Auth
POST /api/v1/access-reviews Tạo access review
GET /api/v1/access-reviews/{id} Lấy review theo ID
POST /api/v1/access-reviews/{id}/items Thêm item
POST /api/v1/access-reviews/{id}/start Bắt đầu review
POST /api/v1/access-reviews/{id}/items/{itemId}/review Certify/Revoke
POST /api/v1/access-reviews/{id}/complete Hoàn thành

Privileged Access (/api/v1/privileged-access) - Phase 3B PAM

Method Endpoint Mô Tả Auth
POST /api/v1/privileged-access/request Yêu cầu JIT access
GET /api/v1/privileged-access/active Grants đang active
POST /api/v1/privileged-access/{id}/revoke Thu hồi access

Audit (/api/v1/audit) - Phase 4A

Method Endpoint Mô Tả Auth
GET /api/v1/audit/logs Lấy audit logs (filtered)

Compliance (/api/v1/compliance) - Phase 4A

Method Endpoint Mô Tả Auth
POST /api/v1/compliance/reports Generate report
GET /api/v1/compliance/reports Danh sách reports
GET /api/v1/compliance/reports/{id} Report chi tiết
POST /api/v1/compliance/reports/{id}/complete Hoàn thành report
GET /api/v1/compliance/violations Violations chưa giải quyết

Quy Trình Xác Thực

Bước 1: Đăng Ký User Mới

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"
  }'

Response:

{
  "success": true,
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com"
  }
}

Bước 2: Đăng Nhập (Password Grant)

curl -X POST http://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=password-client" \
  -d "client_secret=password-client-secret" \
  -d "username=user@example.com" \
  -d "password=Password123!" \
  -d "scope=openid profile email api offline_access"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9...",
  "scope": "openid profile email offline_access"
}

Bước 3: Sử Dụng Access Token

Sử dụng access_token trong header Authorization cho các API được bảo vệ:

curl http://localhost:5001/api/v1/users/me \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9..."

Bước 4: Làm Mới Token (Khi Access Token Hết Hạn)

curl -X POST http://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9..."

Bước 5: Đăng Xuất

curl -X POST http://localhost:5001/api/v1/auth/logout \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Client Credentials (Service-to-Service)

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"

Xác Thực Email

Gửi Email Xác Thực

curl -X POST http://localhost:5001/api/v1/auth/send-verification-email \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Xác Nhận Email

curl -X POST http://localhost:5001/api/v1/auth/confirm-email \
  -H "Content-Type: application/json" \
  -d '{"userId": "user-guid", "token": "confirmation-token"}'

Xác Thực Hai Yếu Tố (2FA)

Bật 2FA

curl -X POST http://localhost:5001/api/v1/auth/2fa/enable \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
  "success": true,
  "data": {
    "secretKey": "JBSWY3DPEHPK3PXP",
    "qrCodeBase64": "data:image/png;base64,...",
    "recoveryCodes": ["code1", "code2", "code3", ...]
  }
}

Xác Minh Mã 2FA

curl -X POST http://localhost:5001/api/v1/auth/2fa/verify \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"code": "123456"}'

Tắt 2FA

curl -X POST http://localhost:5001/api/v1/auth/2fa/disable \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"code": "123456"}'

Đăng Nhập Mạng Xã Hội

Bắt Đầu OAuth Flow

Chuyển hướng user tới:

GET http://localhost:5001/api/v1/auth/external-login/Google?returnUrl=http://your-app/callback
GET http://localhost:5001/api/v1/auth/external-login/Facebook?returnUrl=http://your-app/callback

Lấy Tài Khoản Đã Liên Kết

curl http://localhost:5001/api/v1/auth/linked-accounts \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
  "success": true,
  "data": {
    "linkedProviders": [
      {"provider": "Google", "providerDisplayName": "Google"},
      {"provider": "Facebook", "providerDisplayName": "Facebook"}
    ]
  }
}

Swagger UI

Sau khi chạy service, truy cập Swagger UI tại:

Cấu Hình

Biến Môi Trường

Biến Mô Tả Mặc định
ASPNETCORE_ENVIRONMENT Môi trường Development
DATABASE_URL PostgreSQL connection -
JWT_SECRET Secret ký JWT (32+ ký tự) -
REDIS_HOST Redis server host localhost
REDIS_PORT Redis server port 6379
REDIS_PASSWORD Redis password -
REDIS_DATABASE Redis database number 0

Redis Caching

Service sử dụng Redis cho distributed caching thông qua interface ICacheService.

Cấu Hình Redis

Thêm cấu hình Redis trong appsettings.json:

{
  "Redis": {
    "Host": "localhost",
    "Port": 6379,
    "Password": "",
    "Database": 0,
    "ConnectTimeout": 5000,
    "SyncTimeout": 5000
  }
}

Hoặc sử dụng biến môi trường:

REDIS_HOST=your-redis-host
REDIS_PORT=6379
REDIS_PASSWORD=your-password
REDIS_DATABASE=0

ICacheService Interface

public interface ICacheService
{
    // Các thao tác cơ bản
    Task<T?> GetAsync<T>(string key);
    Task SetAsync<T>(string key, T value, TimeSpan? expiration = null);
    Task RemoveAsync(string key);
    Task<bool> ExistsAsync(string key);
    
    // Get hoặc tạo mới pattern
    Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> factory, TimeSpan? expiration = null);
    
    // Hỗ trợ blacklist token
    Task BlacklistAsync(string key, TimeSpan expiration);
    Task<bool> IsBlacklistedAsync(string key);
}

Ví Dụ Sử Dụng

Get/Set cơ bản:

public class MyService
{
    private readonly ICacheService _cache;
    
    public MyService(ICacheService cache) => _cache = cache;
    
    public async Task<User?> GetUser(string userId)
    {
        return await _cache.GetAsync<User>($"user:{userId}");
    }
    
    public async Task CacheUser(User user)
    {
        await _cache.SetAsync($"user:{user.Id}", user, TimeSpan.FromMinutes(15));
    }
}

Get or Set Pattern (Cache-Aside):

public async Task<User> GetUserById(string userId)
{
    return await _cache.GetOrSetAsync(
        $"user:{userId}",
        async () => await _repository.GetByIdAsync(userId),
        TimeSpan.FromMinutes(15)
    );
}

Blacklist Token (cho Logout):

public async Task Logout(string tokenId)
{
    // Blacklist refresh token trong thời gian còn lại của token
    await _cache.BlacklistAsync($"token:{tokenId}", TimeSpan.FromDays(7));
}

public async Task<bool> IsTokenRevoked(string tokenId)
{
    return await _cache.IsBlacklistedAsync($"token:{tokenId}");
}

Kiểm Thử

dotnet test

Triển Khai

Docker Build

docker build -t goodgo/iam-service:latest .
docker run -p 5001:8080 --env-file .env goodgo/iam-service:latest

Tài Nguyên