Skip to content
bknd-oauth-setup logo

OAuth/Social Login Setup

bknd-oauth-setup

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.

SKILL.md

Full skill instructions

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:

ProviderTypeScopes
googleOIDCopenid, email, profile
githubOAuth2read:user, user:email

Google OAuth Setup

1. Create Google OAuth Credentials

  1. Go to Google Cloud Console
  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

// 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

# .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
  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

// 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

# .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:

// 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.):

// 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:

PropertyTypeRequiredDescription
namestringYesStrategy identifier
type"oauth2" | "oidc"YesProtocol type
client.client_idstringYesOAuth client ID
client.client_secretstringYesOAuth client secret
client.token_endpoint_auth_methodstringYesAuth method (client_secret_basic)
as.issuerstringYesAuthorization server issuer URL
as.authorization_endpointstringYesOAuth authorize URL
as.token_endpointstringYesToken exchange URL
as.userinfo_endpointstringNoUser info URL
as.scopes_supportedstring[]NoAvailable scopes

OAuth Endpoints

Once configured, Bknd exposes these endpoints:

MethodPathDescription
POST/​api/​auth/​{provider}/​loginStart OAuth login (cookie mode)
POST/​api/​auth/​{provider}/​registerStart OAuth registration (cookie mode)
GET/​api/​auth/​{provider}/​loginGet OAuth URL (token mode)
GET/​api/​auth/​{provider}/​callbackOAuth callback handler

Frontend Integration

Cookie-Based Flow (Recommended for SSR)

// 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)

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

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 (
    <div>
      <button onClick={handleGoogleLogin}>
        Continue with Google
      </​button>
      <button onClick={handleGitHubLogin}>
        Continue with GitHub
      </​button>
    </​div>
  );
}

OAuth Callback Page (React)

import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { Api } from "bknd";

const api = new Api({
  host: import.meta.env.VITE_API_URL,
  storage: localStorage,
});

function OAuthCallback() {
  const navigate = useNavigate();
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const code = params.get("code");
    const challenge = sessionStorage.getItem("oauth_challenge");

    if (!code) {
      setError("No authorization code received");
      return;
    }

    if (!challenge) {
      setError("OAuth session expired. Please try again.");
      return;
    }

    fetch(`${import.meta.env.VITE_API_URL}/​api/​auth/​google/​callback?code=${code}`, {
      headers: {
        "X-State-Challenge": challenge,
        "X-State-Action": "login",
      },
    })
      .then((res) => res.json())
      .then(({ user, token }) => {
        api.setToken(token);
        sessionStorage.removeItem("oauth_challenge");
        navigate("/​dashboard");
      })
      .catch((err) => {
        setError("Authentication failed. Please try again.");
      });
  }, [navigate]);

  if (error) {
    return (
      <div>
        <p>{error}</​p>
        <a href="/​login">Back to login</​a>
      </​div>
    );
  }

  return <div>Completing sign in...</​div>;
}

Callback URL Configuration

Development:

http://localhost:7654/​api/​auth/​{provider}/​callback

Production:

https://api.yourapp.com/​api/​auth/​{provider}/​callback

Update redirect URIs in provider dashboard when deploying.

Cookie Settings for OAuth

Configure cookie behavior for OAuth flow:

{
  auth: {
    cookie: {
      secure: process.env.NODE_ENV === "production",  // HTTPS only in prod
      httpOnly: true,
      sameSite: "lax",  // Required for OAuth redirects
      pathSuccess: "/​dashboard",  // Redirect after login
      pathLoggedOut: "/​login",    // Redirect after logout
    },
  },
}

Common Pitfalls

Callback URL Mismatch

Problem: redirect_uri_mismatch error from provider

Fix: Ensure callback URL exactly matches provider dashboard:

# Provider dashboard (Google/​GitHub)
http://localhost:7654/​api/​auth/​google/​callback

# Must match Bknd host configuration
host: "http://localhost:7654"

Missing Environment Variables

Problem: OAuth login fails silently

Fix: Verify all required env vars are set:

# Required for Google OAuth
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

# Required for GitHub OAuth
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

# Always required
JWT_SECRET=...

CORS Issues (SPA)

Problem: CORS error when calling OAuth endpoints

Fix: Configure CORS on backend:

{
  server: {
    cors: {
      origin: ["http://localhost:3000"],  // Your frontend URL
      credentials: true,
    },
  },
}

Strategy Conflict

Problem: "User signed up with different strategy"

Cause: User has existing account with different auth method

Solution: Users can only have ONE strategy. Guide them to use their original login method or implement account linking (requires custom code).

OAuth Cookie Not Set

Problem: Cookie not received after OAuth callback

Fix: Ensure secure cookie settings:

{
  auth: {
    cookie: {
      secure: false,  // Set false for localhost (no HTTPS)
      sameSite: "lax",  // Required for OAuth redirects
    },
  },
}

Invalid Scopes

Problem: Provider rejects scope request

Fix: Use only scopes from scopes_supported:

// Google OIDC defaults
scopes_supported: ["openid", "email", "profile"]

// GitHub OAuth2 defaults
scopes_supported: ["read:user", "user:email"]

Verification

Test OAuth setup:

1. Check available strategies:

curl http://localhost:7654/​api/​auth/​strategies

Response should include your OAuth providers:

{
  "strategies": ["password", "google", "github"],
  "basepath": "/​api/​auth"
}

2. Test OAuth URL generation:

curl http://localhost:7654/​api/​auth/​google/​login

Response:

{
  "url": "https://accounts.google.com/​o/​oauth2/​v2/​auth?...",
  "challenge": "...",
  "action": "login"
}

3. Complete full OAuth flow:

  • Visit the OAuth URL in browser
  • Complete provider login
  • Verify redirect to pathSuccess
  • Check api/​auth/​me returns user

DOs and DON'Ts

DO:

  • Store client secrets in environment variables
  • Use HTTPS in production
  • Set sameSite: "lax" for cookie (required for OAuth redirects)
  • Match callback URLs exactly in provider dashboard
  • Test OAuth flow in incognito (avoid cached sessions)
  • Set appropriate JWT expiration

DON'T:

  • Hardcode client secrets in code
  • Use secure: true cookie on localhost (no HTTPS)
  • Mix up client_id and client_secret
  • Forget to update callback URLs for production
  • Expect users to have multiple strategies (one per user)
  • Skip the challenge verification in token flow

Related Skills

  • bknd-setup-auth - Initialize authentication system
  • bknd-login-flow - Login/​logout functionality
  • bknd-registration - User registration setup
  • bknd-session-handling - Manage user sessions
  • bknd-create-role - Define user roles for OAuth users

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View