Skip to main content

OAuth and Original Connect

Original acts as an OAuth 2.0 / OpenID Connect authorization server. External apps and agent platforms (for example MCP clients) can let users sign in with their Original account and act on their behalf, using the Original Connect SDK or any standard OAuth client.

Supported standards​

StandardWhat it covers
RFC 6749OAuth 2.0 framework (authorization code and refresh token grants)
RFC 7636PKCE, mandatory for every client, S256 only
RFC 7591Dynamic Client Registration: apps register themselves without admin help
RFC 8414Authorization Server Metadata (/.well-known/oauth-authorization-server)
OpenID ConnectID token (RS256), discovery (/.well-known/openid-configuration), UserInfo
RFC 7009Token revocation

Endpoints​

All endpoints are relative to https://ai.original.land.

EndpointPurpose
GET /.well-known/oauth-authorization-serverServer metadata (used by MCP clients)
GET /.well-known/openid-configurationSame metadata, OpenID Connect location
POST /oauth/registerDynamic client registration
GET /oauth/authorizeUser sign-in and consent
POST /oauth/tokenExchange a code or refresh token for tokens
POST /oauth/revokeRevoke a refresh token
GET /oauth/userinfoSigned-in user profile
GET /oauth/jwksPublic keys to verify ID and access tokens
tip

Start from the discovery document. Most OAuth libraries only need the issuer URL and configure everything else automatically.

Register a client (RFC 7591)​

Send a JSON body to POST /oauth/register:

{
"client_name": "My App",
"redirect_uris": ["https://myapp.example.com/callback"],
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"],
"scope": "openid profile agent.chat:<agentId>"
}
FieldNotes
client_nameRequired, up to 200 characters
redirect_urisRequired, 1 to 20 URLs. Redirects must match exactly
token_endpoint_auth_methodnone (public client, default) or client_secret_post (confidential client)
grant_typesInclude refresh_token to receive refresh tokens as a public client
scopeSpace-separated. Scopes not allowed for dynamic clients are dropped
client_uri, logo_uri, contactsOptional metadata

The response (201) contains a client_id (prefix oc_). Confidential clients also receive a client_secret (prefix ocs_) that never expires.

warning

The client_secret is shown only once in the registration response. Store it securely.

Registrations are rate limited: a 429 too_many_requests response means you should retry later.

Scopes​

ScopeMeaningDynamic clients
openidIssue an ID token and allow UserInfoYes
profileEmail, name, picture, plan, and creditsYes
agent.chat:<agentId>Chat with a specific agent on the user's behalfYes
agent.purchaseBuy plans or redeem vouchers for agentsYes
workspacePrivileged workspace accessNo, requires manual registration by the Original team

If no scope is requested, the client gets openid profile.

Authorization flow​

  1. Redirect the user to /oauth/authorize with response_type=code, client_id, redirect_uri, scope, state, optional nonce, code_challenge, and code_challenge_method=S256.
  2. The user signs in, picks the account, and approves the consent screen.
  3. Original redirects back to redirect_uri with code and state, or with error=access_denied if the user declines.
  4. Call POST /oauth/token (form-encoded) with grant_type=authorization_code, code, redirect_uri, client_id, code_verifier, and client_secret for confidential clients.

Token lifetimes​

TokenLifetime
Authorization code60 seconds, single use
Access token1 hour
Refresh token (confidential client)30 days
Refresh token (public client)7 days

Refresh tokens rotate: every grant_type=refresh_token call returns a new refresh token and invalidates the old one. Public clients get refresh tokens only if they registered with the refresh_token grant type.

UserInfo​

GET /oauth/userinfo with Authorization: Bearer <access_token> requires the openid scope. With profile it also returns email, name, picture, the platform plan and credits, unlocked agents, and active agent subscriptions.