SecureStartKit
SecurityFeaturesPricingDocsBlogChangelog
Sign inBuy Now
Getting Started
Installation
Configuration
Deployment

Components

  • Hero
  • Pricing
  • Features

Features

  • Authentication
  • Payments
  • Emails
  • Database
  • Blog
  • Security Headers
  • Claude Code Skills

Recipes

  • Add a Server Action
  • Add a Database Table
  • Add an OAuth Provider
  • Add an Email Template
  • Customize the Auth Flow
  • Add an Admin Metric

Add an OAuth Provider

Add GitHub, Apple, Microsoft, or another OAuth provider to Supabase Auth. PKCE flow + server-side callback exchange + redirect-allowlist hardening.

What you are building

A new OAuth provider (GitHub, Apple, Microsoft, Discord, etc.) wired into the existing Supabase Auth flow. The browser initiates the OAuth redirect with PKCE; the provider redirects back to /auth/callback; the server-side callback route exchanges the auth code for a session using exchangeCodeForSession.

Google is already wired as the example provider; adding another follows the same three-touchpoint pattern.

Step 1: register the OAuth app with the provider

Each provider has its own OAuth registration UI. The fields you need:

  • Client ID (sometimes called "App ID")
  • Client Secret (sometimes called "App Secret")
  • Authorized redirect URI: https://<your-supabase-project-ref>.supabase.co/auth/v1/callback

You can find your Supabase project ref under Supabase Dashboard > Settings > General > Reference ID. The redirect URI is Supabase's URL, NOT your app's URL, because Supabase Auth is the OAuth intermediary.

For most providers the rest of the registration is name, logo, and consent-screen copy. Set the consent screen to use your app name + domain, not "supabase.co", so the user sees your brand during the consent step.

Step 2: enable the provider in Supabase

In the Supabase Dashboard, go to Authentication > Providers. Find your provider (GitHub, Apple, Discord, etc.) and enable it. Paste the Client ID and Client Secret from Step 1.

While you are in the dashboard, also visit Authentication > URL Configuration and confirm:

  • Site URL matches your production domain (https://yourdomain.com)
  • Redirect URLs allowlist contains the callback paths you actually use:
    • http://localhost:3000/auth/callback (local dev)
    • https://yourdomain.com/auth/callback (production)
    • any preview-deployment URL pattern you use

Use exact paths in production. Wildcards like ** against the production domain create an open-redirect primitive. See Supabase OAuth, magic links, MFA for the full allowlist-hardening rules.

Step 3: add the provider to config.ts

// config.ts
auth: {
  providers: ['email', 'google', 'github'], // Added 'github'
}

Step 4: add the Server Action

Add a sign-in action in actions/auth.ts. It mirrors the existing loginWithGoogle():

// actions/auth.ts
'use server'

import { createServerClientWithCookies } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'

export async function loginWithGitHub() {
  const supabase = await createServerClientWithCookies()
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider: 'github',
    options: {
      redirectTo: `${process.env.NEXT_PUBLIC_APP_URL}/auth/callback`,
      scopes: 'read:user user:email', // GitHub-specific scopes
    },
  })

  if (error) {
    console.error('GitHub OAuth init failed:', error)
    redirect('/login?error=oauth_failed')
  }

  if (data.url) {
    redirect(data.url)
  }
}

Two things to know:

  • redirectTo MUST match an entry in your Supabase Redirect URLs allowlist (Step 2). Mismatches cause Supabase to silently fall back to the Site URL, which is usually not what you want.
  • Scopes are provider-specific. GitHub uses read:user user:email for basic profile + email access. Apple, Microsoft, Discord all have their own scope vocabularies; check the provider's OAuth docs.

Step 5: add the login button

In components/forms/login-form.tsx, add a button that calls the new action:

import { loginWithGitHub } from '@/actions/auth'

// Inside the login form JSX
<form action={loginWithGitHub}>
  <button type="submit">
    Sign in with GitHub
  </button>
</form>

Each OAuth provider gets its own <form action={...}> because Server Actions run on form submission and the redirect needs to happen server-side. Inline <button onClick> handlers do not work for OAuth redirects.

Why this is shaped this way

The OAuth flow uses PKCE by default in @supabase/ssr. The code-for-session exchange happens server-side at /auth/callback via exchangeCodeForSession. This is the only safe pattern for browser-initiated auth: an attacker who intercepts the URL with the auth code (via referer leak, log capture, or browser history) cannot complete the exchange without the original PKCE verifier that was generated client-side.

The legacy implicit flow (tokens in the URL fragment) is deprecated and unsafe. @supabase/ssr defaults to PKCE; do not change this.

Common mistakes

  • Wildcard in production redirect allowlist. A ** against your production domain accepts arbitrary paths under your domain and turns the OAuth callback into an open-redirect primitive that attackers can use for phishing. Use exact paths.
  • Mismatched redirectTo. If the redirectTo value in your signInWithOAuth call does not exactly match an allowlist entry, Supabase falls back to the Site URL silently. Symptom: user lands at / after auth instead of /auth/callback, and no session is established.
  • Trusting the next query parameter without validation. A common pattern is to use ?next=/some-path to remember where to send the user after auth. Always validate that next is a path on your own domain (starts with /, no protocol, no //), or use a server-side session cookie instead. Unvalidated next is the OWASP A07 open-redirect pattern.
  • Adding the OAuth button without testing the callback. The callback route is a separate failure surface. Run the full flow end-to-end in local dev with the actual provider before shipping.

What to read next

  • Supabase OAuth, magic links, MFA, the secure implementation guide for the full PKCE + redirect-allowlist + MFA architecture.
  • Authentication feature docs for the broader auth surface in this template.