# 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)
