OAuth2 Authentication
Enterprise-grade authentication for M4 using OAuth2 with JWT tokens.
Quick Setup
# Enable OAuth2 when configuring
m4 config claude --enable-oauth2 \
--oauth2-issuer https://your-auth-provider.com \
--oauth2-audience m4-api
MCP Configuration with OAuth2
For manual MCP client configuration with OAuth2 enabled:
{
"mcpServers": {
"m4": {
"command": "uvx",
"args": ["m4-infra"],
"env": {
"M4_OAUTH2_ENABLED": "true",
"M4_OAUTH2_ISSUER_URL": "https://your-auth-provider.com",
"M4_OAUTH2_AUDIENCE": "m4-api",
"M4_OAUTH2_TOKEN": "your-jwt-token"
}
}
}
}
Note: The active backend is configured via
m4 backend duckdb(orbigquery), not through MCP env vars.
Environment Variables
Required (when OAuth2 enabled)
M4_OAUTH2_ENABLED=true
M4_OAUTH2_ISSUER_URL=https://your-auth-provider.com
M4_OAUTH2_AUDIENCE=m4-api
Optional
# Scopes
M4_OAUTH2_REQUIRED_SCOPES=read:mimic-data # Default: read:mimic-data
# JWKS (auto-discovered from issuer if not set)
M4_OAUTH2_JWKS_URL=https://your-auth-provider.com/.well-known/jwks.json
M4_OAUTH2_JWKS_CACHE_TTL=3600 # Default: 3600 (1 hour)
# Client credentials (if needed by your provider)
M4_OAUTH2_CLIENT_ID=your-client-id
M4_OAUTH2_CLIENT_SECRET=your-client-secret
# Validation toggles
M4_OAUTH2_VALIDATE_EXP=true # Default: true
M4_OAUTH2_VALIDATE_AUD=true # Default: true
M4_OAUTH2_VALIDATE_ISS=true # Default: true
# Rate limiting
M4_OAUTH2_RATE_LIMIT_ENABLED=true # Default: true
M4_OAUTH2_RATE_LIMIT_REQUESTS=100 # Default: 100 requests per window
M4_OAUTH2_RATE_LIMIT_WINDOW=3600 # Default: 3600 seconds (1 hour)
# Token (set at runtime)
M4_OAUTH2_TOKEN=your-jwt-token # Bearer prefix optional
Token Requirements
Your JWT must include:
Header:
alg: RS256 or ES256kid: Key ID matching a key in the JWKS
Claims:
{
"iss": "https://your-auth-provider.com",
"aud": "m4-api",
"scope": "read:mimic-data",
"exp": 1234567890,
"sub": "user-id"
}
Rate Limiting
Rate limiting is per-user (based on the sub claim):
- Default limit: 100 requests per hour per user
- Memory management: LRU eviction when cache exceeds 10,000 users
- Cleanup: Expired entries are periodically removed
Disable rate limiting:
M4_OAUTH2_RATE_LIMIT_ENABLED=false
Provider Examples
Auth0
M4_OAUTH2_ISSUER_URL=https://your-domain.auth0.com/
M4_OAUTH2_AUDIENCE=https://api.your-domain.com
M4_OAUTH2_REQUIRED_SCOPES=read:mimic-data
Okta
M4_OAUTH2_ISSUER_URL=https://your-domain.okta.com/oauth2/default
M4_OAUTH2_AUDIENCE=api://m4
Any OIDC Provider
Any OAuth2 provider supporting:
- JWKS endpoint (
.well-known/jwks.json) - JWT tokens with RS256 or ES256 signing
- Standard claims (
iss,aud,exp,sub)
Troubleshooting
Error: "Missing OAuth2 access token"
Set the token environment variable:
export M4_OAUTH2_TOKEN="eyJhbGciOiJSUzI1NiIs..."
Error: "Invalid token signature"
- Verify token is signed by the configured issuer
- Check JWKS URL is accessible
- Ensure token's
kidmatches a key in JWKS
Error: "Missing required scopes"
Request a new token with all required scopes. Check if your provider uses:
- Space-separated scopes in
scopeclaim - Array in
scpclaim (both are supported)
Error: "Rate limit exceeded"
- Wait for the rate limit window to reset (default: 1 hour)
- Or increase
M4_OAUTH2_RATE_LIMIT_REQUESTS - Or disable rate limiting for development
Error: "Token has expired"
Request a fresh token from your OAuth2 provider.
Security Best Practices
- Use short-lived tokens (< 1 hour)
- Never commit tokens to version control
- Use environment variables or secure secret storage
- Start with conservative rate limits and adjust based on usage
- Monitor authentication failures in logs
Disabling OAuth2
For development or local use, OAuth2 is disabled by default:
M4_OAUTH2_ENABLED=false # or simply don't set it
When disabled, all MCP tools are accessible without authentication.