OAuth Providers
KATforge supports four social login providers plus its own first-party OAuth server:
| Provider | Identifier | Notes |
|---|---|---|
| Discord | discord | Standard OAuth 2.0 |
google | Standard OAuth 2.0 | |
| Apple | apple | Sign in with Apple |
| Steam | steam | OpenID 2.0 (legacy) |
| KATforge | katforge | First-party OAuth 2.0 server with PKCE |
Flow
The flow is two-legged. The frontend never sees the provider's code directly; the API handles the callback and redirects back with a result.
sequenceDiagram
autonumber
participant B as Browser
participant A as KATforge API
participant P as Provider (Discord/Google/...)
B->>A: GET /v1/gateway/oauth/{provider}/url
A-->>B: { url: "https://provider.com/oauth2/authorize?..." }
B->>P: Redirect to provider authorization page
P-->>B: Redirect back with ?code=...&state=...
B->>A: GET /v1/gateway/oauth/{provider}/check?code=...&state=...
A->>P: Exchange code for access token
P-->>A: User profile
A-->>B: 302 → frontend with access_token, needs_username, or error
1. Get the authorization URL
const { url } = await katforge.auth.oauthUrl ('discord', {
redirect: 'https://katforge.com/oauth/callback'
});
window.location.href = url;
The redirect URL must be on a KATforge-owned domain. It's preserved across the entire round-trip.
2. Handle the callback
The browser ends up at your redirect URL with one of three outcomes encoded in the query string:
Success — existing user
https://katforge.com/oauth/callback?access_token=eyJ...&created=0
The refresh token is also set as a cookie on the response. Just use the access token; you're logged in.
Success — new user, needs username
https://katforge.com/oauth/callback?needs_username=1&temp_token=eyJ...&suggested_username=Anders&email=anders@example.com
Show a username picker, then call:
const session = await katforge.auth.oauthComplete ({
temp_token: tempToken,
username: chosenUsername
});
This creates the new account and returns a normal TokenResponse.
Error
https://katforge.com/oauth/callback?error=Invalid+state
Just display the error to the user.
Linking and unlinking providers
Authenticated users can link extra providers to their existing account:
await katforge.auth.oauthLink ('discord', { code, state });
And remove them:
await katforge.auth.oauthUnlink ('discord');
The API refuses to unlink the last remaining sign-in method to avoid locking the user out.
Listing linked providers
const { providers } = await katforge.auth.oauthList ();
// providers: [{ provider: 'discord', linked_at: '...', external_id: '...' }, ...]
KATforge as an OAuth provider
KATforge can also act as an OAuth 2.0 provider for first-party and approved third-party apps. The flow is standard authorization-code with optional PKCE:
- Validate the client + redirect URI:
GET /v1/oauth/authorize/validate?client_id=…&redirect_uri=… - Authorize after user consent:
POST /v1/oauth/authorizereturns a code - Exchange the code for tokens:
POST /v1/oauth/token(grant_type=authorization_code) - Read the user profile:
GET /v1/oauth/userinfo
See the OAuth Server endpoints in the API reference for details.