Pular para o conteúdo
📖 COOKBOOK

Signup com Google em 15 linhas.

Adiciona OAuth Google a um app Next.js 15. Cobre setup no Console Google, redirect flow, callback e sessão persistente via cookie.

O que vamos fazer

Ao fim deste cookbook, seu app Next.js 15 terá:

  • Um botão "Entrar com Google" que redireciona pro consentimento do Google
  • Callback handler que troca o code por uma sessão SuperDB
  • Sessão persistente via cookie httpOnly (server e client com acesso)
  • Usuário salvo automaticamente em auth.users (e em public.profiles via trigger, se quiser)
  • Server component que lê o usuário autenticado via db.auth.getUser()

Pré-requisitos

  • Conta SuperDB no plano Pro+ (OAuth está liberado também no Free, mas Pro libera mais redirect URIs)
  • Console Google Cloud com um OAuth 2.0 Client ID criado (tipo "Web application")
  • Next.js 15 com App Router
  • Pacote instalado:
terminal
npm install @superdb/supabase-compat

Variáveis de ambiente em .env.local:

.env.local
NEXT_PUBLIC_SUPERDB_URL=https://api.superdb.com.br
NEXT_PUBLIC_SUPERDB_ANON_KEY=eyJhbGciOi...

Passo 1 — Configurar OAuth no Google Console

No Google Cloud Console:

  1. Crie um projeto (ou use existente)
  2. Vá em APIs & Services → Credentials
  3. Clique Create Credentials → OAuth client ID
  4. Application type: Web application
  5. Em Authorized redirect URIs, adicione:
Authorized redirect URIs
https://api.superdb.com.br/auth/v1/callback
http://localhost:9999/callback

O primeiro é o callback do SuperDB (produção). O segundo só é necessário se você for testar self-host local. Copie Client ID e Client Secret — você vai colar no próximo passo.

⚠️

Atenção: a URL acima precisa bater exatamente com o que está no Console — Google compara byte a byte. Trailing slash, http vs https, porta — qualquer diferença e o redirect falha com redirect_uri_mismatch.

Passo 2 — Configurar provider no Dashboard

No Dashboard SuperDB do seu projeto:

  1. Vá em Auth → Providers
  2. Clique em Google
  3. Toggle Enabled
  4. Cole o Client ID e o Client Secret do passo anterior
  5. Salve
💡

Dica: o Dashboard mostra a redirect URI exata que você precisa colar no Google Console — copie de lá em vez de digitar. Evita o erro mais comum.

Passo 3 — Botão de login no frontend

Crie um client component com o botão. Use signInWithOAuth passando o provider:

app/login/google-button.tsx
'use client'
import { createBrowserClient } from '@superdb/supabase-compat'

export function GoogleButton() {
  const db = createBrowserClient(
    process.env.NEXT_PUBLIC_SUPERDB_URL!,
    process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!
  )

  async function entrar() {
    await db.auth.signInWithOAuth({
      provider: 'google',
      options: {
        redirectTo: `${location.origin}/auth/callback`,
      },
    })
  }

  return <button onClick={entrar}>Entrar com Google</button>
}
app/login/google-button.js
'use client'
import { createBrowserClient } from '@superdb/supabase-compat'

export function GoogleButton() {
  const db = createBrowserClient(
    process.env.NEXT_PUBLIC_SUPERDB_URL,
    process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY
  )

  async function entrar() {
    await db.auth.signInWithOAuth({
      provider: 'google',
      options: { redirectTo: `${location.origin}/auth/callback` },
    })
  }

  return <button onClick={entrar}>Entrar com Google</button>
}
terminal
curl -X POST "$SUPERDB_URL/auth/v1/authorize?provider=google&redirect_to=http://localhost:3000/auth/callback" \
  -H "apikey: $ANON_KEY"

Clicar no botão dispara um redirect 302 do SuperDB pro Google. O usuário consente, Google manda de volta com ?code=... pra /auth/callback.

Passo 4 — Callback handler

Crie a rota que troca o code por sessão e seta o cookie:

app/auth/callback/route.ts
import { NextResponse } from 'next/server'
import { createServerClient } from '@superdb/supabase-compat/ssr'
import { cookies } from 'next/headers'

export async function GET(request: Request) {
  const { searchParams, origin } = new URL(request.url)
  const code = searchParams.get('code')
  const next = searchParams.get('next') ?? '/'

  if (code) {
    const cookieStore = await cookies()
    const db = createServerClient(
      process.env.NEXT_PUBLIC_SUPERDB_URL!,
      process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!,
      {
        cookies: {
          getAll: () => cookieStore.getAll(),
          setAll: (all) => all.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)),
        },
      }
    )
    const { error } = await db.auth.exchangeCodeForSession(code)
    if (!error) return NextResponse.redirect(`${origin}${next}`)
  }

  return NextResponse.redirect(`${origin}/login?erro=oauth`)
}

Passo 5 — Ler o usuário no server

Em qualquer server component ou middleware, recupere o usuário autenticado:

app/perfil/page.tsx
import { createServerClient } from '@superdb/supabase-compat/ssr'
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export default async function PerfilPage() {
  const cookieStore = await cookies()
  const db = createServerClient(
    process.env.NEXT_PUBLIC_SUPERDB_URL!,
    process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!,
    { cookies: { getAll: () => cookieStore.getAll(), setAll: () => {} } }
  )

  const { data: { user } } = await db.auth.getUser()
  if (!user) redirect('/login')

  return <div>Olá, {user.email}</div>
}

Resultado

Você tem um fluxo OAuth completo. Usuário clica, escolhe a conta Google, volta logado. Da próxima vez que abrir o app, a sessão é restaurada do cookie automaticamente — sem novo redirect.

meu-app.com/perfil
v0.4.2
Bem-vindo de volta
felipe@exemplo.com
✓ Sessão Google ativa · expira em 1h

Variações

Trocar por GitHub

Mesma receita, só muda o provider. Repita o passo 1 no GitHub Developers e troque a string:

diff
- provider: 'google',
+ provider: 'github',

Apple Sign-In

Idem. Precisa de Apple Developer Account ($99/ano), mas o código do app é igual:

app/login/apple-button.tsx
await db.auth.signInWithOAuth({
  provider: 'apple',
  options: { redirectTo: `${location.origin}/auth/callback` },
})

Refatore o botão pra receber o provider como prop:

app/login/oauth-buttons.tsx
'use client'
import { createBrowserClient } from '@superdb/supabase-compat'

const PROVIDERS = ['google', 'github', 'apple'] as const

export function OAuthButtons() {
  const db = createBrowserClient(
    process.env.NEXT_PUBLIC_SUPERDB_URL!,
    process.env.NEXT_PUBLIC_SUPERDB_ANON_KEY!
  )

  return PROVIDERS.map((p) => (
    <button key={p} onClick={() => db.auth.signInWithOAuth({
      provider: p,
      options: { redirectTo: `${location.origin}/auth/callback` }
    })}>Entrar com {p}</button>
  ))
}

Erros comuns

redirect_uri_mismatch

A URL no Console Google não bate com a do SuperDB. Solução: copie a redirect URI do Dashboard SuperDB e cole exatamente no Console — não digite.

Causa comum: chamando createServerClient sem repassar setAll dos cookies. O exchangeCodeForSession retorna a sessão, mas se você não escrever no cookieStore o Next.js não persiste. Confira o passo 4: o setAll precisa estar implementado.

Tentar usar a sessão antes de trocar o code

Se você fizer db.auth.getUser() no /auth/callback antes do exchangeCodeForSession rodar, vai retornar null — o code ainda não virou sessão. Sempre troque primeiro, depois redirect, e leia o user na página de destino.

ℹ️

Dúvida frequente: a sessão expira em 1h por padrão, mas o refresh token vale 30 dias e o SDK renova automaticamente. Você não precisa lidar com isso na mão.

Essa página ajudou?