Providers
OAuth Providers
Add OAuth with providers from @keyloom/providers or build your own via the provider factory.
Providers
Add OAuth 2.0 / OIDC providers by installing @keyloom/providers and listing providers in your keyloom.config.ts.
Install
pnpm add @keyloom/providersUsage
import { defineKeyloom } from "@keyloom/core";
import { github, google } from "@keyloom/providers";
export default defineKeyloom({
// ...
providers: [
github({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
});Routes handled by the Next.js handler:
GET /api/auth/oauth/:provider/startGET/POST /api/auth/oauth/:provider/callback
Available Providers
Keyloom supports a comprehensive list of OAuth providers:
Major Platforms
- GitHub - Developer-focused platform
- Google - Google accounts and Workspace
- Apple - Sign in with Apple
- Microsoft - Microsoft accounts and Azure AD
- Auth0 - Identity platform
Social Media
- Discord - Gaming and community platform
- Facebook - Meta's social platform
- Instagram - Photo and video sharing
- LinkedIn - Professional networking
- Reddit - Community discussions
- Spotify - Music streaming
- TikTok - Short-form video platform
- Twitch - Live streaming platform
- X (Twitter) - Social media platform
Enterprise & Self-Hosted
- Authentik - Open-source identity provider
- GitLab - DevOps platform (GitLab.com or self-hosted)
Development
- Dev - Local development provider for testing
import {
// Major platforms
github,
google,
apple,
microsoft,
auth0,
// Social media
discord,
facebook,
instagram,
linkedin,
reddit,
spotify,
tiktok,
twitch,
x,
// Enterprise
authentik,
gitlab,
// Development
dev,
} from "@keyloom/providers";Custom Providers
Use the provider factory utilities to create a new provider quickly.
import { createProvider } from "@keyloom/providers/factory";
export default createProvider({
id: "my-idp",
client: {
authorizeUrl: "https://idp.example.com/oauth/authorize",
tokenUrl: "https://idp.example.com/oauth/token",
userUrl: "https://idp.example.com/userinfo",
},
profile: (raw) => ({ id: raw.sub, email: raw.email, name: raw.name }),
scopes: ["openid", "profile", "email"],
});Error Handling
- Invalid callback:
{ error: "invalid_callback" }(400) - Unknown provider:
provider_not_found:<id> - Token exchange failures bubble as 400/500 responses with safe messages
Security
- OAuth state is sealed (AES-GCM) and stored in an HttpOnly cookie with short TTL; cleared after callback
- PKCE S256 supported for web flows
Troubleshooting
- Mismatched redirect URI: ensure your callback path matches the configured one (e.g.,
/api/auth/oauth/github/callback) - Missing client credentials: set the provider ENV vars, rebuild, and retry
Prerequisites
- Create OAuth apps at your providers (GitHub, Google, etc.)
- Set callback URL(s):
${APP_URL}/api/auth/oauth/<provider>/callback - Store client ID/secret in your platform's secret manager
GitHub setup
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...import { defineKeyloom } from "@keyloom/core";
import { github } from "@keyloom/providers";
export default defineKeyloom({
// ...
providers: [
github({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
scopes: ["read:user", "user:email"],
}),
],
});Google setup
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...import { google } from "@keyloom/providers";
export default defineKeyloom({
providers: [
google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
scopes: ["openid", "profile", "email"],
}),
],
});OAuth flow
Scope recommendations
- GitHub:
read:user,user:email(avoid repo/org scopes unless needed) - Google:
openid profile email(avoid Drive/Gmail scopes unless required) - Microsoft:
openid profile emailminimal; add Graph scopes as needed - Apple:
name emailvia Sign in with Apple; useform_postcallback if required
Custom provider (advanced)
import { createProvider } from "@keyloom/providers/factory";
export const myIdp = createProvider({
id: "my-idp",
client: {
authorizeUrl: "https://idp.example.com/oauth/authorize",
tokenUrl: "https://idp.example.com/oauth/token",
userUrl: "https://idp.example.com/userinfo",
},
profile: (raw) => ({ id: raw.sub, email: raw.email, name: raw.name }),
scopes: ["openid", "profile", "email"],
});Error handling
- Unknown provider → 404/400:
{ error: "provider_not_found" } - Callback error → 400:
{ error: "oauth_error", code, description? } - Token exchange/network issues → 502/500 with minimal message in production
Performance and rate limiting
- Apply rate limit to
/oauth/*/startand/oauth/*/callback - Cache provider discovery/doc endpoints where applicable (OIDC discovery)
- Keep provider profile fetch lightweight; avoid extra downstream calls during login
Troubleshooting
- Mismatched redirect URI: the callback URL must exactly match provider settings
- Invalid scope: reduce scopes to the minimum or request approval for sensitive scopes
- CSR/Edge issues: rely on server handlers for OAuth flows; avoid running login in middleware
See also
- Security: /docs/security/overview
- Handler endpoints: /docs/nextjs/handler
- Installation: /docs/getting-started/installation
Next steps
- Add at least one provider and test end-to-end sign-in
- Add additional providers or a custom provider as needed
How is this guide?