GitHub OAuth ============ GitHub OAuth implementation for web user authentication with JWT token generation. .. contents:: Table of Contents :local: :depth: 2 OAuth Flow ---------- .. mermaid:: sequenceDiagram participant User participant Frontend participant API participant GitHub User->>Frontend: Click "Login" Frontend->>API: GET /github/login API->>API: Generate state token (CSRF protection) API-->>Frontend: Redirect to GitHub (with state) Frontend->>GitHub: Authorization request User->>GitHub: Approve GitHub-->>API: Callback with code + state API->>API: Verify state token (CSRF check) API->>GitHub: Exchange code for token GitHub-->>API: Access token API->>GitHub: Get user info + org membership GitHub-->>API: User profile API->>API: Create/update user + assign roles API->>API: Generate JWT (30 min expiration) API-->>Frontend: Redirect with JWT Configuration ------------- Required environment variables: .. code-block:: bash GITHUB_CLIENT_ID=your_oauth_app_id GITHUB_CLIENT_SECRET=your_oauth_app_secret GITHUB_ORG_NAME=your_org_name # Required for org membership check SECRET_KEY=jwt_signing_key FRONTEND_URL=http://localhost:8080 # OAuth callback redirect BACKEND_URL=http://localhost:8000 Optional: .. code-block:: bash GITHUB_TEAM_ROLE_MAPPING='{"org/admins": "admin", "org/observers": "observer"}' JWT Generation -------------- .. code-block:: python from jose import jwt from datetime import datetime, timedelta def create_jwt_token(user: User) -> str: payload = { "sub": user.username, # Username in subject "exp": datetime.utcnow() + timedelta(minutes=30), # 30 minute expiration "iat": datetime.utcnow() } return jwt.encode(payload, SECRET_KEY, algorithm="HS256") Frontend Integration -------------------- .. code-block:: javascript // Redirect to OAuth window.location.href = `${API_URL}/github/login`; // After callback, extract JWT from URL const params = new URLSearchParams(window.location.search); const jwt = params.get('token'); // Store and use localStorage.setItem('jwt_token', jwt); // Make authenticated requests fetch(`${API_URL}/auth/me`, { headers: {'Authorization': `Bearer ${jwt}`} }); Next Steps ---------- * :doc:`../../quickstart/first-api-call` - Testing authentication