# 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 { ["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"); ``` ## 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)