The OAuth 2.1 server turns the application you host on Stormkit into an
OAuth authorization server. External clients — most commonly MCP
connectors such as Claude (claude.ai / claude.com) and ChatGPT
(chatgpt.com), or native/CLI clients like Claude Code — register with your app
and obtain tokens that let them call your app's MCP endpoint as your end
users.
This is the opposite role from the Google / X provider logins described in Authentication. There, your app is a client of an external identity provider. Here, your app is the authorization server that other clients connect to.
The OAuth server is layered on top of Stormkit Auth (SkAuth): it reuses SkAuth's end-user identities and its signing secret. SkAuth must be enabled for the OAuth server to work.
Requirements
- Available on self-hosted installations only.
- Stormkit Auth must be enabled (which in turn requires a database attached to the environment). Identities and the token-signing secret come from SkAuth.
All endpoints are served from your app's own hosting domain under the
/_stormkit/oauth path prefix. Stormkit intercepts these paths before your
deployment is served — there is nothing to install in your application.
| Endpoint | Description |
|---|---|
POST /_stormkit/oauth/register |
RFC 7591 Dynamic Client Registration. Clients self-register as public clients; PKCE is required. |
GET /_stormkit/oauth/authorize |
Authorization request (RFC 6749 + PKCE RFC 7636). If the user has no readable session, the server delegates to your app's configured Login URL (with a loop-guarded return_to param) rather than showing a Stormkit login page. |
POST /_stormkit/oauth/authorize |
Consent / grant submission. Issues the authorization code. |
POST /_stormkit/oauth/token |
Exchanges the authorization code + PKCE code_verifier for an access token, and — when the offline_access scope was requested — a rotating refresh token. |
POST /_stormkit/oauth/revoke |
RFC 7009 token revocation. Deletes a refresh token. Always returns 200, even for unknown tokens (per RFC 7009 §2.2, to prevent probing). |
| Token | How it works |
|---|---|
| Access token | A stateless HS256 JWT signed with the environment's SkAuth secret. The edge validates it on every request. It carries an audience (aud) bound to the resource (RFC 8707) — your app's origin plus the MCP resource path. Access tokens are not individually revocable; they expire on their own. |
| Refresh token | Stored server-side (Redis, SHA-256 keyed), rotates on each use, and is only issued when the offline_access scope is requested. Refresh tokens can be revoked via /revoke. |
The server publishes standard /.well-known/ metadata so clients can discover
it automatically:
/.well-known/oauth-protected-resource/<path> matching your MCP resource
path.The /revoke endpoint is advertised as revocation_endpoint in the metadata.
When an unauthenticated request hits the MCP endpoint, the auth challenge points
the client at these documents.
Redirect validation for the OAuth server does not use SkAuth's Allowed origins list. Instead:
claude.ai, claude.com, and chatgpt.com. No per-origin
configuration is needed for these clients.localhost on an ephemeral port) are supported only when
the Allow loopback toggle is on. Loopback redirects are matched on
scheme + path, ignoring the port.Configure the OAuth server under Environment > Authentication.
/mcp). This must exactly equal the path
in the connector URL your users enter — a mismatch makes connectors fail
silently./authorize delegates
unauthenticated users here.Remember to Save after changing these settings.
The same settings can be set programmatically with POST /v1/auth/config using
a user- or environment-scoped API key, or via the configure_auth MCP tool. The
relevant fields are:
| Field | Meaning |
|---|---|
oauthServerEnabled |
Enable the OAuth server. |
oauthResourcePath |
The MCP resource path (e.g. /mcp). |
oauthAllowLoopback |
Allow RFC 8252 loopback redirects. |
loginUrl |
Your app's login page for /authorize delegation. |
See the Authentication docs for the full field list.
https://app.example.com/mcp) into Claude or ChatGPT./.well-known/ metadata./_stormkit/oauth/register./_stormkit/oauth/authorize./authorize.code_verifier at
/_stormkit/oauth/token for an access token (and a refresh token if
offline_access was requested)./mcp). A mismatch is the most
common cause./authorize can delegate unauthenticated users to it.