OAuth flow (detailed)
This page is the reference for anyone implementing a custom MCP client or debugging OAuth issues against K-AI. Both MCP servers (api-retrieval and api-audit) share a single Authorization Server at https://auth-api.kai-studio.ai. A token obtained against either resource server is accepted on both.
Sequence diagram
Every ~15 minutes the client refreshes the access token by calling /auth/oauth/token with grant_type=refresh_token; the response contains a new access token and a rotated refresh token.
Step-by-step
1. Discovery
GET https://api-retrieval.kai-studio.ai/.well-known/oauth-authorization-server (or the api-audit equivalent — both return identical metadata). The response contains registration_endpoint, authorization_endpoint, token_endpoint, revocation_endpoint, supported response/grant types, PKCE methods, and scopes.
2. Dynamic Client Registration (RFC 7591)
POST to /auth/oauth/register with client_name, redirect_uris, grant_types, and token_endpoint_auth_method. The server returns a fresh client_id and client_secret. K-AI Auth supports confidential clients only — every MCP client (Claude Desktop, Cursor, Le Chat) registers with a client_id + client_secret and stores the secret locally.
3. Authorization request
Generate a code_verifier (43–128 chars), derive code_challenge = BASE64URL(SHA256(code_verifier)), pick a random state, and open the user's browser at /auth/oauth/authorize with response_type=code, client_id, redirect_uri, scope=mcp, state, code_challenge, code_challenge_method=S256. The user signs in via magic code or Microsoft SSO.
4. Authorization code delivery
The Authorization Server redirects to redirect_uri?code=<code>&state=<state>. The client must verify state matches what it sent.
5. Token exchange
POST to /auth/oauth/token with grant_type=authorization_code, code, redirect_uri, client_id, and code_verifier. The server returns access_token (JWT, 15 min TTL) and refresh_token (7 days TTL).
6. Authenticated tool calls
Subsequent tool invocations go to https://api-retrieval.kai-studio.ai/mcp or https://api-audit.kai-studio.ai/mcp with the header Authorization: Bearer <access_token>.
7. Refresh
When the access token nears expiry, POST to /auth/oauth/token with grant_type=refresh_token. The server returns a new access token and a rotated refresh token. The previous refresh token is invalidated immediately.
Token verification is performed server-side by K-AI's resource APIs, not by clients. Treat the access token as an opaque bearer credential.
Spec details
PKCE:
S256required. Plaintext (plain) not accepted.Token lifetimes: access token 15 min, refresh token 7 days.
Refresh rotation: mandatory. Each refresh call returns a new refresh token and invalidates the old one immediately. If a revoked refresh token is presented again, the entire token chain is revoked and the user must re-authorize.
Authorization code TTL: 10 minutes, single-use.
Token endpoint auth methods supported:
client_secret_basic,client_secret_post. Confidential clients only — the token endpoint rejects requests without aclient_secretwithinvalid_client 401.Scope:
mcp.DCR rate limit: 5 requests per minute per IP.
Endpoints
Discovery (from either K-AI API)
https://<api>/.well-known/oauth-authorization-server
GET
Dynamic Client Registration
https://auth-api.kai-studio.ai/auth/oauth/register
POST
Authorization
https://auth-api.kai-studio.ai/auth/oauth/authorize
GET
Token exchange and refresh
https://auth-api.kai-studio.ai/auth/oauth/token
POST
Revocation
https://auth-api.kai-studio.ai/auth/oauth/revoke
POST
Both api-retrieval.kai-studio.ai and api-audit.kai-studio.ai publish their own discovery document, but both point to the same Authorization Server. Register your client once; the resulting tokens are accepted on both APIs.
Troubleshooting
401after 15 min: access token expired. Refresh it. Most MCP clients do this automatically.invalid_granton refresh: the stored refresh token is stale — an older one was used after a successful rotation. Always replace the stored refresh token with the latest one returned.CSRF / state mismatch: the
statereturned toredirect_uridoes not match what the client sent. Persiststatefor the lifetime of the flow.Microsoft SSO loop: confirm the user's browser is not blocking third-party cookies on
auth-api.kai-studio.ai.DCR rejected (
429): the rate limit of 5 registrations per minute per IP was exceeded. Wait and retry.invalid_clienton token exchange: theclient_iddoes not match the one returned by DCR, or theclient_secretis wrong or missing. K-AI Auth supports confidential clients only — every token request must carry aclient_secret.invalid_requestwithcode_verifier: thecode_verifierdoes not match thecode_challengeused at the authorization step. Regenerate both as a pair.Agent hangs waiting for a browser: the client received a
401, treated it as "start OAuth", and opened an authorization request nobody will answer. If the caller is an unattended agent, authenticate it with an Organization API key instead and treat401as fatal.
For the higher-level narrative on K-AI authentication, see OAuth 2.1. For unattended callers, see Autonomous agents (API key).
Last updated