OAuth
Connect an MCP or API client with the OAuth 2.0 authorization server.
Cadence is an OAuth 2.0 authorization server. A client that drives the API or the
MCP endpoint on your behalf obtains an mcoa_ access token
through the flow below, rather than carrying an API token you minted by hand.
Every client is a public client using PKCE with the S256 method — there is no
client secret. The only scope is mcp.
Replace https://cadence.example.com with the address of your Cadence instance.
Discovery
A client finds the endpoints from two discovery documents.
GET /.well-known/oauth-authorization-server returns the authorization-server
metadata:
{
"issuer": "https://cadence.example.com",
"authorization_endpoint": "https://cadence.example.com/oauth/authorize",
"token_endpoint": "https://cadence.example.com/oauth/token",
"registration_endpoint": "https://cadence.example.com/oauth/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"],
"scopes_supported": ["mcp"]
}GET /.well-known/oauth-protected-resource names the protected resource and the
server that guards it:
{
"resource": "https://cadence.example.com/mcp",
"authorization_servers": ["https://cadence.example.com"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["mcp"]
}A 401 from the API or MCP points here through its WWW-Authenticate header, so
a client can discover where to authenticate. See
Authentication.
Register a client
POST /oauth/register registers a client dynamically. Send client_name,
redirect_uris, and optionally logo_uri:
{
"client_name": "My integration",
"redirect_uris": ["https://myapp.example.com/callback"]
}A successful registration returns 201:
{
"client_id": "…",
"client_id_issued_at": 1717171717,
"client_name": "My integration",
"redirect_uris": ["https://myapp.example.com/callback"],
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code"],
"response_types": ["code"]
}Invalid metadata is refused with 400 and
{ "error": "invalid_client_metadata", "error_description": "…" }.
Registration is rate-limited per source address: too many registrations from one
address in a short window are refused with 429.
Authorize and consent
Send the operator's browser to GET /oauth/authorize with client_id,
redirect_uri, response_type=code, scope, state, code_challenge, and
code_challenge_method=S256. PKCE is required — an authorize request without a
code challenge is refused.
If the operator is signed out, they are sent to sign in first, then returned to
the consent screen. When they approve, Cadence redirects to your redirect_uri
with a code and the state you sent. If they decline, it redirects with
error=access_denied.
Exchange the code for a token
POST /oauth/token with grant_type=authorization_code, the code, the
matching redirect_uri, your client_id, and the code_verifier for your PKCE
challenge:
{
"access_token": "mcoa_…",
"refresh_token": "mcor_…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "mcp"
}Refresh with grant_type=refresh_token and your refresh_token at the same
endpoint; each refresh rotates the refresh token.
The token endpoint refuses with 400 and one of these error codes:
invalid_client— the client is unknown.unsupported_grant_type— thegrant_typeis not one this server issues.invalid_grant— everything else the exchange rejects: a bad or expired code, a PKCE verifier that does not match, or a replayed or expired refresh token.
Revoke a token
POST /oauth/revoke with the token (an mcoa_ access token or an mcor_
refresh token) and your client_id revokes the whole grant — its access and
refresh tokens all stop working. Per the revocation standard, this endpoint
always returns 200, whether or not the token was known, so it reveals nothing
about a token's validity.
An operator can also disconnect a client from the web interface; see connected applications.
Sign in with Google
An operator signs in to the web interface with Google at GET /auth/google,
which returns through GET /auth/google/callback. Signing in with Google links
to an existing operator account; it does not create one.