OAuth2 and OIDC Authentication

This document describes the OAuth2 and OpenID Connect (OIDC) authentication implementation for Docling Pipelines.

Overview

The authentication system supports:
- OAuth2 Authorization Code Flow with PKCE support
- OpenID Connect (OIDC) for identity verification
- JWT token validation with JWKS
- Multiple providers: Google, Azure AD, and generic OIDC providers
- Flexible authentication: Support for both Bearer tokens and OAuth2 tokens

Features

Supported Providers

  1. Google OAuth2
  2. Pre-configured endpoints
  3. Automatic OIDC discovery
  4. ID token validation

  5. Azure AD (Microsoft)

  6. Multi-tenant support
  7. Azure AD v2.0 endpoints
  8. Microsoft Graph integration

  9. Generic OIDC

  10. Works with any OIDC-compliant provider
  11. Manual endpoint configuration
  12. Supports Okta, Auth0, Keycloak, GitLab, etc.

Security Features

  • State parameter for CSRF protection
  • JWT signature verification using JWKS
  • Token expiration validation
  • Issuer and audience validation
  • Secure token storage (in-memory, can be extended to Redis)

Installation

Required Dependencies

The following packages are already included in requirements.txt:
- httpx>=0.28.1 - HTTP client for OAuth2 requests
- python-jose[cryptography] - JWT token handling
- pydantic-settings>=2.12.0 - Configuration management
- fastapi>=0.128.8 - Web framework

Configuration

1. Environment Variables

Copy .env.oauth2.example to .env and configure:

cp .env.oauth2.example .env

2. Google OAuth2 Setup

OAUTH2_ENABLED=true
OAUTH2_PROVIDER=google
OAUTH2_CLIENT_ID=your-client-id.apps.googleusercontent.com
OAUTH2_CLIENT_SECRET=your-client-secret
OAUTH2_REDIRECT_URI=http://localhost:8000/auth/oauth2/callback
JWT_SECRET_KEY=your-jwt-secret-key

Setup Steps:
1. Go to Google Cloud Console
2. Create a new project or select existing
3. Enable Google+ API
4. Create OAuth 2.0 credentials
5. Add authorized redirect URI: http://localhost:8000/auth/oauth2/callback
6. Copy Client ID and Client Secret

3. Azure AD Setup

OAUTH2_ENABLED=true
OAUTH2_PROVIDER=azure
AZURE_TENANT_ID=your-tenant-id
OAUTH2_CLIENT_ID=your-application-id
OAUTH2_CLIENT_SECRET=your-client-secret
OAUTH2_REDIRECT_URI=http://localhost:8000/auth/oauth2/callback
JWT_SECRET_KEY=your-jwt-secret-key

Setup Steps:
1. Go to Azure Portal
2. Navigate to Azure Active Directory > App registrations
3. Create new registration
4. Add redirect URI: http://localhost:8000/auth/oauth2/callback
5. Create client secret under Certificates & secrets
6. Copy Application (client) ID, Directory (tenant) ID, and client secret

4. Generic OIDC Provider

OAUTH2_ENABLED=true
OAUTH2_PROVIDER=generic
OAUTH2_DISCOVERY_URL=https://your-provider.com/.well-known/openid-configuration
OAUTH2_CLIENT_ID=your-client-id
OAUTH2_CLIENT_SECRET=your-client-secret
OAUTH2_REDIRECT_URI=http://localhost:8000/auth/oauth2/callback
OIDC_ISSUER=https://your-provider.com
OIDC_AUDIENCE=your-client-id
JWT_SECRET_KEY=your-jwt-secret-key

API Endpoints

OAuth2 Endpoints

1. Initiate Authorization

GET /auth/oauth2/authorize?provider=google

Redirects to OAuth2 provider's authorization page.

Query Parameters:
- provider (optional): Provider name (google, azure, generic)
- redirect_after (optional): URL to redirect after successful login

2. OAuth2 Callback

GET /auth/oauth2/callback?code=xxx&state=xxx&provider=google

Handles OAuth2 callback and exchanges code for token.

Response:

{
  "access_token": "ey...",
  "token_type": "bearer"
}

3. List Available Providers

GET /auth/oauth2/providers

Returns list of configured OAuth2 providers.

4. OIDC Discovery

GET /auth/oauth2/discovery/{provider}

Returns OIDC discovery document for a provider.

Existing Endpoints

Get Current User

GET /auth/me
Authorization: Bearer <token>

Returns current authenticated user information.

Protected Route Example

GET /protected
Authorization: Bearer <token>

Example protected endpoint requiring authentication.

Usage Examples

1. Web Application Flow

import httpx

# Step 1: Redirect user to authorization URL
auth_url = "http://localhost:8000/auth/oauth2/authorize?provider=google"

# Step 2: User completes OAuth2 flow in browser
# User is redirected to /auth/oauth2/callback with code and state

# Step 3: Use the returned access token
token = "eyJ..."

# Step 4: Make authenticated requests
async with httpx.AsyncClient() as client:
    response = await client.get(
        "http://localhost:8000/auth/me",
        headers={"Authorization": f"Bearer {token}"}
    )
    user = response.json()
    print(f"Logged in as: {user['username']}")

2. Testing with cURL

# Step 1: Get authorization URL (open in browser)
curl http://localhost:8000/auth/oauth2/authorize?provider=google

# Step 2: After OAuth2 flow, you'll receive a token
TOKEN="your-access-token-here"

# Step 3: Use token to access protected endpoints
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8000/auth/me

curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8000/protected

Architecture

Components

  1. OAuth2Config (oauth2_config.py)
  2. Configuration management for OAuth2 providers
  3. Provider-specific settings (Google, Azure, Generic)
  4. Environment variable loading

  5. OAuth2Provider (oauth2_provider.py)

  6. Base provider class with common OAuth2 logic
  7. OIDC discovery and JWKS fetching
  8. Token validation and user extraction
  9. Provider implementations: GoogleOAuth2Provider, AzureADOAuth2Provider, GenericOIDCProvider

  10. OAuth2Routes (oauth2_routes.py)

  11. FastAPI router with OAuth2 endpoints
  12. Authorization flow handling
  13. Callback processing
  14. State management

  15. Dependencies (dependencies.py)

  16. FastAPI dependencies for authentication
  17. Token validation
  18. User extraction from tokens
  19. Flexible authentication (Bearer + OAuth2)

Authentication Flow

1. User → GET /auth/oauth2/authorize
2. Server → Redirect to OAuth2 Provider
3. User → Authenticates with Provider
4. Provider → Redirect to /auth/oauth2/callback?code=xxx&state=xxx
5. Server → Exchange code for tokens
6. Server → Validate ID token
7. Server → Extract user info
8. Server → Create JWT token
9. Server → Return JWT to user
10. User → Use JWT for API requests

Security Considerations

Production Deployment

  1. Use HTTPS: Always use HTTPS in production
    env OAUTH2_REDIRECT_URI=https://your-domain.com/auth/oauth2/callback

  2. Secure JWT Secret: Use a strong, random secret key
    bash python -c "import secrets; print(secrets.token_urlsafe(32))"

  3. State Storage: Use Redis or database for state storage in production

  4. Token Expiration: Configure appropriate token expiration
    env JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30 OAUTH2_SESSION_EXPIRE_MINUTES=60

  5. CORS Configuration: Restrict allowed origins
    env CORS_ORIGINS=https://your-frontend.com

Best Practices

  • Always validate state parameter
  • Use PKCE for public clients
  • Implement token refresh mechanism
  • Store tokens securely (HttpOnly cookies for web apps)
  • Implement rate limiting on auth endpoints
  • Log authentication events
  • Monitor for suspicious activity

Troubleshooting

Common Issues

  1. Invalid redirect URI
  2. Ensure redirect URI matches exactly in provider settings
  3. Include protocol (http/https) and port

  4. Token validation fails

  5. Check OIDC_ISSUER matches provider's issuer
  6. Verify OIDC_AUDIENCE is set correctly
  7. Ensure system time is synchronized

  8. State parameter invalid

  9. State expires after use
  10. Don't reuse authorization URLs
  11. Check state storage implementation

  12. JWKS fetch fails

  13. Verify OAUTH2_JWKS_URI is accessible
  14. Check network connectivity
  15. Ensure provider's JWKS endpoint is available

Additional Resources