--- name: bknd-oauth-setup description: Use when configuring OAuth or social login providers in a Bknd application. Covers Google OAuth, GitHub OAuth, custom OAuth providers, callback URLs, environment variables, and frontend OAuth integration. --- # OAuth/Social Login Setup Configure OAuth authentication providers (Google, GitHub, or custom) in Bknd. ## Prerequisites - Bknd project with auth enabled (`bknd-setup-auth`) - OAuth app credentials from provider (client_id, client_secret) - For Google: Google Cloud Console project with OAuth 2.0 credentials - For GitHub: GitHub OAuth App in Developer Settings - For custom: Provider's authorization server endpoints ## When to Use UI Mode - Testing OAuth login flow via admin panel - Viewing enabled OAuth strategies - Checking callback URL configuration **UI steps:** Admin Panel > Auth > Strategies ## When to Use Code Mode - Configuring OAuth providers in `bknd.config.ts` - Setting up multiple OAuth providers - Implementing frontend OAuth buttons - Configuring custom OAuth providers (Slack, Discord, etc.) ## Built-in OAuth Providers Bknd has pre-configured support for: | Provider | Type | Scopes | |----------|------|--------| | `google` | OIDC | openid, email, profile | | `github` | OAuth2 | read:user, user:email | ## Google OAuth Setup ### 1. Create Google OAuth Credentials 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create project or select existing 3. Navigate: **APIs & Services > Credentials** 4. Click **Create Credentials > OAuth client ID** 5. Application type: **Web application** 6. Add authorized redirect URI: ``` http://localhost:7654/api/auth/google/callback ``` (Replace with your production URL) 7. Copy **Client ID** and **Client Secret** ### 2. Configure Bknd ```typescript // bknd.config.ts import { defineConfig } from "bknd"; export default defineConfig({ auth: { enabled: true, jwt: { secret: process.env.JWT_SECRET!, expires: 604800, }, strategies: { google: { type: "oauth", enabled: true, config: { name: "google", client: { client_id: process.env.GOOGLE_CLIENT_ID!, client_secret: process.env.GOOGLE_CLIENT_SECRET!, }, }, }, }, }, }); ``` ### 3. Environment Variables ```bash # .env GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-google-client-secret JWT_SECRET=your-256-bit-secret ``` ## GitHub OAuth Setup ### 1. Create GitHub OAuth App 1. Go to [GitHub Developer Settings](https://github.com/settings/developers) 2. Click **New OAuth App** 3. Fill in: - **Application name**: Your app name - **Homepage URL**: `http://localhost:7654` - **Authorization callback URL**: `http://localhost:7654/api/auth/github/callback` 4. Click **Register application** 5. Copy **Client ID** and generate **Client Secret** ### 2. Configure Bknd ```typescript // bknd.config.ts import { defineConfig } from "bknd"; export default defineConfig({ auth: { enabled: true, jwt: { secret: process.env.JWT_SECRET!, expires: 604800, }, strategies: { github: { type: "oauth", enabled: true, config: { name: "github", client: { client_id: process.env.GITHUB_CLIENT_ID!, client_secret: process.env.GITHUB_CLIENT_SECRET!, }, }, }, }, }, }); ``` ### 3. Environment Variables ```bash # .env GITHUB_CLIENT_ID=your-github-client-id GITHUB_CLIENT_SECRET=your-github-client-secret JWT_SECRET=your-256-bit-secret ``` ## Multiple OAuth Providers Enable multiple providers simultaneously: ```typescript // bknd.config.ts import { defineConfig } from "bknd"; export default defineConfig({ auth: { enabled: true, jwt: { secret: process.env.JWT_SECRET!, expires: 604800, }, strategies: { password: { type: "password", enabled: true, config: { hashing: "bcrypt", rounds: 4, }, }, google: { type: "oauth", enabled: true, config: { name: "google", client: { client_id: process.env.GOOGLE_CLIENT_ID!, client_secret: process.env.GOOGLE_CLIENT_SECRET!, }, }, }, github: { type: "oauth", enabled: true, config: { name: "github", client: { client_id: process.env.GITHUB_CLIENT_ID!, client_secret: process.env.GITHUB_CLIENT_SECRET!, }, }, }, }, }, }); ``` ## Custom OAuth Provider For providers not built-in (Slack, Discord, Microsoft, etc.): ```typescript // bknd.config.ts import { defineConfig } from "bknd"; export default defineConfig({ auth: { enabled: true, strategies: { slack: { type: "custom_oauth", enabled: true, config: { name: "slack", type: "oauth2", // "oauth2" or "oidc" client: { client_id: process.env.SLACK_CLIENT_ID!, client_secret: process.env.SLACK_CLIENT_SECRET!, token_endpoint_auth_method: "client_secret_basic", }, as: { issuer: "https://slack.com", authorization_endpoint: "https://slack.com/oauth/v2/authorize", token_endpoint: "https://slack.com/api/oauth.v2.access", userinfo_endpoint: "https://slack.com/api/users.identity", scopes_supported: ["openid", "profile", "email"], }, }, }, }, }, }); ``` **Custom OAuth config options:** | Property | Type | Required | Description | |----------|------|----------|-------------| | `name` | string | Yes | Strategy identifier | | `type` | `"oauth2"` \| `"oidc"` | Yes | Protocol type | | `client.client_id` | string | Yes | OAuth client ID | | `client.client_secret` | string | Yes | OAuth client secret | | `client.token_endpoint_auth_method` | string | Yes | Auth method (`client_secret_basic`) | | `as.issuer` | string | Yes | Authorization server issuer URL | | `as.authorization_endpoint` | string | Yes | OAuth authorize URL | | `as.token_endpoint` | string | Yes | Token exchange URL | | `as.userinfo_endpoint` | string | No | User info URL | | `as.scopes_supported` | string[] | No | Available scopes | ## OAuth Endpoints Once configured, Bknd exposes these endpoints: | Method | Path | Description | |--------|------|-------------| | POST | `/api/auth/{provider}/login` | Start OAuth login (cookie mode) | | POST | `/api/auth/{provider}/register` | Start OAuth registration (cookie mode) | | GET | `/api/auth/{provider}/login` | Get OAuth URL (token mode) | | GET | `/api/auth/{provider}/callback` | OAuth callback handler | ## Frontend Integration ### Cookie-Based Flow (Recommended for SSR) ```typescript // Redirect user to OAuth provider function loginWithGoogle() { // POST redirects to Google, callback sets cookie, redirects to pathSuccess const form = document.createElement("form"); form.method = "POST"; form.action = "http://localhost:7654/api/auth/google/login"; document.body.appendChild(form); form.submit(); } ``` ### Token-Based Flow (SPA) ```typescript import { Api } from "bknd"; const api = new Api({ host: "http://localhost:7654", storage: localStorage, }); async function loginWithGoogle() { // Get OAuth URL const { data } = await api.auth.login("google"); if (data?.url) { // Store challenge for callback verification sessionStorage.setItem("oauth_challenge", data.challenge); // Redirect to Google window.location.href = data.url; } } // On callback page, complete the flow async function handleOAuthCallback() { const params = new URLSearchParams(window.location.search); const code = params.get("code"); const challenge = sessionStorage.getItem("oauth_challenge"); if (code && challenge) { // Complete OAuth flow const response = await fetch( `http://localhost:7654/api/auth/google/callback?code=${code}`, { headers: { "X-State-Challenge": challenge, "X-State-Action": "login", }, } ); const { user, token } = await response.json(); api.setToken(token); sessionStorage.removeItem("oauth_challenge"); } } ``` ### React OAuth Buttons ```tsx import { useAuth } from "@bknd/react"; function OAuthButtons() { const { login } = useAuth(); async function handleGoogleLogin() { const result = await login("google"); if (result.data?.url) { window.location.href = result.data.url; } } async function handleGitHubLogin() { const result = await login("github"); if (result.data?.url) { window.location.href = result.data.url; } } return (
{error}
Back to login