# Authentication & Authorization

## Overview

Attune uses JWT (JSON Web Token) based authentication for securing API endpoints. The authentication system supports user registration, login, token refresh, and password management.

## Architecture

### Components

1. **JWT Tokens**
   - **Access Tokens**: Short-lived tokens (default: 1 hour) used for API authentication
   - **Refresh Tokens**: Long-lived tokens (default: 7 days) used to obtain new access tokens

2. **Password Security**
   - Passwords are hashed using **Argon2id** (industry-standard, memory-hard algorithm)
   - Password hashes are stored in the `attributes` JSONB field of the `identity` table
   - Minimum password length: 8 characters

3. **Middleware**
   - `require_auth`: Middleware function that validates JWT tokens on protected routes
   - `RequireAuth`: Extractor for accessing authenticated user information in handlers

## Configuration

Authentication is configured via environment variables:

```bash
# JWT Secret Key (REQUIRED in production)
JWT_SECRET=your-secret-key-here

# Token Expiration (in seconds)
JWT_ACCESS_EXPIRATION=3600      # 1 hour (default)
JWT_REFRESH_EXPIRATION=604800   # 7 days (default)
```

**Security Warning**: Always set a strong, random `JWT_SECRET` in production. The default value is insecure and should only be used for development.

## API Endpoints

### Public Endpoints (No Authentication Required)

#### Register a New User

```http
POST /auth/register
Content-Type: application/json

{
  "login": "username",
  "password": "securepassword123",
  "display_name": "John Doe" // optional
}
```

**Response:**
```json
{
  "data": {
    "access_token": "eyJhbGc...",
    "refresh_token": "eyJhbGc...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}
```

#### Login

```http
POST /auth/login
Content-Type: application/json

{
  "login": "username",
  "password": "securepassword123"
}
```

**Response:**
```json
{
  "data": {
    "access_token": "eyJhbGc...",
    "refresh_token": "eyJhbGc...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}
```

#### Refresh Access Token

```http
POST /auth/refresh
Content-Type: application/json

{
  "refresh_token": "eyJhbGc..."
}
```

**Response:**
```json
{
  "data": {
    "access_token": "eyJhbGc...",
    "refresh_token": "eyJhbGc...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}
```

### Protected Endpoints (Authentication Required)

All protected endpoints require an `Authorization` header with a valid access token:

```http
Authorization: Bearer <access_token>
```

#### Get Current User

```http
GET /auth/me
Authorization: Bearer eyJhbGc...
```

**Response:**
```json
{
  "data": {
    "id": 1,
    "login": "username",
    "display_name": "John Doe"
  }
}
```

#### Change Password

```http
POST /auth/change-password
Authorization: Bearer eyJhbGc...
Content-Type: application/json

{
  "current_password": "oldpassword123",
  "new_password": "newpassword456"
}
```

**Response:**
```json
{
  "data": {
    "success": true,
    "message": "Password changed successfully"
  }
}
```

## Error Responses

Authentication errors return appropriate HTTP status codes:

- **400 Bad Request**: Invalid request format or validation errors
- **401 Unauthorized**: Missing, invalid, or expired token; invalid credentials
- **403 Forbidden**: Insufficient permissions (future RBAC implementation)
- **409 Conflict**: Username already exists during registration

Example error response:
```json
{
  "error": "Invalid authentication token",
  "code": "UNAUTHORIZED"
}
```

## Usage in Route Handlers

### Protecting Routes

Add the authentication middleware to routes that require authentication:

```rust
use crate::auth::middleware::RequireAuth;

async fn protected_handler(
    RequireAuth(user): RequireAuth,
) -> Result<Json<ApiResponse<MyData>>, ApiError> {
    let identity_id = user.identity_id()?;
    let login = user.login();
    
    // Your handler logic here
    Ok(Json(ApiResponse::new(data)))
}
```

### Accessing User Information

The `RequireAuth` extractor provides access to the authenticated user's claims:

```rust
pub struct AuthenticatedUser {
    pub claims: Claims,
}

impl AuthenticatedUser {
    pub fn identity_id(&self) -> Result<i64, ParseIntError>
    pub fn login(&self) -> &str
}
```

## Database Schema

### Identity Table

The `identity` table stores user authentication information:

```sql
CREATE TABLE attune.identity (
    id BIGSERIAL PRIMARY KEY,
    login TEXT NOT NULL UNIQUE,
    display_name TEXT,
    attributes JSONB NOT NULL DEFAULT '{}'::jsonb,
    password_hash TEXT,  -- Added in migration 20240102000001
    created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
```

**Note**: The `password_hash` column is optional to support:
- External authentication providers (OAuth, SAML, etc.)
- Service accounts that don't use password authentication
- API key-based authentication (future implementation)

## Security Best Practices

1. **JWT Secret**
   - Use a strong, random secret (minimum 256 bits)
   - Never commit secrets to version control
   - Rotate secrets periodically in production

2. **Token Storage (Client-Side)**
   - Store tokens securely (e.g., httpOnly cookies or secure storage)
   - Never expose tokens in URLs or localStorage (if using web clients)
   - Clear tokens on logout

3. **Password Requirements**
   - Minimum 8 characters (enforced by validation)
   - Consider implementing additional requirements (uppercase, numbers, symbols)
   - Implement rate limiting on login attempts (future enhancement)

4. **HTTPS**
   - Always use HTTPS in production to protect tokens in transit
   - Configure proper TLS/SSL certificates

5. **Token Expiration**
   - Keep access tokens short-lived (1 hour recommended)
   - Use refresh tokens for long-lived sessions
   - Implement token revocation for logout (future enhancement)

## Future Enhancements

### Planned Features

1. **Role-Based Access Control (RBAC)**
   - Permission set assignments
   - Fine-grained authorization middleware
   - Resource-level permissions

2. **Multi-Factor Authentication (MFA)**
   - TOTP support
   - SMS/Email verification codes

3. **OAuth/OIDC Integration**
   - Support for external identity providers
   - Single Sign-On (SSO)

4. **Token Revocation**
   - Blacklist/whitelist mechanisms
   - Force logout functionality

5. **Account Security**
   - Password reset via email
   - Account lockout after failed attempts
   - Security audit logs

6. **API Keys**
   - Service-to-service authentication
   - Scoped API keys for automation

## Testing

### Manual Testing with cURL

```bash
# Register a new user
curl -X POST http://localhost:8080/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "login": "testuser",
    "password": "testpass123",
    "display_name": "Test User"
  }'

# Login
curl -X POST http://localhost:8080/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "login": "testuser",
    "password": "testpass123"
  }'

# Get current user (replace TOKEN with actual access token)
curl http://localhost:8080/auth/me \
  -H "Authorization: Bearer TOKEN"

# Change password
curl -X POST http://localhost:8080/auth/change-password \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "current_password": "testpass123",
    "new_password": "newpass456"
  }'

# Refresh token
curl -X POST http://localhost:8080/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "REFRESH_TOKEN"
  }'
```

### Unit Tests

Password hashing and JWT utilities include comprehensive unit tests:

```bash
# Run auth-related tests
cargo test --package attune-api password
cargo test --package attune-api jwt
cargo test --package attune-api middleware
```

## Troubleshooting

### Common Issues

1. **"Missing authentication token"**
   - Ensure you're including the `Authorization` header
   - Verify the header format: `Bearer <token>`

2. **"Authentication token expired"**
   - Use the refresh token endpoint to get a new access token
   - Check token expiration configuration

3. **"Invalid login or password"**
   - Verify credentials are correct
   - Check if the identity has a password set (some accounts may use external auth)

4. **"JWT_SECRET not set" warning**
   - Set the `JWT_SECRET` environment variable before starting the server
   - Use a strong, random value in production

### Debug Logging

Enable debug logging to troubleshoot authentication issues:

```bash
RUST_LOG=attune_api=debug cargo run --bin attune-api
```

## References

- [RFC 7519: JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)
- [Argon2 Password Hashing](https://en.wikipedia.org/wiki/Argon2)
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
