Integrate Connect's OAuth API with an existing authentication stack.
Standalone Connect allows applications with existing authentication systems to use AuthKit as their OAuth authorization server. The existing authentication stack is maintained while leveraging AuthKit’s OAuth infrastructure for token issuance and management.
Unlike standard AuthKit integration, Standalone Connect delegates authentication to the application, then handles the OAuth flow and token issuance for OAuth clients. This feature works with OAuth applications only – M2M applications use the client_credentials flow, which does not involve user authentication.
Use Standalone Connect when the application:
Before testing the Standalone Connect integration, create an OAuth application in the WorkOS Dashboard. To support MCP auth, enable Client ID Metadata Document (CIMD), which is described in the MCP guide.
Navigate to Connect → Configuration in the WorkOS Dashboard and provide the Login URI.
The Login URI is where AuthKit redirects users to authenticate with the existing system. Only one Login URI can be configured per environment.
The Login URI must:
external_auth_id query parameter.Example: https://your-app.example.com/auth/login
OAuth clients start the authorization flow with AuthKit following standard OAuth 2.0. This could be a third-party application, partner integration, or any OAuth-enabled client.
AuthKit redirects users to the Login URI with an external_auth_id parameter:
https://your-app.example.com/auth/login?external_auth_id=01J3X4Y5Z6A7B8C9D0E1F2G3H4
The external_auth_id is a temporary identifier used to complete the flow with AuthKit.
Authenticate users with the existing system. If users have an active session, skip to the next step.
AuthKit handles OAuth consent separately, so the application does not need to display any consent screens.
Call the AuthKit completion API after authenticating the user, passing the external_auth_id that the Login URI originally received:
const response = await fetch('https://api.workos.com/authkit/oauth2/complete', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.WORKOS_API_KEY}`, }, body: JSON.stringify({ external_auth_id: externalAuthId, user: { id: user.id, email: user.email, first_name: user.firstName, last_name: user.lastName, metadata: { department: user.department }, }, }), }); const { redirect_uri } = await response.json();
Redirect users to the redirect_uri from the API response. AuthKit displays a consent screen if needed, issues tokens, and completes the OAuth flow.
Provide user_consent_options to display options during the OAuth consent screen. This is useful when users need to choose specific resources or contexts (like a parent resource in the application) to grant access to.
Each consent option must include:
claim: The name of the access token claim that will hold the user’s selected value.type: The format of the option. Only enum is supported currently.label: Display text for the option.choices: Array of choices (can be flat or grouped).
const response = await fetch('https://api.workos.com/authkit/oauth2/complete', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.WORKOS_API_KEY}`, }, body: JSON.stringify({ external_auth_id, user: { id: user.id, email: user.email }, user_consent_options: [ { claim: 'urn:example:tenant', type: 'enum', label: 'Environment', choices: [ { group: 'Production', choices: [ { value: 'prod_us', label: 'US-East' }, { value: 'prod_eu', label: 'EU-West' }, ], }, { group: 'Development', choices: [ { value: 'dev_main', label: 'Development' }, { value: 'staging', label: 'Staging' }, ], }, ], }, ], }), });
The selected values appear as custom claims in the issued tokens. For example, if the user selects one of the above options, the token will include:
{ "sub": "user_123", "email": "user@example.com", "urn:example:tenant": "prod_us" // ... }
If the external_auth_id is invalid, the call to the AuthKit completion API will fail. Handle this case as appropriate for the application – redirecting to the application’s homepage is recommended.
Resource servers verify tokens issued by AuthKit using standard Connect token verification:
import { jwtVerify, createRemoteJWKSet } from 'jose'; const JWKS = createRemoteJWKSet(new URL('https://<subdomain>.authkit.app/oauth2/jwks')); async function verifyToken(token) { const { payload } = await jwtVerify(token, JWKS, { audience: 'client_123456789', issuer: 'https://<subdomain>.authkit.app', }); return payload; }
See the Connect documentation for details on token expiration, refresh tokens, and revocation.