Docs
OAuth Consent

OAuth Consent

OAuth 2.1 consent block for Next.js

Installation

Folder structure

This block includes the Supabase client. If you already have one installed, you can skip overwriting it.

  • app
    • oauth
      • consent
  • components
  • hooks
  • lib
    • supabase
1import { OAuthConsent } from '@/components/oauth-consent'
2
3export default async function ConsentPage({
4  searchParams,
5}: {
6  searchParams: Promise<{ authorization_id?: string }>
7}) {
8  const { authorization_id } = await searchParams
9
10  return (
11    <main className="flex min-h-svh items-center justify-center p-6 md:p-10">
12      <OAuthConsent className="w-full max-w-lg" authorizationId={authorization_id} />
13    </main>
14  )
15}

Usage

This block installs an OAuth 2.1 consent route at /oauth/consent. It is designed for an app that already has authentication: it does not install sign-in, sign-up, or callback routes.

When the visitor has no session, the consent screen redirects to /auth/login and preserves the original consent URL in the next query parameter. Update the signInPath prop in app/oauth/consent/page.tsx if your sign-in route is different.

After sign-in, your login page must send the visitor back to the path in next; otherwise the OAuth flow stops at your login screen. The password-based auth and social auth blocks follow next automatically. For a custom login page, validate that next is a relative path before redirecting to it:

// After sign-in succeeds:
const next = new URLSearchParams(window.location.search).get('next')
try {
  const nextUrl = new URL(next ?? '/protected', window.location.origin)
  router.push(
    nextUrl.origin === window.location.origin
      ? `${nextUrl.pathname}${nextUrl.search}${nextUrl.hash}`
      : '/protected'
  )
} catch {
  router.push('/protected')
}

Set the productName prop to replace the Your product placeholder in the consent header.

Your middleware must let unauthenticated requests reach /oauth/consent. The middleware in lib/supabase/middleware.ts exempts only /oauth/consent. Middleware that redirects to a login page before the consent route runs drops the authorization and ends the OAuth flow at your login screen.

Getting started

After installing the block, you'll have the following environment variables in your .env.local file:

NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
  • If you're using supabase.com, you can find these values in the Connect modal under App Frameworks or in your project's API settings.
  • If you're using a local instance of Supabase, you can find these values by running supabase start or supabase status (if you already have it running).

Configure the OAuth server

Enable the OAuth server in the Supabase Dashboard under Authentication > OAuth Server, then set its authorization URL path to /oauth/consent. For local development, set the following in supabase/config.toml:

[auth.oauth_server]
enabled = true
authorization_url_path = "/oauth/consent"

Recent CLI versions already write an [auth.oauth_server] section with enabled = false. Edit that section rather than adding a second one, which fails with table oauth_server already exists.

The route expects the authorization_id query parameter that Supabase Auth supplies during the authorization flow.

Further reading