# 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

```mermaid
sequenceDiagram
    participant C as MCP Client
    participant A as K-AI Resource API
    participant S as K-AI Auth Server
    participant U as User browser

    C->>A: GET /.well-known/oauth-authorization-server
    A-->>C: discovery metadata
    C->>S: POST /auth/oauth/register
    S-->>C: client_id, client_secret
    C->>U: open /auth/oauth/authorize with PKCE challenge
    U->>S: Login
    S-->>U: Redirect with code
    U-->>C: Deliver code
    C->>S: POST /auth/oauth/token
    S-->>C: access_token, refresh_token
    C->>A: API call with Bearer access_token
    A-->>C: Response
```

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.

{% hint style="warning" %}
Token verification is performed server-side by K-AI's resource APIs, not by clients. Treat the access token as an opaque bearer credential.
{% endhint %}

## Spec details

* **PKCE:** `S256` required. 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 a `client_secret` with `invalid_client 401`.
* **Scope:** `mcp`.
* **DCR rate limit:** 5 requests per minute per IP.

## Endpoints

| Purpose                          | URL                                                    | Method |
| -------------------------------- | ------------------------------------------------------ | ------ |
| 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

* **`401` after 15 min:** access token expired. Refresh it. Most MCP clients do this automatically.
* **`invalid_grant` on 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 `state` returned to `redirect_uri` does not match what the client sent. Persist `state` for 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_client` on token exchange:** the `client_id` does not match the one returned by DCR, or the `client_secret` is wrong or missing. K-AI Auth supports confidential clients only — every token request must carry a `client_secret`.
* **`invalid_request` with `code_verifier`:** the `code_verifier` does not match the `code_challenge` used at the authorization step. Regenerate both as a pair.

For the higher-level narrative on K-AI authentication, see [OAuth 2.1](/knowledge-ai/authentication/oauth.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://k-ai.gitbook.io/knowledge-ai/k-ai-mcp/oauth-flow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
