Authentication
Klaxon's authentication surface is split across two binaries:
klaxon-auth(port 3001) is a compliant OAuth 2.1 Authorization Server with RFC 8414 discovery, RFC 7591 dynamic client registration, PKCE S256, refresh-token rotation, and RFC 7009 revocation. It also handles all IdP login flows (GitHub, Google, Apple, magic link) and account management (/auth/me,/auth/logout,/auth/api-keys).klaxon-server(port 3000) hosts the protected resources. It validates bearer tokens against the shared Postgres schema via theklaxon-auth-coreextractor — no cross-service RPC.
Klaxon issues two shapes of bearer token:
- Session tokens for human users (web / mobile) — opaque, SHA-256 hashed at rest, 30-day TTL, 7-day on invite-accept.
- API keys for MCP agents — same shape, configurable TTL. Created automatically when an admin creates an agent.
Human Login
Pick whichever IdP fits your deployment. You can enable multiple — the login screen picks up whatever's configured.
GitHub OAuth
Set these env vars on klaxon-auth:
| Env var | Purpose |
|---|---|
GITHUB_CLIENT_ID | OAuth app client ID |
GITHUB_CLIENT_SECRET | OAuth app client secret |
Register the callback as https://<auth-host>/auth/oauth/github/callback. First-time signup auto-creates a personal org + user + user_identity row.
Google OAuth
| Env var | Purpose |
|---|---|
GOOGLE_CLIENT_ID | OAuth client ID |
GOOGLE_CLIENT_SECRET | OAuth client secret |
Callback: https://<auth-host>/auth/oauth/google/callback.
Sign in with Apple
Apple uses ES256-signed client-secret JWTs and JWKS-verified id_tokens. You'll need:
| Env var | Purpose |
|---|---|
APPLE_CLIENT_ID | Your Services ID (e.g. com.klaxon.signin) |
APPLE_TEAM_ID | 10-char Team ID from Apple Developer |
APPLE_KEY_ID | 10-char Key ID for the .p8 private key |
APPLE_PRIVATE_KEY | Contents of the .p8 file (including the BEGIN/END PRIVATE KEY lines) |
Unlike other IdPs, Apple POSTs to the callback URL. Register https://<auth-host>/auth/oauth/apple/callback as your redirect.
Magic Link
Email-based passwordless login — no IdP app to register, just SMTP. User enters their email, receives a short-lived link, clicks it.
Step 1 — Request magic link:
curl -X POST http://localhost:3000/auth/magic-link \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com", "org_id": "ORG_UUID"}'Always returns 200 (doesn't leak whether the email exists). If SMTP is configured, sends an email with a login link. Link expires in 15 minutes, single-use.
Step 2 — Exchange token for session:
curl "http://localhost:3000/auth/verify?token=base64url-token-from-email-link"Response:
{
"token": "session-bearer-token",
"user_id": "...",
"org_id": "..."
}Sessions expire after 30 days.
Dev mode: When SMTP is not configured (no SMTP_HOST env var), the magic link token is logged to the console and returned in the response body. This lets you develop without an email server.
SMTP configuration:
SMTP_HOST— mail server hostnameSMTP_PORT— port (default: 587)SMTP_USER/SMTP_PASS— credentialsSMTP_FROM— sender address (default:noreply@klaxon.sh)APP_URL— base URL for the link (default:http://localhost:5173)
Dev bypass (optional)
Setting DEV_LOGIN_ENABLED=true on klaxon-auth makes /oauth/authorize auto-consent for the first-party client without prompting. Combined with the magic-link flow returning the token in the response body when SMTP is unset, this lets you develop end-to-end without any external services.
WARNING
Dev bypass accepts any email without verification. Never set this in production.
Agent API Keys
Users create API keys for their agents. Each key is bound to a specific agent entity and has a configurable TTL.
Create an API Key
curl -X POST http://localhost:3000/auth/api-keys \
-H "Authorization: Bearer SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "AGENT_UUID",
"label": "my-agent-prod",
"expires_in_days": 90
}'Response:
{
"id": "KEY_UUID",
"key": "base64url-encoded-api-key"
}WARNING
The key is shown only once. Store it securely.
Revoke an API Key
curl -X POST http://localhost:3000/auth/api-keys/revoke \
-H "Authorization: Bearer SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"key_id": "KEY_UUID"}'Revoked keys are soft-deleted (revoked_at timestamp) and immediately stop working.
Using Tokens
All authenticated endpoints require the Authorization header:
Authorization: Bearer <token>The server tries the token as a session first, then as an API key. The resolved identity includes:
| Field | Description |
|---|---|
user_id | The user who owns the session/key |
org_id | The organization scope |
agent_id | The agent (API keys only; null for sessions) |
source | "session" or "api_key" |
Who Am I
curl http://localhost:3000/auth/me \
-H "Authorization: Bearer TOKEN"{
"user_id": "...",
"org_id": "...",
"agent_id": null,
"source": "session"
}Logout
curl -X POST http://localhost:3000/auth/logout \
-H "Authorization: Bearer SESSION_TOKEN"Revokes the current session.
OAuth 2.1 for third-party clients
klaxon-auth is a compliant Authorization Server so external MCP clients can use standard OAuth flows instead of copy-pasting API keys.
- Discovery:
GET /.well-known/oauth-authorization-server(RFC 8414) andGET /.well-known/oauth-protected-resource(RFC 9728) - Dynamic client registration:
POST /oauth/register(RFC 7591) — takesredirect_uris, returns aclient_id+client_secret - Authorization code flow with PKCE S256:
GET /oauth/authorize→POST /oauth/token. Thecode_verifier/code_challengepair is mandatory — the server rejects any token exchange without it. - Refresh tokens rotate: each refresh returns a new refresh token and invalidates the previous one. A replay is a hard error.
- Revocation:
POST /oauth/revoke(RFC 7009) accepts either an access token or a refresh token.
The browser session cookie that underpins /oauth/authorize is HMAC-signed with OAUTH_SIGNING_KEY — rotate it and every logged-in browser session invalidates at once.
| Env var | Purpose |
|---|---|
OAUTH_SIGNING_KEY | 32+ random bytes, openssl rand -base64 32. Signs the browser session cookie + OAuth state param. |
ISSUER_URL | Public URL of the AS — the issuer field in discovery |
RESOURCE_URL | Public URL of klaxon-server — WWW-Authenticate points MCP clients here |