README
¶
Dex OAuth Provider Example
This example demonstrates how to use the Dex OAuth provider with the mcp-oauth library.
Features Demonstrated
- OIDC Discovery: Automatically discovers Dex authorization and token endpoints
- Connector ID Support: Optional parameter to bypass Dex's connector selection UI
- Groups Claim: Retrieves user group memberships from Dex
- Refresh Token Rotation: Properly handles Dex's strict refresh token rotation
- Protected Resources: Demonstrates group-based access control
Prerequisites
- Running Dex Instance: You need a Dex server running and accessible
- Dex Client Configuration: Register this application as an OAuth client in Dex
Dex Configuration Example
Add this client to your Dex configuration:
# dex-config.yaml
staticClients:
- id: demo-client
secret: demo-secret
name: 'Dex OAuth Example'
redirectURIs:
- 'http://localhost:8080/oauth/callback'
connectors:
- type: github
id: github
name: GitHub
config:
clientID: $GITHUB_CLIENT_ID
clientSecret: $GITHUB_CLIENT_SECRET
redirectURI: https://dex.example.com/callback
orgs:
- name: your-org
Environment Variables
Set the following environment variables before running the example:
# Required
export DEX_ISSUER_URL="https://dex.example.com" # Your Dex issuer URL
export DEX_CLIENT_ID="demo-client" # OAuth client ID
export DEX_CLIENT_SECRET="demo-secret" # OAuth client secret
# Optional
export DEX_CONNECTOR_ID="github" # Skip connector selection (use specific connector)
Running the Example
First, generate go.mod files and build all examples from the repository root:
make build-examples
Then run the example:
cd examples/dex
go run main.go
The server will start on http://localhost:8080
Usage
-
Visit the home page: Open http://localhost:8080 in your browser
-
Sign in: Click the "Sign in with Dex" button
-
Connector Selection (if DEX_CONNECTOR_ID not set):
- Dex will show a list of configured connectors (GitHub, LDAP, etc.)
- Choose your preferred authentication method
-
Connector Selection (if DEX_CONNECTOR_ID is set):
- You'll be redirected directly to the specified connector
- No connector selection screen will be shown
-
Authenticate: Complete authentication with your chosen provider
-
Access Protected Resource: Try accessing http://localhost:8080/api/resource
- You need to be in the "developers" or "admins" group
- The response will show your user information and groups
What Makes This Dex-Specific?
1. Connector ID Parameter
The DEX_CONNECTOR_ID environment variable enables the Dex-specific feature to bypass the connector selection UI:
dexProvider, err := dex.NewProvider(&dex.Config{
IssuerURL: issuerURL,
ClientID: clientID,
ClientSecret: clientSecret,
RedirectURL: "http://localhost:8080/oauth/callback",
ConnectorID: connectorID, // Dex-specific: skip connector selection
})
2. Groups Claim
The provider automatically includes the groups scope in default scopes:
// Default scopes (automatically included):
// - openid
// - profile
// - email
// - groups <- Dex-specific
// - offline_access
3. Refresh Token Rotation
Dex enforces strict refresh token rotation. The provider handles this automatically by returning the new refresh token from each refresh operation.
Group-Based Access Control
The example demonstrates how to use Dex group memberships for access control:
// Check if user is in required group
hasAccess := false
for _, group := range userInfo.Groups {
if group == "developers" || group == "admins" {
hasAccess = true
break
}
}
if !hasAccess {
http.Error(w, "Forbidden: requires 'developers' or 'admins' group", http.StatusForbidden)
return
}
Security Considerations
-
HTTPS in Production: This example uses HTTP for simplicity. In production:
- Use HTTPS for all OAuth endpoints
- Configure Dex with HTTPS
- Update redirect URIs to use HTTPS
-
Secret Management: Don't hardcode secrets. In production:
- Use environment variables (as shown)
- Or use secret management systems (Vault, AWS Secrets Manager, etc.)
-
Group Validation: The groups claim is validated for security:
- Maximum 100 groups per user
- Maximum 256 characters per group name
- Prevents memory exhaustion attacks
Troubleshooting
"OIDC discovery failed"
- Check that
DEX_ISSUER_URLis correct and accessible - Ensure Dex is running and reachable from your machine
- Verify the discovery document is available at
$DEX_ISSUER_URL/.well-known/openid-configuration
"Failed to exchange code"
- Verify
DEX_CLIENT_IDandDEX_CLIENT_SECRETmatch your Dex configuration - Check that the redirect URI in Dex config matches:
http://localhost:8080/oauth/callback
"Connector not found"
- If using
DEX_CONNECTOR_ID, ensure the connector ID matches one in your Dex config - Check Dex logs for connector configuration errors
"Forbidden: requires developers or admins group"
- Your user account needs to be in the "developers" or "admins" group
- Check your identity provider's group configuration
- Verify Dex is configured to pass through group claims