Troubleshooting
This guide covers common issues when using Casdoor with MCP servers, whether you're connecting to Casdoor's built-in MCP server or using Casdoor as an OAuth provider for your own MCP server.
Common Errors
401 Unauthorized from MCP Server
Symptom: MCP server rejects requests with 401 Unauthorized status code.
Causes:
- Access token has expired
- Token's
aud(audience) claim doesn't match the MCP server's resource URI - Missing
Authorization: Bearerheader in requests - Token was issued for a different resource
Fix:
- Decode your token at jwt.io and check the
expclaim for expiration - Verify the
audclaim matches your MCP server's URI exactly (including scheme, host, and port) - Ensure requests include the header:
Authorization: Bearer YOUR_TOKEN - If using the
resourceparameter during OAuth, confirm it matches the MCP server URI
# Example: Check token claims
curl -X GET https://your-mcp-server.com/api/mcp \
-H "Authorization: Bearer YOUR_TOKEN"
# If 401, inspect token at jwt.io:
# - exp: 1735689600 (must be in future)
# - aud: "https://your-mcp-server.com" (must match server URI)
# - scope: "read:application" (must include required scopes)
CORS Errors in Browser
Symptom: Browser console shows CORS errors when MCP client attempts to connect to Casdoor.
Causes:
- Casdoor CORS settings don't include the MCP client's origin
- Preflight requests are being blocked
- Wildcard CORS is disabled for security
Fix:
- Log into Casdoor admin panel
- Navigate to your application configuration
- Add the MCP client's origin to the CORS Allowed Origins field
- Include the full origin:
https://client-domain.com(with scheme and port if non-standard) - For local development, add
http://localhost:PORT
# Example CORS configuration:
https://claude.ai
https://cursor.sh
http://localhost:3000
Redirect URI Mismatch
Symptom: OAuth flow fails with redirect_uri_mismatch error.
Causes:
- The
redirect_uriin the authorization request doesn't exactly match the application configuration - Scheme mismatch (
httpvshttps) - Port number missing or incorrect
- Trailing slash mismatch
Fix:
- Copy the exact
redirect_urifrom your authorization request - In Casdoor, edit the application configuration
- Add the exact URI to Redirect URLs field (must match character-for-character)
- Ensure scheme, host, port, and path all match exactly
# These are all different redirect URIs:
http://localhost:3000/callback
https://localhost:3000/callback # Different scheme
http://localhost:3000/callback/ # Trailing slash
http://localhost:3001/callback # Different port
Discovery Endpoint 404
Symptom: Attempting to fetch .well-known discovery document returns 404.
Causes:
- Using wrong discovery path for your use case
- Casdoor configuration doesn't expose discovery endpoints
- Application not configured as OIDC provider
Fix:
Try these discovery endpoints in order:
OAuth Authorization Server Metadata (RFC 8414):
curl https://your-casdoor.com/.well-known/oauth-authorization-serverOpenID Connect Discovery:
curl https://your-casdoor.com/.well-known/openid-configurationOAuth Protected Resource Metadata (RFC 9470):
curl https://your-casdoor.com/.well-known/oauth-protected-resource
For MCP servers acting as resource servers, use the oauth-protected-resource endpoint to advertise OAuth requirements.
DCR Registration Rejected
Symptom: Dynamic Client Registration (DCR) request fails with error.
Causes:
- Organization has DCR disabled in settings
- Registration request missing required fields
- Software statement rejected or invalid
- Rate limiting on registration endpoint
Fix:
Navigate to your organization settings in Casdoor
Enable Dynamic Client Registration toggle
Configure Allowed Redirect URI Patterns to restrict client URIs
For registration requests, include all required metadata:
{
"client_name": "My MCP Client",
"redirect_uris": ["https://client.example.com/callback"],
"grant_types": ["authorization_code"],
"token_endpoint_auth_method": "client_secret_basic"
}
For more details, see the Dynamic Client Registration documentation.
Consent Screen Not Showing
Symptom: OAuth flow completes without showing user consent screen.
Causes:
- Application's Consent Policy is set to "Never"
- User has previously granted consent and policy is "Once"
- Session authentication bypasses consent
Fix:
- Edit your application in Casdoor admin panel
- Set Consent Policy to:
- Always: Show consent on every authorization request
- Once: Show consent only on first authorization (recommended)
- Save the application configuration
- Clear user's previous consent if testing (revoke application access)
The consent screen displays requested scopes with their display names and descriptions from your scope configuration.
insufficient_scope Error
Symptom: MCP tool calls fail with insufficient_scope JSON-RPC error.
Causes:
- Access token doesn't include the scope required by the tool
- Token was requested with incorrect scopes
- Scope names don't match server expectations
Fix:
Check the error response for
required_scopeandgranted_scopes:{
"error": {
"code": -32001,
"message": "insufficient_scope",
"data": {
"tool": "add_application",
"granted_scopes": ["read:application"],
"required_scope": "write:application"
}
}
}Request a new token with the required scope:
curl -X POST https://your-casdoor.com/api/login/oauth/access_token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=read:application write:application"
For available scopes, see the Authorization and Scopes documentation.
invalid_target / Resource Error
Symptom: Authorization request fails with invalid_target or invalid_resource error.
Causes:
resourceparameter is not a valid URI (RFC 8707)- Resource URI missing scheme (
http://orhttps://) - Resource parameter conflicts with token audience
Fix:
Ensure
resourceparameter is a full URL:# Correct:
resource=https://your-server.com
resource=https://api.example.com:8080
# Incorrect:
resource=your-server.com # Missing scheme
resource=localhost:3000 # Missing schemeThe
resourcevalue becomes theaudclaim in the access tokenResource must match the MCP server's expected audience exactly
Claude Desktop / Cursor Connection Failures
Symptom: Claude Desktop or Cursor IDE fails to connect to MCP server with OAuth errors.
Causes:
- MCP server not returning valid Protected Resource Metadata (PRM)
WWW-Authenticateheader malformed or missing- Discovery endpoint not accessible
- Token validation failing
Fix:
Verify PRM endpoint returns valid JSON:
curl https://your-mcp-server.com/.well-known/oauth-protected-resourceExpected response:
{
"resource": "https://your-mcp-server.com",
"authorization_servers": [
"https://your-casdoor.com"
]
}Check WWW-Authenticate header on unauthorized requests:
curl -v https://your-mcp-server.com/api/mcpExpected header:
WWW-Authenticate: Bearer realm="mcp-server",
authorization_uri="https://your-casdoor.com/login/oauth/authorize",
scope="read:application write:application"Test complete OAuth flow with curl:
# 1. Get authorization code (requires browser)
# 2. Exchange for token
curl -X POST https://your-casdoor.com/api/login/oauth/access_token \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE" \
-d "redirect_uri=YOUR_REDIRECT_URI" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
# 3. Test MCP endpoint with token
curl https://your-mcp-server.com/api/mcp \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Debugging Tools
MCP Inspector
The official MCP Inspector helps test MCP connections interactively:
npx @modelcontextprotocol/inspector
Features:
- Interactive tool browser and testing
- Real-time JSON-RPC request/response viewer
- OAuth flow testing
- Connection diagnostics
Testing Discovery Endpoints
Verify each discovery endpoint returns valid JSON:
# OAuth Authorization Server
curl -s https://your-casdoor.com/.well-known/oauth-authorization-server | jq
# OIDC Configuration
curl -s https://your-casdoor.com/.well-known/openid-configuration | jq
# Protected Resource (for MCP resource servers)
curl -s https://your-mcp-server.com/.well-known/oauth-protected-resource | jq
Inspecting JWT Tokens
Use jwt.io to decode access tokens and verify claims:
Key claims to check:
aud(audience): Must match MCP server URIscope: Must include required scopes for toolsexp(expiration): Must be in the future (Unix timestamp)iss(issuer): Should match Casdoor's authorization server URLsub(subject): User identifierclient_id: Application/client that received the token
# Alternative: Decode token with jq
echo "YOUR_JWT_TOKEN" | cut -d. -f2 | base64 -d | jq
Token Introspection Endpoint
Casdoor provides a token introspection endpoint (RFC 7662) to validate and inspect tokens:
curl -X POST https://your-casdoor.com/api/login/oauth/introspect \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "CLIENT_ID:CLIENT_SECRET" \
-d "token=ACCESS_TOKEN"
Response includes:
{
"active": true,
"scope": "read:application write:application",
"client_id": "your-client-id",
"username": "admin",
"exp": 1735689600,
"iat": 1735603200,
"aud": "https://your-mcp-server.com"
}
Testing with curl
Manual OAuth flow testing with curl:
# 1. Test authorization endpoint (requires browser)
# Open in browser:
https://your-casdoor.com/login/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=http://localhost:8080/callback&
response_type=code&
scope=read:application&
state=random-state
# 2. Exchange authorization code for token
curl -X POST https://your-casdoor.com/api/login/oauth/access_token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=http://localhost:8080/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
# 3. Use access token with MCP server
curl https://your-mcp-server.com/api/mcp \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Debug Logging
Enable debug logging in your MCP client or server to see detailed OAuth flows:
For MCP clients:
- Check client configuration for debug/verbose mode
- Review client logs for OAuth redirect, token exchange, and API calls
- Capture network traffic with browser DevTools or mitmproxy
For MCP servers:
- Enable server debug logging to see incoming requests
- Log token validation results (success/failure and reasons)
- Monitor authorization checks and scope validation
Network Debugging
Use browser DevTools or network analysis tools:
Browser DevTools (F12):
- Network tab shows all OAuth redirects and API calls
- Console tab displays JavaScript errors
- Application tab shows stored tokens and cookies
mitmproxy for CLI clients:
mitmproxy -p 8080
# Configure client to use proxy: http://localhost:8080Wireshark for low-level packet analysis
Related Documentation
- Authorization and Scopes - Complete scope reference
- Error Handling - JSON-RPC error codes
- Authentication - OAuth flows and token management
- Custom Scopes - Configuring custom scopes for Agent applications
- Dynamic Client Registration - DCR setup and configuration