OAuth endpoints reference
Standard OAuth 2.1 + OpenID Connect endpoints exposed by the AuthSec backend (proxied through Hydra). These are the endpoints OAuth clients hit — your MCP server's SDK uses a different surface (see Resource servers API).
Discovery
| Path | Purpose |
|---|---|
GET /.well-known/openid-configuration | OIDC Discovery 1.0 metadata. Superset of OAuth AS metadata. |
GET /.well-known/oauth-authorization-server | RFC 8414 OAuth authorization server metadata. |
GET /oauth/jwks | Public keys for local JWT verification. |
Clients use discovery to find the other endpoint URLs without hardcoding them.
Authorization
GET /oauth/authorize?...
Standard RFC 6749 authorization-code flow with PKCE (RFC 7636) required.
Query parameters:
| Param | Required | Notes |
|---|---|---|
client_id | yes | The OAuth client's identifier. From DCR or pre-registration. |
response_type | yes | code (always). |
redirect_uri | yes | Must exactly match a registered URI for this client. |
scope | yes | Space-separated scope strings. |
state | recommended | Opaque round-trip value for CSRF protection. |
code_challenge | yes | Base64url-encoded SHA256 of code_verifier. |
code_challenge_method | yes | S256. |
audience | optional | Resource URI to bind the token to. Sets the aud claim. |
Response: 302 redirect to redirect_uri with ?code=...&state=... on success, or ?error=...&error_description=... on denial.
Token exchange
POST /oauth/token
Content-Type: application/x-www-form-urlencoded.
For the authorization-code flow:
grant_type=authorization_code
&code=<code from /oauth/authorize redirect>
&redirect_uri=<same as authorize step>
&client_id=<client>
&client_secret=<secret> # confidential clients only
&code_verifier=<PKCE verifier matching code_challenge>
Response (200):
{
"access_token": "eyJhbGc...",
"refresh_token": "ory_rt_...",
"id_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "rs-xyz:tools:read"
}
For refresh:
grant_type=refresh_token
&refresh_token=<rt>
&client_id=<client>
&client_secret=<secret>
For client_credentials (M2M):
grant_type=client_credentials
&client_id=<client>
&client_secret=<secret>
&scope=<requested scope>
Introspection
POST /oauth/introspect
Content-Type: application/x-www-form-urlencoded. Basic auth required — for resource server callers, the credentials are rs_id : introspection_secret. For OAuth clients, use their own client_id : client_secret.
token=eyJhbGc...
Response:
{
"active": true,
"sub": "alice@example.com",
"aud": "https://your-mcp.example.com/mcp",
"scope": "rs-xyz:tools:read rs-xyz:tools:write",
"exp": 1730000000,
"iat": 1729996400,
"client_id": "claude-desktop"
}
If active is false, the token is revoked or never existed. Other claims may be omitted.
The scope field is RBAC-resolved when called by a resource server: filtered to what the user currently has, not what the token was issued with. See Token introspection vs JWT.
Revocation
POST /oauth/revoke (RFC 7009)
Content-Type: application/x-www-form-urlencoded. Basic auth.
token=eyJhbGc...
&token_type_hint=access_token # or refresh_token
Response: 200 with empty body on success. Revoked tokens fail active on subsequent introspection.
UserInfo
GET /oauth/userinfo or POST /oauth/userinfo
Bearer auth required.
Response:
{
"sub": "alice@example.com",
"email": "alice@example.com",
"email_verified": true,
"name": "Alice Example"
}
OIDC standard. Returns whatever profile claims the user consented to share.
Dynamic Client Registration
POST /oauth/register (RFC 7591)
Open by default (no auth required). The defaults can be tightened per resource server by editing registration_modes.
Request:
{
"client_name": "Claude Desktop",
"redirect_uris": ["http://localhost:33417/oauth/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none"
}
Response:
{
"client_id": "abc-123",
"client_id_issued_at": 1730000000,
"redirect_uris": ["http://localhost:33417/oauth/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none"
}
Public clients (no client_secret) are issued when token_endpoint_auth_method is none. Use PKCE; required for public clients.
Error shapes
All OAuth endpoints follow RFC 6749:
{
"error": "invalid_grant",
"error_description": "The provided authorization grant is invalid, expired, revoked..."
}
Standard error codes:
invalid_requestinvalid_clientinvalid_grantunauthorized_clientunsupported_grant_typeinvalid_scopeaccess_deniedserver_errortemporarily_unavailable
For introspection and protected resource calls, also:
invalid_token(RFC 6750)insufficient_scope(RFC 6750)
Related
- Resource servers API — the AuthSec-specific surface
- How to add OAuth to an MCP server
- Troubleshoot OAuth tokens