Guia completo de login OAuth no Next.js: Google, GitHub e WeChat

Você clica em “Entrar com Google”, a página abre o Google, você autoriza o acesso e, ao voltar, o login já está concluído.
É um processo que todo mundo já viu inúmeras vezes. Mas, quando chega a hora de adicionar um login de terceiros ao próprio projeto, surgem várias dúvidas: por que há dois redirecionamentos? O que é uma URL de callback? O que significa redirect_uri_mismatch? Por que funciona localmente e falha depois da implantação?
Na primeira vez que configurei OAuth, li uma pilha de documentação repleta de termos como “código de autorização”, access_token e client_secret. Quanto mais eu lia, mais confuso ficava. Foram dois dias e muitos tropeços até eu entender o processo de verdade.
Neste artigo, quero explicar o login OAuth da maneira mais direta possível. Sem acumular jargão ou teoria desnecessária: vamos entender como ele realmente funciona e como configurar login com Google, GitHub e WeChat no Next.js. No fim, você vai perceber que não é nenhum bicho de sete cabeças.
O que é OAuth 2.0, afinal? Uma explicação simples
Primeiro, uma analogia do dia a dia
Imagine que você mora em um condomínio e fez uma compra online. Você quer que o entregador leve o pacote até a porta do apartamento, mas existe um problema: a entrada do condomínio é controlada, e ele não consegue passar.
Uma solução tradicional seria entregar seu cartão de acesso ao entregador. Isso seria arriscado: com o cartão em mãos, ele poderia voltar e entrar no condomínio quando quisesse.
Uma solução mais inteligente seria avisar a portaria de que uma entrega está chegando. O porteiro emite para o entregador um passe temporário, com regras como “válido apenas hoje, das 14h às 16h, e somente para o bloco A”. Depois da entrega, o passe deixa de funcionar.
Essa é a ideia central do OAuth.
Na analogia:
- Você = o usuário que quer entrar
- O entregador = o aplicativo de terceiros, como o site que você desenvolveu
- A portaria = o provedor OAuth, como Google, WeChat ou GitHub
- O cartão de acesso = sua senha, que não deve ser entregue a outra pessoa
- O passe temporário = o
access_token, que expira e possui permissões limitadas
Você não precisa entregar sua senha ao aplicativo terceiro. Basta autorizá-lo a obter um “passe temporário” com o provedor OAuth.
As cinco etapas do OAuth no fluxo de código de autorização
Agora vamos aplicar esse processo ao login OAuth em um projeto Next.js.
Primeira etapa: o usuário clica no botão “Entrar com Google” no seu site.
Segunda etapa: seu site redireciona o usuário para a página de autorização do Google, por meio de uma URL parecida com esta:
https://accounts.google.com/o/oauth2/auth?
client_id=ID_do_seu_aplicativo
&redirect_uri=http://localhost:3000/api/auth/callback/google
&response_type=code
&scope=openid email profile
&state=string_aleatória
Nesse momento, seu site está dizendo ao Google: “Sou este aplicativo (client_id), o usuário quer entrar usando uma conta de vocês. Peça a confirmação dele e, depois, envie-o de volta para este endereço (redirect_uri)”.
Terceira etapa: na página do Google, o usuário vê uma mensagem informando que o aplicativo quer acessar seus dados básicos e clica em “Permitir”.
Quarta etapa: o Google redireciona o usuário de volta ao seu site (redirect_uri) e inclui na URL um código de autorização (code):
http://localhost:3000/api/auth/callback/google?code=ABCD1234&state=string_aleatória
Esse código é apenas uma credencial provisória, não o passe definitivo. Ele expira rapidamente, normalmente em dez minutos, e só pode ser usado uma vez.
Quinta etapa: o backend do seu site envia esse código, junto com o client_secret, ao Google para trocá-lo por um access_token real:
// Código do backend (versão simplificada)
const response = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: JSON.stringify({
code: 'ABCD1234',
client_id: 'ID_do_seu_aplicativo',
client_secret: 'senha_do_seu_aplicativo',
redirect_uri: 'http://localhost:3000/api/auth/callback/google',
grant_type: 'authorization_code',
}),
})
const { access_token } = await response.json()
Com o access_token, seu site pode consultar os dados do usuário no Google, como e-mail, foto e nome.
Sexta etapa (opcional): usar o access_token para obter os dados do usuário:
const userInfo = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`,
},
})
Quando todo o fluxo termina, seu site sabe quem é o usuário, pode criar uma sessão e mantê-lo autenticado.
Os principais conceitos, sem complicação
Talvez alguns termos ainda pareçam confusos. Vamos explicá-los em linguagem simples:
-
client_id: é o “documento de identidade” do seu aplicativo no Google. Pode ser público; não há problema se alguém o vir.
-
client_secret: é a “senha” do seu aplicativo. Nunca pode vazar e deve ser usada apenas no backend. Se outra pessoa obtiver seu
client_secret, poderá se passar pelo aplicativo para acessar dados de usuários. -
redirect_uri: indica para qual endereço o Google deve enviar o usuário depois da autorização. Essa URL precisa ser cadastrada antes no Google Cloud Console e é validada de forma rigorosa. Até uma barra extra pode gerar erro — sim, é o irritante
redirect_uri_mismatch. -
state: uma string aleatória usada para evitar ataques CSRF. Você gera o
stateao iniciar a autorização, e o Google o devolve sem alterações. É preciso comparar o valor recebido com o enviado; se forem diferentes, a solicitação pode ter sido falsificada. -
code: é o código de autorização temporário. Ele expira em cerca de dez minutos e só pode ser usado uma vez. Serve para comprovar que “o usuário autorizou o acesso no Google”.
-
access_token: é o “passe” de verdade. Com ele, seu site pode consultar dados no Google em nome do usuário. O
access_tokentambém expira, geralmente depois de uma hora ou de alguns dias, dependendo do provedor.
Por que existem duas etapas, uma para o code e outra para o access_token?
Talvez você se pergunte por que o Google não devolve logo o access_token, em vez de exigir uma troca intermediária.
O motivo é segurança. O code passa por um redirecionamento do navegador e fica visível no frontend, enquanto o access_token é transmitido diretamente entre servidores, sem aparecer no navegador. Se o token fosse retornado na URL, ele poderia vazar pelo histórico, pelos logs ou por ferramentas de monitoramento de rede. A troca do código pelo token exige o client_secret, que existe apenas no backend, tornando o processo muito mais seguro.
Como configurar login com Google usando Next.js e NextAuth.js
Por que escolher NextAuth.js?
Implementar todo o fluxo OAuth por conta própria dá bastante trabalho: você precisa processar callbacks, gerenciar sessões, evitar ataques CSRF, armazenar tokens e cuidar de vários outros detalhes.
A boa notícia é que existe uma biblioteca chamada NextAuth.js — agora conhecida como Auth.js v5 — feita especificamente para isso. Ela tem mais de 15 mil estrelas no GitHub, uma comunidade ativa e suporte a mais de 50 provedores OAuth, incluindo Google, GitHub, WeChat e Twitter. A versão mais recente funciona com o App Router do Next.js 14+ e é mais simples de configurar do que as anteriores.
Em resumo, NextAuth.js elimina cerca de 80% do trabalho repetitivo.
Primeira etapa: criar um aplicativo no Google Cloud
Antes de escrever código, você precisa “cadastrar” seu aplicativo no Google e obter um client_id e um client_secret.
-
Abra o Google Cloud Console e entre com sua conta Google.
-
Se nunca usou a plataforma, crie primeiro um projeto. O nome pode ser qualquer um, como “My Next.js App”.
-
No menu lateral, acesse “APIs e serviços” → “Credenciais”.
-
Clique em “Criar credenciais” e selecione “ID do cliente OAuth”.
-
No primeiro acesso, talvez seja necessário configurar a “Tela de consentimento OAuth”. Informe o nome do aplicativo e um e-mail de suporte; o restante pode ficar para depois. Escolha o tipo de usuário “Externo”. Durante os testes, não é necessário passar pela verificação.
-
Volte à criação do ID de cliente OAuth e selecione “Aplicativo da Web” como tipo de aplicativo.
-
Este é o ponto mais importante: configure as “URIs de redirecionamento autorizadas”. Adicione estes dois endereços:
- Desenvolvimento local:
http://localhost:3000/api/auth/callback/google - Produção, depois da implantação:
https://yourdomain.com/api/auth/callback/google
A URL precisa ser exatamente igual à usada no código. Uma barra a mais ou a menos já provoca o erro
redirect_uri_mismatch. Eu mesmo tropecei nisso na primeira configuração. - Desenvolvimento local:
-
Clique em “Criar”. Uma janela exibirá o Client ID e o Client Secret. Copie os dois valores para usá-los em seguida.
Segunda etapa: instalar NextAuth.js e configurar as variáveis de ambiente
No projeto Next.js, instale o pacote:
npm install next-auth@beta
É importante usar a versão @beta, que corresponde à v5 mais recente.
Depois, crie o arquivo .env.local na raiz do projeto e preencha o Client ID e o Secret obtidos anteriormente:
GOOGLE_CLIENT_ID=seu_Client_ID.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=seu_Client_Secret
NEXTAUTH_SECRET=gere_uma_string_aleatória
NEXTAUTH_URL=http://localhost:3000
Você pode gerar o NEXTAUTH_SECRET com este comando:
openssl rand -base64 32
Ao implantar em produção, lembre-se de trocar o NEXTAUTH_URL pelo seu domínio.
Terceira etapa: criar o arquivo de configuração do NextAuth
Crie app/api/auth/[...nextauth]/route.ts. Se o projeto usa Pages Router, o caminho é pages/api/auth/[...nextauth].ts:
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
callbacks: {
async signIn({ user, account, profile }) {
// Callback executado após o login; você pode salvar o usuário no banco aqui
console.log("Login do usuário:", user)
return true // true permite o login
},
async session({ session, token }) {
// Personaliza o conteúdo da sessão
if (session.user) {
session.user.id = token.sub // Adiciona o ID do usuário à sessão
}
return session
},
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
Pronto. NextAuth.js processa automaticamente todo o fluxo OAuth. A rota /api/auth/callback/google também é criada pela biblioteca, então você não precisa implementá-la.
Quarta etapa: criar o botão de login
Em qualquer componente, você pode criar o botão desta forma:
'use client' // O App Router exige que este seja um Client Component
import { signIn, signOut, useSession } from "next-auth/react"
export default function LoginButton() {
const { data: session } = useSession()
if (session) {
// O usuário está autenticado
return (
<div>
<p>Olá, {session.user?.name}</p>
<img src={session.user?.image || ''} alt="Foto de perfil" />
<button onClick={() => signOut()}>Sair</button>
</div>
)
}
// O usuário não está autenticado
return <button onClick={() => signIn('google')}>Entrar com Google</button>
}
signIn('google') redireciona automaticamente para a página de autorização do Google. Depois da autorização, o usuário volta ao site já autenticado. É bem simples.
Quinta etapa: envolver o layout raiz com SessionProvider
Para usar useSession em todos os componentes, envolva o conteúdo do layout raiz com o Provider:
// app/layout.tsx
import { SessionProvider } from "next-auth/react"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<SessionProvider>{children}</SessionProvider>
</body>
</html>
)
}
Tudo pronto. Agora você tem um aplicativo Next.js com login pelo Google.
Solução de problemas comuns
Problema 1: redirect_uri_mismatch
Esse é o erro mais comum, e eu também o encontrei na primeira configuração.
A mensagem costuma ser: Error 400: redirect_uri_mismatch.
Causa: a URL de callback cadastrada no Google Cloud Console não corresponde à URL usada na solicitação.
Solução:
- Confirme se a “URI de redirecionamento autorizada” no Google Cloud Console é
http://localhost:3000/api/auth/callback/googlee verifique se não há uma barra extra. - Confirme se
NEXTAUTH_URLno.env.localéhttp://localhost:3000. - Se você mudou a porta, por exemplo para 3001, altere-a nos dois lugares.
Problema 2: funciona no desenvolvimento local, mas o login falha depois da implantação
Eu também já passei por isso. Localmente, o login funcionava perfeitamente; depois da implantação na Vercel, o botão não fazia nada ou retornava um erro.
Causa: as variáveis de ambiente de produção não foram atualizadas.
Solução:
- Adicione a URL do domínio de produção às “URIs de redirecionamento autorizadas” no Google Cloud Console:
https://yourdomain.com/api/auth/callback/google. - Nas configurações de variáveis de ambiente da Vercel, ou da sua plataforma de hospedagem, defina
NEXTAUTH_URLcomohttps://yourdomain.com. - Faça uma nova implantação.
Problema 3: a session continua null depois do login
Se useSession() sempre retorna uma session nula, verifique se você esqueceu de envolver o layout raiz com <SessionProvider>.
Problema 4: TypeError: Cannot read property ‘user’ of null
Normalmente, isso acontece porque a session ainda está carregando quando o código tenta acessar session.user.
Solução: confirme primeiro se a session existe:
const { data: session, status } = useSession()
if (status === 'loading') {
return <div>Carregando...</div>
}
if (!session) {
return <div>Não autenticado</div>
}
// Agora é seguro acessar session.user
Configuração do login com GitHub e principais diferenças
Depois de configurar o Google, adicionar o GitHub fica bem mais fácil. Ainda assim, existem algumas diferenças importantes entre os dois.
Diferenças entre o OAuth do GitHub e o do Google
O que eles têm em comum: ambos usam o fluxo padrão de código de autorização do OAuth 2.0, com as mesmas etapas gerais.
As diferenças:
- Controle de permissões mais detalhado: o scope do GitHub é mais específico que o do Google. Por padrão, o aplicativo acessa apenas dados públicos. Para obter o e-mail do usuário, especialmente se for privado, é preciso solicitar a permissão
user:email. - Configuração de callback mais flexível: o Google exige a URL completa de callback; no GitHub, a configuração é menos rígida.
- Tipos de aplicativo: o GitHub permite OAuth Apps associados a contas pessoais ou organizações.
Primeira etapa: criar um OAuth App no GitHub
-
Entre no GitHub, clique na foto de perfil no canto superior direito e acesse Settings. No menu lateral, abra “Developer settings”.
-
Clique em “OAuth Apps” → “New OAuth App”.
-
Preencha os dados do aplicativo:
- Application name: nome do aplicativo, que aparecerá na tela de autorização
- Homepage URL: página inicial do site, como
http://localhost:3000 - Authorization callback URL: use
http://localhost:3000/api/auth/callback/github
-
Clique em “Register application”, depois em “Generate a new client secret” e copie o Client ID e o Client Secret.
Segunda etapa: configurar as variáveis de ambiente
Adicione a configuração do GitHub ao .env.local:
GITHUB_CLIENT_ID=seu_GitHub_Client_ID
GITHUB_CLIENT_SECRET=seu_GitHub_Client_Secret
Terceira etapa: atualizar a configuração do NextAuth
No arquivo route.ts criado anteriormente, adicione GitHubProvider:
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import GitHubProvider from "next-auth/providers/github"
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
// Para obter o e-mail privado do usuário, adicione esta configuração
authorization: {
params: {
scope: 'read:user user:email'
}
}
}),
],
callbacks: {
// ... callbacks anteriores
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
Quarta etapa: atualizar os botões de login
Adicione a opção de login com GitHub ao componente:
return (
<div>
<button onClick={() => signIn('google')}>Entrar com Google</button>
<button onClick={() => signIn('github')}>Entrar com GitHub</button>
</div>
)
Pronto.
Entendendo o scope, ou escopo de permissões
O scope do GitHub controla quais dados do usuário seu aplicativo pode acessar. Os mais usados são:
read:user: lê dados públicos e privados do perfil, como nome, foto e biouser:email: lê os e-mails do usuário, inclusive os privadospublic_repo: acessa os repositórios públicos do usuáriorepo: acessa todos os repositórios, públicos e privados; é uma permissão ampla e deve ser usada com cuidado
Para um fluxo de login, read:user user:email é suficiente.
Sem o scope user:email, NextAuth.js só obtém o e-mail público. Se o usuário ocultou o endereço nas configurações do GitHub, session.user.email será null. Passei um bom tempo tentando descobrir se havia algo errado no meu código por causa disso.
Um detalhe importante: o usuário do GitHub pode não ter e-mail público
Ao contrário do Google, que exige um e-mail, o GitHub permite ocultá-lo. Se seu aplicativo depende do endereço, por exemplo para enviar notificações, verifique-o no callback signIn:
async signIn({ user, account }) {
if (account?.provider === 'github' && !user.email) {
// O usuário não forneceu um e-mail público; você pode recusar o login ou avisá-lo
console.log("Usuário do GitHub sem e-mail")
return false // Recusa o login
}
return true
}
Configuração do login com WeChat: particularidades do mercado chinês
Agora vamos falar sobre o WeChat. Para ser sincero, esse login é bem mais complexo que Google e GitHub, principalmente porque o ecossistema funciona de outra maneira.
Por que o login com WeChat é diferente?
Estas são as principais diferenças:
- Exige leitura de QR code: em sites para desktop, o usuário precisa abrir o WeChat no celular e ler um QR code para autorizar o acesso. Não basta clicar em uma página como no Google ou GitHub.
- Não existe Provider oficial no NextAuth.js: NextAuth.js não inclui um provider para WeChat, então você precisa criar um.
- Há mais restrições para o callback: o WeChat exige um domínio de callback com registro ICP e não aceita
localhost, o que dificulta os testes locais. - Existem openid e unionid: a identificação do usuário funciona de forma particular. O mesmo usuário recebe um
openiddiferente em cada aplicativo. Para compartilhar dados entre vários aplicativos, é necessário usar ounionid.
Primeira etapa: cadastrar-se na WeChat Open Platform
-
Acesse a WeChat Open Platform e crie uma conta.
-
Crie um “aplicativo para sites”. Não se trata de uma conta oficial nem de um Mini Program.
-
Preencha os dados do site, envie capturas de tela e aguarde a análise. O processo normalmente leva de um a três dias úteis.
-
Depois da aprovação, você receberá um AppID e um AppSecret, equivalentes a
client_ideclient_secret. -
Na área de informações de desenvolvimento, configure o domínio de callback autorizado. Informe apenas o domínio, sem o caminho completo, por exemplo
yourdomain.com.
Segunda etapa: criar um Provider personalizado para WeChat
Como NextAuth.js não inclui um provider para WeChat, precisamos criá-lo. Adicione o arquivo lib/wechat-provider.ts ao projeto:
import type { OAuthConfig, OAuthUserConfig } from "next-auth/providers"
export interface WeChatProfile {
openid: string
nickname: string
headimgurl: string
sex: number
province: string
city: string
country: string
unionid?: string
}
export default function WeChatProvider<P extends WeChatProfile>(
options: OAuthUserConfig<P>
): OAuthConfig<P> {
return {
id: "wechat",
name: "WeChat",
type: "oauth",
// URL de autorização do WeChat para aplicativos de sites em desktop
authorization: {
url: "https://open.weixin.qq.com/connect/qrconnect",
params: {
scope: "snsapi_login",
appid: options.clientId,
response_type: "code",
},
},
// URL para trocar o código de autorização pelo access_token
token: {
url: "https://api.weixin.qq.com/sns/oauth2/access_token",
params: {
appid: options.clientId,
secret: options.clientSecret,
grant_type: "authorization_code",
},
},
// URL para obter os dados do usuário
userinfo: {
url: "https://api.weixin.qq.com/sns/userinfo",
async request({ tokens, provider }) {
const res = await fetch(
`${provider.userinfo?.url}?access_token=${tokens.access_token}&openid=${tokens.openid}&lang=zh_CN`
)
return await res.json()
},
},
// Converte os dados do WeChat para o formato padrão do NextAuth
profile(profile) {
return {
id: profile.openid,
name: profile.nickname,
email: null, // O WeChat não fornece e-mail
image: profile.headimgurl,
}
},
options,
}
}
Terceira etapa: configurar as variáveis de ambiente
Adicione as configurações do WeChat ao .env.local:
WECHAT_CLIENT_ID=seu_AppID_do_WeChat
WECHAT_CLIENT_SECRET=seu_AppSecret_do_WeChat
Quarta etapa: usar o Provider no NextAuth
Atualize route.ts:
import WeChatProvider from "@/lib/wechat-provider"
export const authOptions = {
providers: [
GoogleProvider({...}),
GitHubProvider({...}),
WeChatProvider({
clientId: process.env.WECHAT_CLIENT_ID!,
clientSecret: process.env.WECHAT_CLIENT_SECRET!,
}),
],
}
Quinta etapa: como testar no ambiente local?
Esse é um ponto complicado. Como o WeChat não aceita localhost como domínio de callback, não é possível testar a integração localmente de forma direta.
Existem duas alternativas:
Opção 1: usar uma ferramenta de túnel
Use ngrok ou cpolar para expor o serviço local à internet:
# Instale o ngrok
brew install ngrok
# Inicie o túnel para o serviço local
ngrok http 3000
O ngrok fornecerá um domínio temporário, como https://abc123.ngrok.io. Cadastre esse domínio como domínio de callback na WeChat Open Platform e atualize o NEXTAUTH_URL no .env.local:
NEXTAUTH_URL=https://abc123.ngrok.io
Opção 2: configurar o arquivo hosts
Adicione esta linha ao arquivo hosts local — /etc/hosts no macOS e Linux ou C:\Windows\System32\drivers\etc\hosts no Windows:
127.0.0.1 dev.yourdomain.com
Depois, acesse http://dev.yourdomain.com:3000 e cadastre dev.yourdomain.com como domínio de callback na WeChat Open Platform.
Essa opção tem uma limitação: o WeChat exige que o domínio de callback tenha registro ICP, portanto dev.yourdomain.com ainda pode ser recusado. Na prática, a primeira opção é mais confiável.
Tratamento específico do login com WeChat
O WeChat não fornece o e-mail do usuário. Se seu aplicativo depende dessa informação, será necessário tratar o caso separadamente:
async signIn({ user, account }) {
if (account?.provider === 'wechat') {
// O usuário do WeChat não tem e-mail; você pode pedir que ele o informe
// Outra opção é usar o openid como identificador único no banco de dados
console.log("openid do usuário do WeChat:", user.id)
}
return true
}
Boas práticas de segurança para evitar erros comuns
Depois de configurar o login OAuth, ainda há alguns detalhes de segurança importantes. Aprendi muitos deles da maneira difícil.
1. Nunca exponha o client_secret
Forma errada:
// ❌ Nunca faça isso!
const clientSecret = "abc123def456" // Valor fixo no código
Se você colocar o client_secret no frontend ou enviá-lo para um repositório Git, outra pessoa poderá se passar pelo seu aplicativo e acessar dados dos usuários.
Forma correta:
- Armazene-o em uma variável de ambiente e inclua
.env.localno.gitignore - Use o
client_secretapenas no backend. A API route do NextAuth.js roda no servidor, portanto é apropriada - Em produção, use o gerenciador de variáveis de ambiente da plataforma, como Settings → Environment Variables na Vercel
2. Para que serve o parâmetro state: proteção contra CSRF
O fluxo OAuth usa um parâmetro chamado state para evitar ataques CSRF.
Um possível ataque funciona assim: alguém cria um link malicioso com um código de autorização falsificado e tenta convencer você a clicar. Se o aplicativo não validar o state, poderá aceitar o código forjado e trocá-lo por um token.
A boa notícia é que NextAuth.js faz essa validação automaticamente, sem exigir código adicional.
Se você implementar OAuth manualmente, sem NextAuth.js:
- Gere um
statealeatório ao iniciar a autorização e armazene-o na session ou em um cookie. - No callback, confira se o
stateretornado é igual ao valor enviado. - Recuse a solicitação se os valores forem diferentes.
3. Lista de URLs de callback permitidas
Cadastre no provedor OAuth — Google, GitHub ou WeChat — todas as URLs de callback que poderão ser usadas:
- Ambiente de desenvolvimento:
http://localhost:3000/api/auth/callback/[provider] - Ambiente de preview:
https://preview.yourdomain.com/api/auth/callback/[provider] - Ambiente de produção:
https://yourdomain.com/api/auth/callback/[provider]
Não use curingas, como https://*.yourdomain.com. Embora pareçam convenientes, eles reduzem a segurança. Liste explicitamente todos os domínios para evitar que um invasor explore uma URL inesperada.
4. Segurança no armazenamento de tokens
Por padrão, NextAuth.js usa JWT para armazenar a session, com o token salvo em um cookie HttpOnly. Essa é uma boa escolha:
- HttpOnly: o JavaScript do frontend não consegue ler o cookie, o que ajuda a impedir o roubo do token em ataques XSS
- Secure em produção: o cookie só é enviado por HTTPS, reduzindo o risco de interceptação
O que você deve fazer:
- Não envie o
access_tokenao frontend. NextAuth.js não faz isso por padrão, e você também não deve adicioná-lo manualmente - Se precisar persistir dados do usuário, salve-os no banco no callback
signIne mantenha apenas o essencial na session, como ID e e-mail
5. Prazo de validade do código de autorização
O código de autorização do OAuth expira rapidamente, em cerca de dez minutos, e só pode ser usado uma vez.
Essa é uma medida de segurança: mesmo que alguém intercepte o code, talvez ele já tenha expirado ou já tenha sido usado quando o invasor tentar aproveitá-lo.
Se o usuário passar muito tempo na página de autorização, por exemplo porque foi tomar um café, o código pode expirar. NextAuth.js trata esse caso automaticamente e inicia uma nova autorização.
6. Checklist para o ambiente de produção
Antes da implantação, confira estes pontos:
- Todas as variáveis de ambiente estão definidas (
NEXTAUTH_URL,NEXTAUTH_SECRETe oclient_ideclient_secretde cada provider)? -
NEXTAUTH_URLusa o domínio de produção, e nãolocalhost? - As URLs de callback de produção foram cadastradas nos provedores OAuth?
-
.env.localestá no.gitignore, garantindo que os secrets não sejam enviados ao Git? - O
NEXTAUTH_SECRETde produção foi gerado aleatoriamente, sem reutilizar o valor do ambiente de desenvolvimento?
Resumo
Depois de tantos detalhes, vamos recapitular.
OAuth funciona essencialmente como um “passe temporário”: você não entrega sua senha a um aplicativo terceiro; apenas o autoriza a obter do provedor OAuth uma credencial com prazo de validade e permissões limitadas, o access_token. O processo acontece em duas partes: primeiro, o code comprova que o usuário autorizou o acesso; depois, o backend troca code + client_secret pelo token real.
No Next.js, Google é a opção mais simples e o melhor ponto de partida. GitHub exige um pouco mais de atenção, principalmente ao scope e à possibilidade de o usuário não ter um e-mail público. WeChat é o caso mais particular: usa QR code, exige um provider personalizado e um domínio de callback com registro ICP, além de tornar os testes locais mais trabalhosos.
Em segurança, lembre-se de três princípios:
- Use o client_secret apenas no backend e nunca o exponha.
- Sempre valide o parâmetro state — NextAuth.js faz isso para você.
- Use uma lista explícita de URLs de callback, sem curingas.
Se esta é sua primeira configuração OAuth, recomendo começar pelo Google e seguir o código deste artigo etapa por etapa. Ver o login funcionar pela primeira vez dá uma ótima sensação.
Se surgir algum problema, não entre em pânico: em 90% dos casos, a causa é uma URL redirect_uri incorreta ou uma variável de ambiente ausente. Revise esses pontos e, normalmente, tudo volta a funcionar.
Por fim, consulte a documentação oficial do NextAuth.js para conhecer recursos avançados, como armazenamento de sessões no banco de dados, páginas de login personalizadas e configuração de JWT. A especificação oficial do OAuth 2.0, RFC 6749, também vale a leitura. Quando você entende o princípio, fica muito mais fácil diagnosticar novos problemas.
Agora é sua vez. Boa configuração!
Fluxo completo para configurar login OAuth de terceiros no Next.js
Configure do zero o login de terceiros com Google, GitHub e WeChat
⏱️ Estimated time: 2 hr
- 1
Step 1: Instalar e inicializar o NextAuth.js
Instale a dependência:
• npm install next-auth
• Crie app/api/auth/[...nextauth]/route.ts
Configuração básica:
• Defina NEXTAUTH_URL (local: http://localhost:3000; produção: domínio real)
• Defina NEXTAUTH_SECRET (gere uma string aleatória)
• Configure o array básico de providers - 2
Step 2: Configurar o login com Google
Etapas:
1. Acesse o Google Cloud Console
2. Crie um ID de cliente OAuth
3. Defina a URI de callback autorizada: http://localhost:3000/api/auth/callback/google
4. Obtenha o Client ID e o Client Secret
5. Adicione às variáveis de ambiente: GOOGLE_CLIENT_ID e GOOGLE_CLIENT_SECRET
6. Adicione GoogleProvider à configuração do NextAuth
Atenção: a URL de callback em produção precisa ser exatamente igual à cadastrada - 3
Step 3: Configurar o login com GitHub
Etapas:
1. Acesse GitHub Settings > Developer settings > OAuth Apps
2. Crie um novo OAuth App
3. Defina a Authorization callback URL: http://localhost:3000/api/auth/callback/github
4. Obtenha o Client ID e o Client Secret
5. Adicione às variáveis de ambiente: GITHUB_CLIENT_ID e GITHUB_CLIENT_SECRET
6. Adicione GitHubProvider à configuração do NextAuth
Atenção: o scope precisa incluir user:email para obter o e-mail - 4
Step 4: Configurar o login com WeChat (opcional)
Etapas:
1. Cadastre uma conta na WeChat Open Platform (exige verificação empresarial)
2. Crie um aplicativo para sites e obtenha AppID e AppSecret
3. Defina o domínio de callback autorizado (o domínio precisa ter registro ICP)
4. Crie um Provider personalizado (o NextAuth não inclui WeChat)
5. Implemente o fluxo de login por QR code
Atenção: o login com WeChat é mais complexo; conclua primeiro Google e GitHub - 5
Step 5: Criar a página e os botões de login
Crie o componente de login:
• Use signIn('google') para iniciar o login
• Use signOut() para sair
• Use useSession() para obter os dados do usuário
• Envolva o aplicativo com SessionProvider
Exemplo:
<button onClick={() => signIn('google')}>
Entrar com Google
</button> - 6
Step 6: Testar e depurar
Pontos de teste:
• Teste local: confirme que a URL de callback é http://localhost:3000
• Produção: confirme que a URL de callback corresponde ao domínio real
• Verifique se as variáveis de ambiente estão corretas
• Consulte o console do navegador e os logs do servidor
Erros comuns:
• redirect_uri_mismatch: a URL de callback não corresponde
• invalid_client: Client ID ou Secret incorreto
• access_denied: o usuário recusou a autorização
FAQ
Como funciona o OAuth 2.0?
Como resolver o erro redirect_uri_mismatch?
Solução:
1) Confirme que a URL cadastrada no provedor OAuth é exatamente igual à usada no código, incluindo protocolo, domínio, porta e caminho
2) No desenvolvimento local, use http://localhost:3000; em produção, use o domínio real
3) Verifique se há barras ou parâmetros extras
Qual é a diferença entre usar NextAuth.js e implementar OAuth manualmente?
• Oferece suporte a mais de 50 provedores
• Cuida automaticamente do fluxo de autorização, da sessão e da proteção contra CSRF
Na implementação manual, você precisa cuidar de:
• Troca do código de autorização
• Armazenamento do token
• Validação do state, entre outros detalhes
Isso exige mais código e aumenta o risco de erro, por isso é recomendável usar NextAuth.js.
Como obter o endereço de e-mail do usuário?
• Google: retorna o e-mail por padrão
• GitHub: exige user:email no scope, e o usuário precisa deixar o e-mail público
• WeChat: exige uma consulta por unionid
Se o e-mail não estiver disponível, você pode pedir que o usuário o informe depois do login.
Por que tudo funciona localmente, mas ocorre um erro em produção?
Verifique:
1) Se NEXTAUTH_URL está correto em produção
2) Se a URL de callback cadastrada no provedor OAuth inclui o domínio de produção
3) Se as variáveis de ambiente estão configuradas corretamente
4) Se algum firewall ou proxy está interferindo
É possível oferecer vários métodos de login ao mesmo tempo?
O login OAuth é seguro?
Ainda assim, é preciso tomar alguns cuidados:
1) O client_secret deve permanecer confidencial e ser usado apenas no servidor
2) Use o parâmetro state para evitar ataques CSRF (NextAuth.js faz isso automaticamente)
3) Use uma lista de URLs de callback permitidas, sem curingas
4) Atualize as dependências regularmente
21 min de leitura · Publicado em: 19 dez 2025 · Atualizado em: 4 set 2026
Guia completo Next.js
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Proteção de rotas e controle de acesso no Next.js: guia completo de Middleware e defesa em camadas
Entenda como proteger rotas e controlar permissões no Next.js, do Middleware à defesa em camadas, usando NextAuth e getServerSession para implementar um sistema RBAC seguro, com exemplos completos de código.
Parte 12 de 51
Próximo
Login OAuth no Next.js: integração passo a passo com Google, GitHub e WeChat
Entenda o OAuth com uma analogia simples de retirada de encomenda e implemente login com Google, GitHub e WeChat no NextAuth.js, incluindo um guia completo de solução de erros.
Parte 14 de 51



Comentários
Entre com GitHub para comentar