- Updated README and architecture documentation to reflect the new authentication flow, including user registration, login, token management, and logout processes. - Enhanced API documentation with detailed examples for each step of the authentication process, including curl commands and expected responses. - Improved clarity in the architecture diagrams, outlining the interaction between clients, API, application, and infrastructure layers. - Added sections on OAuth2 grant types and user management functionalities to provide comprehensive guidance for developers. - Streamlined Vietnamese documentation to ensure consistency with English updates and improve accessibility for users.
8.4 KiB
8.4 KiB
IAM Service Architecture
Architecture documentation for IAM (Identity and Access Management) Service built with .NET 10, OpenIddict, and Clean Architecture.
Architecture Overview
graph TB
subgraph "Clients"
WEB[Web App]
MOB[Mobile App]
SVC[Other Services]
end
subgraph "API Layer"
AUTH[AuthController]
USR[UsersController]
TOK[Token Endpoint]
end
subgraph "Application Layer - CQRS"
CMD[Commands]
QRY[Queries]
VAL[Validators]
BHV[Behaviors]
end
subgraph "Domain Layer"
USER[User Aggregate]
ROLE[Role Aggregate]
EVT[Domain Events]
end
subgraph "Infrastructure"
CTX[Identity DbContext]
REPO[Repositories]
OIDDICT[OpenIddict]
end
subgraph "External"
DB[(PostgreSQL)]
REDIS[(Redis)]
end
WEB --> AUTH
MOB --> AUTH
SVC --> TOK
AUTH --> CMD
AUTH --> QRY
USR --> CMD
USR --> QRY
TOK --> OIDDICT
CMD --> VAL
CMD --> BHV
CMD --> USER
QRY --> REPO
USER --> EVT
REPO --> CTX
OIDDICT --> CTX
CTX --> DB
CTX --> REDIS
style AUTH fill:#4a90d9,stroke:#2d5986,color:#fff
style USER fill:#50c878,stroke:#2d8659,color:#fff
style DB fill:#ff6b6b,stroke:#c0392b,color:#fff
style OIDDICT fill:#9b59b6,stroke:#7d3c98,color:#fff
OAuth2 Authentication Flow
sequenceDiagram
participant Client
participant AuthController
participant OpenIddict
participant UserManager
participant Database
Note over Client,Database: Password Grant Flow (User Login)
Client->>AuthController: POST /connect/token<br/>grant_type=password
AuthController->>OpenIddict: Validate Request
OpenIddict->>UserManager: FindByEmailAsync()
UserManager->>Database: Query User
Database-->>UserManager: User Data
UserManager->>UserManager: CheckPasswordAsync()
UserManager-->>OpenIddict: User Validated
OpenIddict->>OpenIddict: Generate Tokens (JWT)
OpenIddict-->>AuthController: Token Response
AuthController-->>Client: access_token + refresh_token
Note over Client,Database: Using Access Token
Client->>AuthController: GET /api/v1/users/me<br/>Authorization: Bearer {token}
AuthController->>OpenIddict: Validate JWT
OpenIddict-->>AuthController: Claims Principal
AuthController-->>Client: User Data
Token Types and Flows
graph LR
subgraph "Grant Types"
PWD[Password Grant]
REF[Refresh Token]
CC[Client Credentials]
end
subgraph "Tokens"
AT[Access Token<br/>15 min]
RT[Refresh Token<br/>7 days]
end
subgraph "Use Cases"
USER[User Login]
RENEW[Token Renewal]
S2S[Service-to-Service]
end
PWD --> AT
PWD --> RT
REF --> AT
CC --> AT
USER --> PWD
RENEW --> REF
S2S --> CC
style AT fill:#2ecc71,stroke:#27ae60,color:#fff
style RT fill:#f39c12,stroke:#d68910,color:#fff
style CC fill:#9b59b6,stroke:#7d3c98,color:#fff
Domain Model
User Aggregate
classDiagram
class ApplicationUser {
+Guid Id
+string Email
+string FirstName
+string LastName
+UserStatus Status
+DateTime CreatedAt
+DateTime? LastLoginAt
+UpdateProfile(firstName, lastName)
+Disable()
+RecordLogin()
}
class UserStatus {
<<enumeration>>
+Active
+Locked
+Disabled
+PendingVerification
}
class ApplicationRole {
+Guid Id
+string Name
+string Description
}
ApplicationUser --> UserStatus : has
ApplicationUser "many" --> "many" ApplicationRole : belongs to
Database Schema
erDiagram
AspNetUsers {
uuid Id PK
string Email UK
string PasswordHash
string FirstName
string LastName
int StatusId FK
datetime CreatedAt
datetime LastLoginAt
}
UserStatuses {
int Id PK
string Name
}
AspNetRoles {
uuid Id PK
string Name UK
string Description
}
AspNetUserRoles {
uuid UserId PK,FK
uuid RoleId PK,FK
}
OpenIddictTokens {
uuid Id PK
uuid ApplicationId FK
uuid AuthorizationId FK
string Type
string Status
datetime ExpirationDate
}
AspNetUsers ||--o{ UserStatuses : has
AspNetUsers ||--o{ AspNetUserRoles : has
AspNetRoles ||--o{ AspNetUserRoles : has
CQRS Pipeline
sequenceDiagram
participant Controller
participant MediatR
participant LoggingBehavior
participant ValidatorBehavior
participant TransactionBehavior
participant CommandHandler
participant Repository
Controller->>MediatR: Send(Command)
MediatR->>LoggingBehavior: Handle
LoggingBehavior->>ValidatorBehavior: Next()
ValidatorBehavior->>TransactionBehavior: Next()
TransactionBehavior->>CommandHandler: Next()
CommandHandler->>Repository: Save
Repository-->>CommandHandler: Result
CommandHandler-->>Controller: Response
Pipeline Behaviors
| Order | Behavior | Purpose |
|---|---|---|
| 1 | LoggingBehavior | Log request/response with timing |
| 2 | ValidatorBehavior | FluentValidation |
| 3 | TransactionBehavior | Database transaction wrapper |
Security Architecture
graph TD
subgraph "Authentication"
JWT[JWT Bearer Tokens]
RS256[RS256 Signing]
OIDC[OpenIddict Server]
end
subgraph "Authorization"
RBAC[Role-Based Access]
CLAIMS[Claims-Based]
POLICY[Policy Enforcement]
end
subgraph "Protection"
HASH[bcrypt Password Hash]
HTTPS[HTTPS/TLS]
CORS[CORS Policy]
end
JWT --> RS256
RS256 --> OIDC
RBAC --> CLAIMS
CLAIMS --> POLICY
style JWT fill:#3498db,stroke:#2980b9,color:#fff
style RBAC fill:#e74c3c,stroke:#c0392b,color:#fff
style HASH fill:#2ecc71,stroke:#27ae60,color:#fff
Health Checks
graph TD
HC[Health Check Endpoints]
HC -->|/health/live| L[Liveness Probe]
HC -->|/health/ready| R[Readiness Probe]
HC -->|/health| F[Full Status]
R --> PG[(PostgreSQL Check)]
R --> RD[(Redis Check)]
style HC fill:#3498db,stroke:#2980b9,color:#fff
style L fill:#2ecc71,stroke:#27ae60,color:#fff
style R fill:#f39c12,stroke:#d68910,color:#fff
Deployment Architecture
Docker Compose (Local/Development)
services:
iam-service:
build: .
ports: ["5001:8080"]
depends_on:
- postgres
- redis
environment:
- DATABASE_URL=Host=postgres;...
postgres:
image: postgres:16-alpine
redis:
image: redis:7-alpine
Kubernetes (Production)
apiVersion: apps/v1
kind: Deployment
metadata:
name: iam-service
spec:
replicas: 3
template:
spec:
containers:
- name: iam-service
image: goodgo/iam-service:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health/live
port: 8080
readinessProbe:
httpGet:
path: /health/ready
port: 8080
Error Handling
Exception Hierarchy
Exception
└── DomainException
└── (Custom domain exceptions)
Problem Details (RFC 7807)
All errors return Problem Details format:
{
"type": "https://tools.ietf.org/html/rfc7807",
"title": "Validation Error",
"status": 400,
"detail": "One or more validation errors occurred.",
"errors": {
"Email": ["Email is required"]
}
}
Performance Considerations
- Connection Pooling: EF Core with Npgsql resilience
- Token Caching: Redis for token validation
- Async Operations: All I/O operations are async
- Database Indexes: Configured in EntityConfigurations