Single Sign-On (SSO) Authentication¶
Multi‑Tenancy in v0.7.0
v0.7.0 brings multi‑tenancy with email authentication, teams, RBAC, and resource visibility. If you're upgrading from 0.6.0, review the Migration Guide and Changelog.
For SSO deployments, configure group‑to‑team mappings to auto‑assign users on first login. See Team Management and the provider tutorials for examples.
MCP Gateway supports enterprise Single Sign-On authentication through OAuth2 and OpenID Connect (OIDC) providers. This enables seamless integration with existing identity providers while maintaining backward compatibility with local authentication.
Overview¶
The SSO system provides:
- Multi-Provider Support: GitHub, Google, IBM Security Verify, Microsoft Entra ID, Keycloak, Okta, and generic OIDC
- Hybrid Authentication: SSO alongside preserved local admin authentication
- Automatic User Provisioning: Creates users on first SSO login
- Security Best Practices: PKCE, CSRF protection, encrypted secrets
- Team Integration: Automatic team assignment and inheritance
- Admin Management: Full CRUD API for provider configuration
Architecture¶
Authentication Flows¶
sequenceDiagram
participant U as User
participant G as Gateway
participant P as SSO Provider
participant D as Database
U->>G: GET /auth/sso/login/github
G->>D: Create auth session
G->>U: Redirect to provider with PKCE
U->>P: Authenticate with provider
P->>G: Callback with auth code
G->>P: Exchange code for tokens (PKCE)
P->>G: Access token + user info
G->>D: Create/update user
G->>U: Set JWT cookie + redirect
Database Schema¶
SSOProvider Table:
- Provider configuration (OAuth endpoints, client credentials)
- Encrypted client secrets using Fernet encryption
- Trusted domains and team mapping rules
SSOAuthSession Table:
- Temporary session tracking during OAuth flow
- CSRF state parameters and PKCE verifiers
- 10-minute expiration for security
Supported Providers¶
GitHub OAuth¶
Perfect for developer-focused organizations with GitHub repositories.
Features:
- GitHub organization mapping to teams
- Repository access integration
- Developer-friendly onboarding
Tutorial: GitHub SSO Setup Guide
Google OAuth/OIDC¶
Ideal for Google Workspace organizations.
Features:
- Google Workspace domain verification
- GSuite organization mapping
- Professional email verification
Tutorial: Google SSO Setup Guide
IBM Security Verify¶
Enterprise-grade identity provider with advanced security features.
Features:
- Enterprise SSO compliance
- Advanced user attributes
- Corporate directory integration
Tutorial: IBM Security Verify Setup Guide
Microsoft Entra ID¶
Microsoft's cloud-based identity and access management service (formerly Azure AD).
Features:
- Azure Active Directory integration
- Enterprise application authentication
- Conditional access policies support
Tutorial: Microsoft Entra ID Setup Guide
Keycloak¶
Open-source identity and access management solution with enterprise features.
Features:
- Auto-discovery of OIDC endpoints (40% less configuration)
- User federation with LDAP/Active Directory
- Identity brokering for external providers
- Realm and client role mapping
- Multi-factor authentication support
- Self-hosted and cost-effective
Tutorial: Keycloak SSO Setup Guide
Okta¶
Popular enterprise identity provider with extensive integrations.
Features:
- Enterprise directory synchronization
- Multi-factor authentication support
- Custom user attributes
Tutorial: Okta SSO Setup Guide
Generic OIDC Provider¶
Support for any OpenID Connect compatible identity provider including Auth0, Authentik, and others.
Features:
- Standards-based OIDC integration
- Flexible endpoint configuration
- Custom provider branding
- Works with any OIDC-compliant provider
Tutorial: Generic OIDC Setup Guide
Note: For Keycloak, use the dedicated Keycloak SSO Setup Guide which leverages auto-discovery for simpler configuration.
Quick Start¶
1. Enable SSO¶
Set the master SSO switch in your environment:
# Enable SSO system
SSO_ENABLED=true
# Optional: Keep local admin authentication (recommended)
SSO_PRESERVE_ADMIN_AUTH=true
2. Configure GitHub OAuth (Example)¶
Register OAuth App¶
- Go to GitHub → Settings → Developer settings → OAuth Apps
- Click "New OAuth App"
- Set Authorization callback URL:
https://your-gateway.com/auth/sso/callback/github
- Note the Client ID and Client Secret
Environment Configuration¶
# GitHub OAuth Configuration
SSO_GITHUB_ENABLED=true
SSO_GITHUB_CLIENT_ID=your-github-client-id
SSO_GITHUB_CLIENT_SECRET=your-github-client-secret
# Optional: Auto-create users and trusted domains
SSO_AUTO_CREATE_USERS=true
SSO_TRUSTED_DOMAINS=["yourcompany.com", "github.com"]
Start Gateway¶
3. Test SSO Flow¶
List Available Providers¶
Response:
Initiate SSO Login¶
Response:
{
"authorization_url": "https://github.com/login/oauth/authorize?client_id=...",
"state": "csrf-protection-token"
}
Provider Configuration¶
GitHub OAuth Setup¶
1. Create OAuth App¶
- GitHub Settings → Developer settings → OAuth Apps
- New OAuth App:
- Application name:
MCP Gateway - YourOrg
- Homepage URL:
https://your-gateway.com
- Authorization callback URL:
https://your-gateway.com/auth/sso/callback/github
2. Environment Variables¶
# GitHub OAuth Configuration
SSO_GITHUB_ENABLED=true
SSO_GITHUB_CLIENT_ID=Iv1.a1b2c3d4e5f6g7h8
SSO_GITHUB_CLIENT_SECRET=1234567890abcdef1234567890abcdef12345678
# Organization-based team mapping (optional)
GITHUB_ORG_TEAM_MAPPING={"your-github-org": "developers-team-id"}
3. Team Mapping (Advanced)¶
Map GitHub organizations to Gateway teams:
{
"team_mapping": {
"your-github-org": {
"team_id": "dev-team-uuid",
"role": "member"
},
"admin-github-org": {
"team_id": "admin-team-uuid",
"role": "owner"
}
}
}
Google OAuth Setup¶
1. Google Cloud Console Setup¶
- Google Cloud Console → APIs & Services → Credentials
- Create Credentials → OAuth client ID
- Application type: Web application
- Authorized redirect URIs:
https://your-gateway.com/auth/sso/callback/google
2. Environment Variables¶
# Google OAuth Configuration
SSO_GOOGLE_ENABLED=true
SSO_GOOGLE_CLIENT_ID=123456789012-abcdefghijklmnop.apps.googleusercontent.com
SSO_GOOGLE_CLIENT_SECRET=GOCSPX-1234567890abcdefghijklmnop
# Google Workspace domain restrictions
SSO_TRUSTED_DOMAINS=["yourcompany.com"]
IBM Security Verify Setup¶
1. IBM Security Verify Configuration¶
- IBM Security Verify Admin Console → Applications
- Add application → Custom Application
- Sign-on → Open ID Connect
- Redirect URI:
https://your-gateway.com/auth/sso/callback/ibm_verify
2. Environment Variables¶
# IBM Security Verify OIDC Configuration
SSO_IBM_VERIFY_ENABLED=true
SSO_IBM_VERIFY_CLIENT_ID=your-client-id
SSO_IBM_VERIFY_CLIENT_SECRET=your-client-secret
SSO_IBM_VERIFY_ISSUER=https://your-tenant.verify.ibm.com/oidc/endpoint/default
Okta Setup¶
1. Okta Admin Console¶
- Applications → Create App Integration
- OIDC - OpenID Connect → Web Application
- Sign-in redirect URIs:
https://your-gateway.com/auth/sso/callback/okta
2. Environment Variables¶
# Okta OIDC Configuration
SSO_OKTA_ENABLED=true
SSO_OKTA_CLIENT_ID=0oa1b2c3d4e5f6g7h8i9
SSO_OKTA_CLIENT_SECRET=1234567890abcdef1234567890abcdef12345678
SSO_OKTA_ISSUER=https://your-company.okta.com
Microsoft Entra ID Setup¶
1. Azure Portal Configuration¶
- Azure Portal → Microsoft Entra ID → App registrations
- New registration:
- Name:
MCP Gateway - YourOrg
- Supported account types: Accounts in this organizational directory only
- Redirect URI:
https://your-gateway.com/auth/sso/callback/entra
- After creation, note the Application (client) ID and Directory (tenant) ID
- Certificates & secrets → New client secret → Note the secret value
2. Environment Variables¶
# Microsoft Entra ID OIDC Configuration
SSO_ENTRA_ENABLED=true
SSO_ENTRA_CLIENT_ID=12345678-1234-1234-1234-123456789012
SSO_ENTRA_CLIENT_SECRET=your-client-secret-value
SSO_ENTRA_TENANT_ID=87654321-4321-4321-4321-210987654321
3. API Permissions (Optional)¶
Add Microsoft Graph API permissions for enhanced user profile access:
User.Read
- Basic profile informationprofile
- OpenID Connect profile scopeemail
- Email address access
Full Tutorial: Microsoft Entra ID Setup Guide
Keycloak Setup¶
1. Keycloak Admin Console¶
- Keycloak Admin Console → Clients → Create client
- Client type: OpenID Connect
- Client ID:
mcp-gateway
- Client authentication: On (confidential client)
- Valid redirect URIs:
https://your-gateway.com/auth/sso/callback/keycloak
- After creation, go to Credentials tab and copy the Client secret
2. Environment Variables¶
# Keycloak OIDC Configuration (with auto-discovery)
SSO_KEYCLOAK_ENABLED=true
SSO_KEYCLOAK_BASE_URL=https://keycloak.yourcompany.com
SSO_KEYCLOAK_REALM=master
SSO_KEYCLOAK_CLIENT_ID=mcp-gateway
SSO_KEYCLOAK_CLIENT_SECRET=your-client-secret-value
# Optional: Role and group mapping
SSO_KEYCLOAK_MAP_REALM_ROLES=true
SSO_KEYCLOAK_MAP_CLIENT_ROLES=false
3. Auto-Discovery Benefits¶
Keycloak's auto-discovery reduces configuration by 40%: - Automatically discovers authorization, token, and userinfo endpoints - Only requires base URL and realm name - No need to manually specify 5+ endpoint URLs
Full Tutorial: Keycloak SSO Setup Guide
Generic OIDC Provider Setup¶
Configure any OIDC-compliant provider (Keycloak, Auth0, Authentik, etc.).
1. Obtain Provider Information¶
From your OIDC provider's configuration (usually at https://provider.com/.well-known/openid-configuration
):
- Authorization endpoint:
https://provider.com/auth
- Token endpoint:
https://provider.com/token
- Userinfo endpoint:
https://provider.com/userinfo
- Issuer:
https://provider.com
- Client ID and Secret: From provider's application registration
2. Environment Variables¶
# Generic OIDC Provider Configuration
SSO_GENERIC_ENABLED=true
SSO_GENERIC_PROVIDER_ID=keycloak # or auth0, authentik, etc.
SSO_GENERIC_DISPLAY_NAME=Keycloak
SSO_GENERIC_CLIENT_ID=your-oidc-client-id
SSO_GENERIC_CLIENT_SECRET=your-oidc-client-secret
SSO_GENERIC_AUTHORIZATION_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/auth
SSO_GENERIC_TOKEN_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/token
SSO_GENERIC_USERINFO_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/userinfo
SSO_GENERIC_ISSUER=https://keycloak.company.com/auth/realms/master
SSO_GENERIC_SCOPE=openid profile email # Optional, defaults to this
3. Callback URL Configuration¶
Configure your provider's redirect URI to:
Replace {provider_id}
with your configured SSO_GENERIC_PROVIDER_ID
(e.g., keycloak
, auth0
).
4. Provider-Specific Examples¶
Keycloak:
SSO_GENERIC_PROVIDER_ID=keycloak
SSO_GENERIC_DISPLAY_NAME=Company SSO
SSO_GENERIC_AUTHORIZATION_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/auth
SSO_GENERIC_TOKEN_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/token
SSO_GENERIC_USERINFO_URL=https://keycloak.company.com/auth/realms/master/protocol/openid-connect/userinfo
SSO_GENERIC_ISSUER=https://keycloak.company.com/auth/realms/master
Auth0:
SSO_GENERIC_PROVIDER_ID=auth0
SSO_GENERIC_DISPLAY_NAME=Auth0
SSO_GENERIC_AUTHORIZATION_URL=https://your-tenant.auth0.com/authorize
SSO_GENERIC_TOKEN_URL=https://your-tenant.auth0.com/oauth/token
SSO_GENERIC_USERINFO_URL=https://your-tenant.auth0.com/userinfo
SSO_GENERIC_ISSUER=https://your-tenant.auth0.com/
Authentik:
SSO_GENERIC_PROVIDER_ID=authentik
SSO_GENERIC_DISPLAY_NAME=Authentik
SSO_GENERIC_AUTHORIZATION_URL=https://authentik.company.com/application/o/authorize/
SSO_GENERIC_TOKEN_URL=https://authentik.company.com/application/o/token/
SSO_GENERIC_USERINFO_URL=https://authentik.company.com/application/o/userinfo/
SSO_GENERIC_ISSUER=https://authentik.company.com/application/o/mcp-gateway/
Advanced Configuration¶
Trusted Domains¶
Restrict SSO access to specific email domains:
# JSON array of trusted domains
SSO_TRUSTED_DOMAINS=["yourcompany.com", "partner.org", "contractor.net"]
Only users with email addresses from these domains can authenticate via SSO.
Auto User Creation¶
Control automatic user provisioning:
# Enable automatic user creation (default: true)
SSO_AUTO_CREATE_USERS=true
# Disable to manually approve SSO users
SSO_AUTO_CREATE_USERS=false
Team Mapping Rules¶
Configure automatic team assignment based on SSO provider attributes:
{
"team_mapping": {
"github_org_name": {
"team_id": "uuid-of-gateway-team",
"role": "member",
"conditions": {
"email_domain": "company.com"
}
},
"google_workspace_domain": {
"team_id": "uuid-of-workspace-team",
"role": "owner",
"conditions": {
"email_verified": true
}
}
}
}
API Reference¶
Public Endpoints¶
List Available Providers¶
Response:
Initiate SSO Login¶
Parameters:
provider_id
: Provider identifier (github
,google
,ibm_verify
,entra
,keycloak
,okta
, or configured generic provider ID)redirect_uri
: Callback URL after authenticationscopes
: Optional space-separated OAuth scopes
Response:
{
"authorization_url": "https://provider.com/oauth/authorize?...",
"state": "csrf-protection-token"
}
Handle SSO Callback¶
This endpoint is called by the SSO provider after user authentication.
Response:
{
"access_token": "jwt-session-token",
"token_type": "bearer",
"expires_in": 604800,
"user": {
"email": "user@example.com",
"full_name": "John Doe",
"provider": "github"
}
}
Admin Endpoints¶
All admin endpoints require admin.sso_providers
permissions.
Create SSO Provider¶
POST /auth/sso/admin/providers
Authorization: Bearer <admin-jwt-token>
Content-Type: application/json
{
"id": "custom_provider",
"name": "custom_provider",
"display_name": "Custom Provider",
"provider_type": "oidc",
"client_id": "client-id",
"client_secret": "client-secret",
"authorization_url": "https://provider.com/oauth/authorize",
"token_url": "https://provider.com/oauth/token",
"userinfo_url": "https://provider.com/oauth/userinfo",
"issuer": "https://provider.com",
"scope": "openid profile email",
"trusted_domains": ["company.com"],
"auto_create_users": true
}
List All Providers¶
Update Provider¶
PUT /auth/sso/admin/providers/{provider_id}
Authorization: Bearer <admin-jwt-token>
Content-Type: application/json
{
"display_name": "Updated Provider Name",
"is_enabled": false
}
Delete Provider¶
Security Considerations¶
Client Secret Encryption¶
Client secrets are encrypted using Fernet (AES 128) before database storage:
# Automatic encryption in SSOService
provider_data["client_secret_encrypted"] = self._encrypt_secret(client_secret)
PKCE Protection¶
All OAuth flows use PKCE (Proof Key for Code Exchange) for enhanced security:
CSRF Protection¶
OAuth state parameters prevent cross-site request forgery:
Session Security¶
- HTTP-only cookies prevent XSS attacks
- Secure flag for HTTPS deployments
- SameSite=Lax protection
- 10-minute OAuth session expiration
Troubleshooting¶
Common Issues¶
SSO Endpoints Return 404¶
Problem: SSO routes not available Solution: Ensure SSO_ENABLED=true
and restart gateway
# Check SSO status
curl -I http://localhost:8000/auth/sso/providers
# Should return 200 if enabled, 404 if disabled
OAuth Callback Errors¶
Problem: Invalid redirect URI Solution: Verify callback URL matches provider configuration exactly
# Correct format
https://your-gateway.com/auth/sso/callback/github
# Common mistakes
https://your-gateway.com/auth/sso/callback/github/ # Extra slash
http://your-gateway.com/auth/sso/callback/github # HTTP instead of HTTPS
User Creation Fails¶
Problem: Email domain not trusted Solution: Add domain to trusted domains list
Debug Mode¶
Enable verbose SSO logging:
Check logs for detailed OAuth flow information:
Health Checks¶
Verify SSO provider connectivity:
# Test provider endpoints
curl -I https://github.com/login/oauth/authorize
curl -I https://github.com/login/oauth/access_token
curl -I https://api.github.com/user
Migration Guide¶
From Local Auth Only¶
-
Enable SSO alongside existing authentication:
-
Configure first provider (e.g., GitHub)
-
Test SSO flow with test users
-
Gradually migrate production users
-
Optional: Disable local auth after full migration
Adding New Providers¶
-
Implement provider-specific user info normalization in
SSOService._normalize_user_info
-
Add environment variables in
config.py
-
Update bootstrap utilities in
sso_bootstrap.py
-
Test integration thoroughly
Best Practices¶
Production Deployment¶
- Use HTTPS for all SSO callbacks
- Secure client secrets in vault/secret management
- Monitor failed authentications
- Regular secret rotation
- Audit SSO access logs
User Experience¶
- Clear provider labeling (GitHub, Google, etc.)
- Graceful error handling for auth failures
- Fallback to local auth if SSO unavailable
- User session management
Security Hardening¶
- Restrict trusted domains to organization emails
- Enable audit logging for admin operations
- Regular provider configuration reviews
- Monitor unusual auth patterns
Integration Examples¶
Frontend Integration¶
// Check available SSO providers
const providers = await fetch('/auth/sso/providers').then(r => r.json());
// Initiate SSO login
const redirectUrl = `${window.location.origin}/dashboard`;
const ssoResponse = await fetch(
`/auth/sso/login/github?redirect_uri=${encodeURIComponent(redirectUrl)}`
).then(r => r.json());
// Redirect user to SSO provider
window.location.href = ssoResponse.authorization_url;
CLI Integration¶
#!/bin/bash
# CLI SSO authentication helper
GATEWAY_URL="https://your-gateway.com"
PROVIDER="github"
# Get authorization URL
AUTH_RESPONSE=$(curl -s "$GATEWAY_URL/auth/sso/login/$PROVIDER?redirect_uri=urn:ietf:wg:oauth:2.0:oob")
AUTH_URL=$(echo "$AUTH_RESPONSE" | jq -r '.authorization_url')
echo "Open this URL in your browser:"
echo "$AUTH_URL"
echo "Enter the authorization code:"
read -r AUTH_CODE
# Exchange code for token (manual callback simulation)
# Note: In practice, this would be handled by the callback endpoint
API Client Integration¶
import requests
import webbrowser
from urllib.parse import urlparse, parse_qs
# SSO authentication for API clients
class SSOAuthenticator:
def __init__(self, gateway_url, provider):
self.gateway_url = gateway_url
self.provider = provider
def authenticate(self):
# Get authorization URL
response = requests.get(
f"{self.gateway_url}/auth/sso/login/{self.provider}",
params={"redirect_uri": "http://localhost:8080/callback"}
)
auth_data = response.json()
# Open browser for user authentication
webbrowser.open(auth_data["authorization_url"])
# Wait for callback (implement callback server)
# Return JWT token for API access
return self.handle_callback()