Concept

OAuth 2.1 with Dynamic Client Registration

knowmind is an OAuth 2.1 provider with Dynamic Client Registration per RFC 7591. Custom connectors in Claude.ai, ChatGPT and Cursor register themselves automatically — nobody manually creates a client or pastes a secret.

What this is about

Classic OAuth setups require a pre-configured client app: a client ID, a client secret, and a hard-wired redirect URI. For custom connectors in browser AI tools that is impractical — the client only exists once the user adds it. The IETF specified RFC 7591 for exactly this case: the client registers itself with the authorization server at runtime. knowmind permits this only for custom connectors whose redirect URIs match an allowlist of MCP-capable platforms.

Sequence in detail

OAuth 2.1 flow with Dynamic Client Registration and PKCE. Steps 1-2: discovery. Steps 3-4: registration. Steps 5-8: authorization code grant with PKCE.
  1. Discovery: the connector reads the OAuth discovery metadata at /.well-known/oauth-authorization-server. knowmind responds with every endpoint, the supported grant types, and the PKCE requirement S256.
  2. Registration: the connector calls POST /oauth/register with its name and its redirect URIs. knowmind checks the URIs against the allowlist (see table below), creates an oauth_clients record with tenant_id = NULL and returns a client ID. No client secret is issued — public client with PKCE.
  3. Authorization request: the connector sends the user to /oauth/authorize with response_type=code, client_id, redirect_uri, scope, a random state, a code_challenge (Base64-URL encoded SHA-256 of the connector's locally stored code_verifier), and code_challenge_method=S256.
  4. Login and consent: if the user is not yet signed in, knowmind redirects them to /signin. Magic link in the mailbox, confirmation, return to the authorization page. On the user's first authorize the oauth_clients record's tenant_id is fixed to the signed-in user's tenant. Later authorize flows with the same client ID must hit the same tenant.
  5. Authorization code: knowmind generates a short-lived code (valid for 10 minutes), stores it along with the code_challenge, redirect_uri, user_id and tenant_id, and redirects the connector with ?code=…&state=….
  6. Token exchange: the connector calls POST /oauth/token with grant_type=authorization_code, the received code, the original redirect_uri, its client_id and the code_verifier. knowmind verifies PKCE (SHA-256 of code_verifier equals code_challenge), consumes the code, and returns a regular kmt_ access token valid for 30 days.
  7. MCP calls: every MCP call carries the token in the Authorization: Bearer kmt_… header. Normal tenant isolation applies — the token only sees the tenant the user authorized during the authorize flow.

Allowlist of permitted redirect hosts

knowmind accepts redirect URIs only on the following hosts (HTTPS required, localhost allowed for development):

HostPlatformSubdomain matching
claude.aiClaude (Anthropic) — custom connectorsyes
claude.comClaude (Anthropic) — alternative hostyes
chat.openai.comChatGPT (legacy host)yes
chatgpt.comChatGPT — custom actions / connectorsyes
cursor.shCursor — MCP integrationyes
cursor.comCursor — alternative hostyes
anysphere.comAnysphere — Cursor makeryes
127.0.0.1Local development (HTTP allowed)no
localhostLocal development (HTTP allowed)no

Subdomain matching: *.claude.ai is accepted, e.g. connectors.claude.ai. Any other redirect host is rejected with HTTP 400 and error: invalid_redirect_uri. If you want a different platform added, contact info@schuebeler-consulting.de.

Tenant binding on first login

When a connector has just registered through /oauth/register, knowmind does not yet know a tenant — the client record carries tenant_id = NULL. On the first authorize flow the tenant_id is wired to the tenant of the signed-in user and is then immutable. If a second user of the same connector tries to authorize with a different tenant, knowmind responds with HTTP 403 access_denied and the hint message "This OAuth client belongs to a different workspace".

Practical consequence: every user who adds a new custom connector runs through their own DCR registration. Multiple users in the same tenant do not share a single oauth_clients record.

Security properties

  • PKCE is mandatory. knowmind rejects authorize requests without a code_challenge or with code_challenge_method ≠ S256 with HTTP 400. This protects the authorization code against interception via open redirects or compromised browser extensions.
  • No client secrets. token_endpoint_auth_method = none. Public client with PKCE replaces the classic client secret model. No pre-distribution of secrets to browser apps.
  • Short access token lifetime. Access tokens live for 30 days; the connector renews them by repeating the authorize flow (no refresh tokens are issued in the standard flow — connectors trigger the authorize loop automatically when needed).
  • Revoke at any time. In the cockpit under OAuth Clients you see every registered connector and can revoke it with one click. The token becomes invalid immediately.
  • State parameter required for CSRF protection. The connector sets a random state, knowmind mirrors it on redirect, the connector checks for a match.
Note

When OAuth is not the right path

If your plan does not unlock OAuth (Private plan), or if you need a programmatic integration without a browser flow, use the static token path. See "Create an API token". A static token offers the same API functionality without the authorize step.

Related