- Added endpoints for sending and confirming email verification, enhancing user account security. - Integrated two-factor authentication (2FA) with TOTP support, including enabling, verifying, and disabling 2FA. - Implemented social login functionality for Google and Facebook, allowing users to authenticate using their existing accounts. - Updated dependency injection to include services for email, 2FA, and social login. - Enhanced documentation to reflect new features and usage examples for email verification and 2FA.
352 lines
9.4 KiB
Markdown
352 lines
9.4 KiB
Markdown
# 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 Duende IdentityServer:
|
|
- **Password Grant** - User login with email/password
|
|
- **Refresh Token** - Token renewal without re-authentication
|
|
- **Client Credentials** - Service-to-service authentication
|
|
- **Email Verification** - SMTP-based email confirmation
|
|
- **Two-Factor Authentication (2FA)** - TOTP with QR code and recovery codes
|
|
- **Social Login** - Google and Facebook OAuth integration
|
|
|
|
## 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) |
|
|
|
|
### Email Verification
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| `POST` | `/api/v1/auth/send-verification-email` | Send email verification link (auth required) |
|
|
| `POST` | `/api/v1/auth/confirm-email` | Confirm email with token |
|
|
|
|
### Two-Factor Authentication (2FA)
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| `POST` | `/api/v1/auth/2fa/enable` | Enable 2FA (get QR code) (auth required) |
|
|
| `POST` | `/api/v1/auth/2fa/verify` | Verify TOTP code & activate (auth required) |
|
|
| `POST` | `/api/v1/auth/2fa/disable` | Disable 2FA (auth required) |
|
|
|
|
### Social Login
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| `GET` | `/api/v1/auth/external-login/{provider}` | Initiate OAuth flow (Google/Facebook) |
|
|
| `GET` | `/api/v1/auth/external-callback` | Handle OAuth callback |
|
|
| `GET` | `/api/v1/auth/linked-accounts` | Get linked OAuth providers (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<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>();
|
|
|
|
// Use token
|
|
client.DefaultRequestHeaders.Authorization =
|
|
new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
|
|
var user = await client.GetFromJsonAsync<UserDto>("/api/v1/users/me");
|
|
```
|
|
|
|
## Email Verification
|
|
|
|
### Send Verification Email
|
|
|
|
```bash
|
|
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"}'
|
|
```
|
|
|
|
### Confirm Email
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/v1/auth/confirm-email \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"userId": "user-guid", "token": "confirmation-token"}'
|
|
```
|
|
|
|
## Two-Factor Authentication (2FA)
|
|
|
|
### Enable 2FA
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/v1/auth/2fa/enable \
|
|
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"secretKey": "JBSWY3DPEHPK3PXP",
|
|
"qrCodeBase64": "data:image/png;base64,...",
|
|
"recoveryCodes": ["code1", "code2", "code3"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Verify 2FA Code
|
|
|
|
```bash
|
|
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"}'
|
|
```
|
|
|
|
### Disable 2FA
|
|
|
|
```bash
|
|
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"}'
|
|
```
|
|
|
|
## Social Login
|
|
|
|
### Initiate OAuth Flow
|
|
|
|
Redirect user to:
|
|
```
|
|
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
|
|
```
|
|
|
|
### Get Linked Accounts
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/v1/auth/linked-accounts \
|
|
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"linkedProviders": [
|
|
{"provider": "Google", "providerDisplayName": "Google"},
|
|
{"provider": "Facebook", "providerDisplayName": "Facebook"}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## 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)
|