Skip to main content

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

PathPurpose
GET /.well-known/openid-configurationOIDC Discovery 1.0 metadata. Superset of OAuth AS metadata.
GET /.well-known/oauth-authorization-serverRFC 8414 OAuth authorization server metadata.
GET /oauth/jwksPublic 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:

ParamRequiredNotes
client_idyesThe OAuth client's identifier. From DCR or pre-registration.
response_typeyescode (always).
redirect_uriyesMust exactly match a registered URI for this client.
scopeyesSpace-separated scope strings.
staterecommendedOpaque round-trip value for CSRF protection.
code_challengeyesBase64url-encoded SHA256 of code_verifier.
code_challenge_methodyesS256.
audienceoptionalResource 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_request
  • invalid_client
  • invalid_grant
  • unauthorized_client
  • unsupported_grant_type
  • invalid_scope
  • access_denied
  • server_error
  • temporarily_unavailable

For introspection and protected resource calls, also:

  • invalid_token (RFC 6750)
  • insufficient_scope (RFC 6750)