# Security API Documentation API documentation for security-related endpoints and how to use security components in routes. ## Table of Contents 1. [Overview](#overview) 2. [Authentication Endpoints](#authentication-endpoints) 3. [Authentication Flows](#authentication-flows) 4. [Using Security in Routes](#using-security-in-routes) 5. [API Examples](#api-examples) ## Overview The Security component provides authentication endpoints and utilities that routes can use to protect their endpoints and access user context. This document focuses on the API surface and how to use security components from route handlers. For detailed information about the Security component architecture and internal workings, see [Security Component Documentation](./security-component.md). ## Authentication Endpoints ### Local Authentication **Base Path**: `/api/local` #### POST `/api/local/login` Authenticate with username and password. **Request**: - Content-Type: `application/x-www-form-urlencoded` - Headers: `X-CSRF-Token` (required) - Body: `username`, `password` (form data) **Response**: - Status: `200 OK` - Cookies: `auth_token` (httpOnly), `refresh_token` (httpOnly) - Body: ```json { "type": "local_auth_success", "message": "Login successful - tokens set in httpOnly cookies", "authenticationAuthority": "local", "expires_at": "2024-01-01T12:00:00" } ``` **Rate Limit**: 30 requests per minute #### POST `/api/local/register` Register a new user account. **Request**: - Content-Type: `application/json` - Body: User object + password **Response**: User object **Rate Limit**: 10 requests per minute #### GET `/api/local/me` Get current authenticated user information. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: User object **Rate Limit**: 30 requests per minute #### POST `/api/local/refresh` Refresh access token using refresh token. **Request**: - Cookie: `refresh_token` (httpOnly) **Response**: - Cookies: New `auth_token` and `refresh_token` - Body: Token refresh response **Rate Limit**: 60 requests per minute #### POST `/api/local/logout` Logout current user and invalidate tokens. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: Logout confirmation **Rate Limit**: 10 requests per minute ### Microsoft OAuth Authentication **Base Path**: `/api/msft` #### GET `/api/msft/login` Initiate Microsoft OAuth login flow. **Response**: Redirects to Microsoft OAuth login page #### GET `/api/msft/auth/callback` OAuth callback endpoint (handled by Microsoft). **Query Parameters**: - `code`: Authorization code from Microsoft - `state`: State parameter for CSRF protection **Response**: HTML page that sets cookies and redirects #### GET `/api/msft/me` Get current authenticated user information. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: User object #### POST `/api/msft/logout` Logout current user. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: Logout confirmation ### Google OAuth Authentication **Base Path**: `/api/google` #### GET `/api/google/login` Initiate Google OAuth login flow. **Query Parameters**: - `state`: Optional state parameter (default: "login") - `connectionId`: Optional connection ID for connection flow **Response**: Redirects to Google OAuth login page #### GET `/api/google/auth/callback` OAuth callback endpoint (handled by Google). **Query Parameters**: - `code`: Authorization code from Google - `state`: State parameter for CSRF protection **Response**: HTML page that sets cookies and redirects #### GET `/api/google/me` Get current authenticated user information. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: User object #### POST `/api/google/logout` Logout current user. **Request**: - Headers: `Authorization: Bearer ` OR Cookie: `auth_token` **Response**: Logout confirmation ## Authentication Flows ### Login Flow (Local Authentication) ```mermaid sequenceDiagram participant Client participant Route as Login Route
POST /api/local/login participant Auth as auth.py participant JWT as jwtService.py participant Interface as Interface Layer participant DB as Database Client->>Route: POST /api/local/login
(username, password, X-CSRF-Token) Route->>Route: Validate CSRF Token Route->>Interface: authenticateLocalUser(username, password) Interface->>DB: Query User & Verify Password DB-->>Interface: User Record alt Invalid Credentials Interface-->>Route: None Route-->>Client: HTTPException 401 end Route->>JWT: createAccessToken(userData) JWT->>JWT: Generate JTI (UUID) JWT->>JWT: Set Expiration JWT->>JWT: Sign JWT JWT-->>Route: Access Token + Expires At Route->>JWT: createRefreshToken(userData) JWT-->>Route: Refresh Token + Expires At Route->>Interface: Save Token to DB
(for LOCAL authority) Interface->>DB: Insert Token Record Route->>JWT: setAccessTokenCookie(response, token) JWT->>JWT: Set httpOnly Cookie
(secure, samesite=strict) Route->>JWT: setRefreshTokenCookie(response, token) JWT->>JWT: Set httpOnly Cookie Route-->>Client: HTTP Response
(with Cookies) ``` ### OAuth Flow (Microsoft/Google) ```mermaid sequenceDiagram participant Client participant Route as OAuth Route
GET /api/{provider}/login participant Provider as OAuth Provider
(MSFT/Google) participant JWT as jwtService.py participant Interface as Interface Layer participant DB as Database Client->>Route: GET /api/{provider}/login Route->>Route: Generate OAuth State Route->>Provider: Redirect to OAuth URL
(with state, client_id, redirect_uri) Provider-->>Client: OAuth Login Page Client->>Provider: User Authenticates Provider->>Route: GET /api/{provider}/callback
(code, state) Route->>Route: Validate State Route->>Provider: Exchange Code for Tokens
(POST /token) Provider-->>Route: Access Token + Refresh Token Route->>Provider: Get User Info
(using Access Token) Provider-->>Route: User Profile Data Route->>Interface: Find/Create User
(by external ID) Interface->>DB: Query/Create User DB-->>Interface: User Record Interface-->>Route: User Object Route->>Interface: Save/Create Connection Interface->>DB: Save Connection Record Route->>Interface: Save Token Interface->>DB: Save Token Record Route->>JWT: createAccessToken(userData) JWT-->>Route: Gateway JWT Token Route->>JWT: setAccessTokenCookie(response, token) Route->>JWT: setRefreshTokenCookie(response, token) Route-->>Client: HTTP Response
(with Gateway Cookies) ``` ## Using Security in Routes ### Basic Authentication Pattern All protected routes use the `getCurrentUser` dependency to access the authenticated user: ```python from fastapi import APIRouter, Depends from modules.security.auth import getCurrentUser from modules.datamodels.datamodelUam import User router = APIRouter(prefix="/api/example", tags=["Example"]) @router.get("/protected") async def protected_endpoint( currentUser: User = Depends(getCurrentUser) ) -> dict: """ Protected endpoint that requires authentication. The currentUser parameter is automatically populated by getCurrentUser. """ return { "message": f"Hello, {currentUser.username}!", "userId": currentUser.id, "mandateId": currentUser.mandateId } ``` ### Rate Limiting Use the `limiter` from the security module to add rate limiting: ```python from modules.security.auth import getCurrentUser, limiter from fastapi import Request @router.post("/action") @limiter.limit("30/minute") async def rate_limited_endpoint( request: Request, currentUser: User = Depends(getCurrentUser) ) -> dict: """Endpoint with rate limiting (30 requests per minute)""" return {"status": "success"} ``` ### Cookie vs Header Authentication The security component supports both authentication methods: 1. **Cookie-based** (preferred for web apps): - Tokens are automatically sent via httpOnly cookies - More secure (not accessible via JavaScript) - Automatically included in requests from same origin 2. **Header-based** (for API clients): - Use `Authorization: Bearer ` header - Required for programmatic API access - Tokens can be obtained from login endpoints The `CookieAuth` class checks cookies first, then falls back to headers. ### Creating Tokens in Routes When implementing custom authentication endpoints, use the JWT service: ```python from modules.security.jwtService import ( createAccessToken, createRefreshToken, setAccessTokenCookie, setRefreshTokenCookie ) from modules.datamodels.datamodelUam import AuthAuthority @router.post("/custom-login") async def custom_login( response: Response, username: str, password: str ): # Verify credentials... user = verify_user(username, password) # Create token data token_data = { "sub": user.username, "mandateId": str(user.mandateId), "userId": str(user.id), "authenticationAuthority": AuthAuthority.LOCAL } # Create tokens access_token, expires_at = createAccessToken(token_data) refresh_token, _ = createRefreshToken(token_data) # Set cookies setAccessTokenCookie(response, access_token) setRefreshTokenCookie(response, refresh_token) return {"status": "success", "expires_at": expires_at.isoformat()} ``` ### Clearing Tokens (Logout) Use the JWT service cookie clearing functions: ```python from modules.security.jwtService import ( clearAccessTokenCookie, clearRefreshTokenCookie ) @router.post("/logout") async def logout( response: Response, currentUser: User = Depends(getCurrentUser) ): # Clear cookies clearAccessTokenCookie(response) clearRefreshTokenCookie(response) # Optionally revoke token in database # interface.revokeToken(tokenId) return {"status": "logged_out"} ``` ## API Examples ### Example: Protected Endpoint ```python from fastapi import APIRouter, Depends, HTTPException from modules.security.auth import getCurrentUser, limiter from modules.datamodels.datamodelUam import User from fastapi import Request router = APIRouter(prefix="/api/data", tags=["Data"]) @router.get("/items") @limiter.limit("60/minute") async def get_items( request: Request, currentUser: User = Depends(getCurrentUser) ) -> list: """ Get items for the current user. Requires authentication. """ # User is guaranteed to be authenticated and enabled # Access user properties: currentUser.id, currentUser.mandateId, etc. items = fetch_user_items(currentUser.id) return items ``` ### Example: Role-Based Access ```python from modules.datamodels.datamodelUam import UserPrivilege @router.delete("/admin/items/{item_id}") async def delete_item( item_id: str, currentUser: User = Depends(getCurrentUser) ): """ Delete item (admin only). """ # Check user privilege if currentUser.privilege not in [UserPrivilege.ADMIN, UserPrivilege.SYSADMIN]: raise HTTPException( status_code=403, detail="Admin access required" ) delete_item_by_id(item_id) return {"status": "deleted"} ``` ### Example: Mandate-Scoped Access ```python @router.get("/mandate/data") async def get_mandate_data( currentUser: User = Depends(getCurrentUser) ): """ Get data scoped to user's mandate. """ # User's mandateId is automatically validated during authentication # Token context must match user's current mandate data = fetch_mandate_data(currentUser.mandateId) return data ``` ### Example: CSRF Protection For state-changing operations, ensure CSRF token is included: ```python @router.post("/update") async def update_data( request: Request, data: dict, currentUser: User = Depends(getCurrentUser) ): """ Update data (requires CSRF token). CSRF middleware automatically validates X-CSRF-Token header. """ # CSRF validation happens automatically via middleware # Just ensure client sends X-CSRF-Token header update_user_data(currentUser.id, data) return {"status": "updated"} ``` ### Example: Error Handling ```python from fastapi import HTTPException, status @router.get("/sensitive") async def get_sensitive_data( currentUser: User = Depends(getCurrentUser) ): """ Get sensitive data with proper error handling. """ try: # getCurrentUser already validates: # - Token is valid and not expired # - User exists and is enabled # - Context matches (mandateId, userId) data = fetch_sensitive_data(currentUser.id) return data except ValueError as e: # Handle business logic errors raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) ``` ## Related Documentation - [Security Component Documentation](./security-component.md) - Component architecture and internal workings - [Architecture Overview](./architecture-overview.md) - Overall system architecture