KeyloomKeyloom
Keyloom Auth is currently in beta. Feedback and contributions are welcome!
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/providers

Usage

keyloom.config.ts
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/start
  • GET/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

.env
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
keyloom.config.ts
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

.env
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
keyloom.config.ts
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 email minimal; add Graph scopes as needed
  • Apple: name email via Sign in with Apple; use form_post callback 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/*/start and /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

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?