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