NextAuth.js para iniciantes: guia completo de login com Credentials e gerenciamento de sessão

Ao abrir a documentação oficial do NextAuth.js, você se depara com tantas opções de configuração que é fácil ficar perdido. Provider, Session, Adapter, JWT, Callbacks… cada termo parece familiar, mas o conjunto não faz sentido de imediato. A documentação diz que “JWT é o padrão”, mas logo depois afirma que “ao usar um banco de dados, a estratégia muda automaticamente para Session”. Afinal, qual escolher?
Na época, quase desisti e fui direto para o Clerk. Mas pensei melhor: embora o Clerk seja rápido de configurar, você começa a pagar depois de ultrapassar a cota gratuita de 10.000 usuários ativos por mês, e várias personalizações ficam limitadas. O NextAuth.js é um pouco mais difícil no início, mas é totalmente gratuito e oferece controle completo.
Este artigo não vai listar todas as opções de configuração — isso seria um sofrimento. O foco é o cenário mais comum de login com Credentials: usuário e senha, gerenciamento de sessão e integração com banco de dados. Depois que você entende esses pontos centrais, o NextAuth.js deixa de parecer tão complicado.
Entendendo os principais conceitos do NextAuth.js
O que o NextAuth.js realmente faz?
Em uma frase: NextAuth.js é um “middleware de autenticação” que gerencia “quem está conectado” e “como o estado do login é armazenado”. Ele não impõe um banco de dados nem uma interface específica; sua função é verificar a identidade do usuário e manter o estado da sessão.
Qual é a diferença em relação a Clerk e Supabase Auth? Em resumo:
- Clerk: oferece uma interface de login bonita e um painel de gerenciamento de usuários. Você configura tudo em 30 minutos, mas paga ao ultrapassar 10.000 usuários ativos mensais.
- Supabase Auth: se você já usa o banco de dados do Supabase, o recurso de autenticação praticamente vem de graça e a integração é muito fluida.
- NextAuth.js: é totalmente gratuito e de código aberto, mas você precisa criar a interface de login, o cadastro de usuários e a lógica de banco de dados.
A tendência de 2025 é interessante: o NextAuth.js continua muito usado, mas soluções prontas como o Clerk estão conquistando o mercado rapidamente. Faz sentido — em vez de gastar dias escrevendo código de autenticação, muita gente prefere investir esse tempo no recurso principal do produto. Ainda assim, para projetos pessoais ou quando você precisa de controle total, vale a pena aprender NextAuth.js.
Três conceitos que você precisa entender
1. Provider (provedor): como o usuário faz login?
É o método de login. O NextAuth.js oferece mais de 50 opções; as mais comuns são:
- Provedores OAuth: Google, GitHub, Facebook… o usuário clica e entra, sem que você precise gerenciar a senha.
- Provedor Credentials: usuário e senha, o método mais tradicional e o foco deste artigo.
Há uma ressalva importante: o provedor Credentials é o mais flexível, mas também exige mais código de sua parte. A própria documentação oficial não o recomenda, porque toda a responsabilidade de segurança fica com você — como armazenar senhas, impedir ataques de força bruta e gerenciar sessões.
2. Session (sessão): como lembrar o usuário depois do login?
Depois de entrar uma vez, o usuário não deveria digitar a senha a cada requisição. Session é o mecanismo que “lembra o estado do login”. Há duas formas:
- JWT Session: os dados de login são criptografados e colocados em um cookie; o servidor não precisa armazenar nada.
- Database Session: o cookie contém apenas um ID; os dados reais do login ficam no banco de dados.
Escolher entre as duas é uma das maiores dúvidas de quem está começando com NextAuth.js. Veremos os detalhes na próxima seção.
3. Adapter (adaptador): onde os dados do usuário ficam armazenados?
Se você quer armazenar dados do usuário no banco, como email e data de cadastro, precisa de um Adapter. O NextAuth.js oferece suporte a Prisma, MongoDB, MySQL e vários outros bancos.
Mas existe um ponto essencial: o provedor Credentials não salva automaticamente os dados do usuário no banco. A documentação oficial deixa claro que, ao usar Credentials, você precisa gerenciar as contas por conta própria. O NextAuth.js apenas valida o login; ele não faz cadastro nem armazenamento.
JWT vs. Session: qual escolher?
Essa é a questão central. Na época, li mais de dez comparações e continuei indeciso, até compreender a diferença fundamental entre as duas estratégias.
JWT Session: o modelo do passaporte
Imagine uma viagem internacional: o passaporte contém sua foto, seu nome e a validade. A cada entrada no país, a imigração consulta o documento sem precisar buscar seus dados em outro sistema. O JWT funciona assim — depois do login, o servidor gera um token criptografado, como um passaporte, com informações como userId e email, e o armazena em um cookie no navegador.
Vantagens:
- É rápido. Não há consulta ao banco; basta descriptografar o token para identificar o usuário.
- É econômico. Não exige um banco para armazenar sessões, o que é especialmente útil em implantações serverless.
- É escalável. Mesmo com muitos usuários, não existe uma tabela de sessões crescendo sem parar.
Desvantagens:
- Não permite forçar o logout de um usuário. Descobriu que uma conta foi invadida e quer invalidar aquele login? Enquanto o token não expirar, não há como revogá-lo — a menos que você mantenha uma lista de bloqueio, o que volta a exigir um banco de dados.
- Não permite limitar o número de dispositivos conectados. Quer estabelecer “no máximo três dispositivos ao mesmo tempo”? Não é possível.
- As informações não podem ser atualizadas antes de o token expirar. Se você armazenou a função do usuário no token e ela mudou, o usuário continuará vendo a função antiga até a expiração.
Database Session: o modelo do cartão de hotel
Um hotel entrega um cartão que contém apenas o número do quarto; seus dados completos, como documento e despesas, ficam no sistema do hotel. A cada uso do cartão, o sistema consulta o quarto e verifica sua permissão. Database Session funciona da mesma forma — o cookie guarda apenas um ID de sessão, enquanto os dados reais do usuário ficam no banco.
Vantagens:
- Permite revogar um login a qualquer momento. O usuário escolheu “sair de todos os dispositivos”? Basta apagar os registros de sessão no banco.
- Permite limitar o número de dispositivos conectados.
- Permite atualizar os dados do usuário em tempo real; se uma permissão mudar, a alteração vale já na próxima requisição.
Desvantagens:
- É mais lento. Cada requisição precisa consultar o banco.
- Exige o gerenciamento da tabela de sessões, incluindo criação e limpeza de sessões expiradas.
- Com muitos usuários, a pressão sobre o banco de dados aumenta.
Árvore de decisão (a parte importante)
Você provavelmente quer saber: qual devo usar? Minha sugestão:
Sua aplicação precisa forçar o usuário a entrar novamente?
(Por exemplo, após mudar a senha ou bloquear a conta.)
├─ Sim → Use Database Session
└─ Não → Continue para a próxima pergunta
Você quer dispensar o banco de dados ou fazer uma implantação serverless?
├─ Sim → Use JWT
└─ Não → Continue para a próxima pergunta
Sua aplicação é um projeto pessoal ou MVP que precisa ir ao ar rapidamente?
├─ Sim → Use JWT (simples e prático)
└─ Não → Use Database Session (mais adequado para aplicações empresariais)
No meu próprio projeto, comecei com JWT. Mais tarde, criei um painel de gerenciamento de usuários e precisei encerrar sessões remotamente, então migrei para Database Session. O custo da mudança foi considerável; vale pensar nisso desde o início.
Caso especial: Credentials + Database Session
Se você usa o provedor Credentials e também quer Database Session, encontra um grande obstáculo: a documentação oficial diz que essa combinação não é compatível.
Provedores OAuth, como Google e GitHub, funcionam perfeitamente com Database Session, mas Credentials não. O motivo é que o NextAuth.js considera Credentials flexível demais para criar registros de sessão automaticamente.
Existem soluções, mas elas exigem código manual para criar a sessão no callback signIn. Há várias discussões no GitHub, como esta issue, com implementações que você pode consultar. Sinceramente, se você está começando, recomendo usar JWT ou trocar para um provedor OAuth em vez de aumentar a complexidade.
Configuração completa do provedor Credentials
Chega de teoria; vamos ao código. Vou mostrar três versões, da mais simples à completa, para você escolher conforme a etapa do seu projeto.
Configuração básica: a menor versão funcional
Primeiro, instale a dependência:
npm install next-auth
Depois, crie o arquivo. No Next.js 13+ com App Router, o caminho é app/api/auth/[...nextauth]/route.ts. Se você ainda usa Pages Router, o caminho é pages/api/auth/[...nextauth].js. Aqui usarei App Router.
app/api/auth/[…nextauth]/route.ts:
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
const handler = NextAuth({
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
email: { label: "邮箱", type: "email" },
password: { label: "密码", type: "password" }
},
async authorize(credentials) {
// 这里先hardcode一个用户,方便测试
if (credentials?.email === "[email protected]" &&
credentials?.password === "123456") {
return {
id: "1",
name: "测试用户",
email: "[email protected]"
}
}
return null // 登录失败
}
})
],
session: {
strategy: "jwt" // 使用JWT session
},
pages: {
signIn: '/login' // 自定义登录页面(可选)
}
})
export { handler as GET, handler as POST }
Variáveis de ambiente em .env.local:
NEXTAUTH_SECRET=your-super-secret-key-change-this
NEXTAUTH_URL=http://localhost:3000
Pontos importantes:
NEXTAUTH_SECRET: usado para criptografar o token. É obrigatório em produção e também recomendado no desenvolvimento local. Para gerar:openssl rand -base64 32.- Função
authorize: é o núcleo da validação da identidade. Retorne o objeto do usuário em caso de sucesso ounullem caso de falha.
Essa versão funciona, mas os dados do usuário estão fixos no código e não servem para uma aplicação real. Agora vamos conectar o banco de dados.
Detalhes das principais opções de configuração
Antes do exemplo completo, vale explicar as opções que mais causam confusão.
1. session.strategy: "jwt" ou "database"?
Como vimos, o padrão é "jwt". Se você usa um Adapter para conectar o banco, a estratégia muda automaticamente para "database". Porém, ao combinar o provedor Credentials com JWT, é melhor definir explicitamente strategy: "jwt"; caso contrário, pode ocorrer um erro.
2. callbacks: como adicionar campos personalizados à session?
Por padrão, useSession retorna apenas name, email e image nos dados do usuário. E se você quiser adicionar userId ou role?
Use callbacks:
callbacks: {
async jwt({ token, user }) {
// user 只在登录时有值
if (user) {
token.userId = user.id // 把userId加到token里
}
return token
},
async session({ session, token }) {
// 把token里的userId放到session里
session.user.userId = token.userId
return session
}
}
Assim, quando o frontend chamar const { data: session } = useSession(), session.user.userId terá um valor.
3. pages: página de login personalizada
O NextAuth.js inclui uma página de login pouco atraente em /api/auth/signin. Para usar sua própria interface, defina pages: { signIn: '/login' }.
Sua página de login deve chamar:
import { signIn } from "next-auth/react"
const handleSubmit = async (e) => {
e.preventDefault()
const result = await signIn('credentials', {
redirect: false,
email,
password
})
if (result?.error) {
// 登录失败
} else {
// 登录成功,跳转
}
}
Exemplo completo: cadastro, login e gerenciamento de sessão
Agora veremos uma versão adequada para uso real. Vamos supor que você use Prisma + PostgreSQL.
1. Crie primeiro a tabela de usuários
prisma/schema.prisma:
model User {
id String @id @default(cuid())
email String @unique
password String
name String?
createdAt DateTime @default(now())
}
Execute npx prisma migrate dev para gerar a tabela.
2. Endpoint de cadastro
app/api/register/route.ts:
import { NextResponse } from "next/server"
import bcrypt from "bcryptjs"
import { prisma } from "@/lib/prisma" // 假设你有个prisma client
export async function POST(req: Request) {
try {
const { email, password, name } = await req.json()
// 检查用户是否已存在
const existingUser = await prisma.user.findUnique({
where: { email }
})
if (existingUser) {
return NextResponse.json(
{ error: "邮箱已被注册" },
{ status: 400 }
)
}
// 密码加密(重点!)
const hashedPassword = await bcrypt.hash(password, 10)
// 创建用户
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
name
}
})
return NextResponse.json({
user: {
id: user.id,
email: user.email,
name: user.name
}
})
} catch (error) {
return NextResponse.json(
{ error: "注册失败" },
{ status: 500 }
)
}
}
Importante: a senha precisa ser armazenada com hash. Use bcrypt ou argon2; nunca salve a senha em texto simples no banco.
3. Configuração do NextAuth conectada ao banco de dados
app/api/auth/[...nextauth]/route.ts:
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import bcrypt from "bcryptjs"
import { prisma } from "@/lib/prisma"
const handler = NextAuth({
providers: [
CredentialsProvider({
credentials: {
email: { label: "邮箱", type: "email" },
password: { label: "密码", type: "password" }
},
async authorize(credentials) {
if (!credentials?.email || !credentials?.password) {
return null
}
// 从数据库查用户
const user = await prisma.user.findUnique({
where: { email: credentials.email }
})
if (!user) {
return null // 用户不存在
}
// 验证密码
const isValid = await bcrypt.compare(
credentials.password,
user.password
)
if (!isValid) {
return null // 密码错误
}
// 返回用户信息(不要包含密码!)
return {
id: user.id,
email: user.email,
name: user.name
}
}
})
],
session: {
strategy: "jwt",
maxAge: 30 * 24 * 60 * 60 // 30天
},
callbacks: {
async jwt({ token, user }) {
if (user) {
token.userId = user.id
}
return token
},
async session({ session, token }) {
session.user.userId = token.userId as string
return session
}
},
pages: {
signIn: '/login'
}
})
export { handler as GET, handler as POST }
4. Use a session no frontend
Em um componente de servidor (Server Component):
import { getServerSession } from "next-auth"
export default async function ProfilePage() {
const session = await getServerSession()
if (!session) {
redirect('/login')
}
return <div>欢迎, {session.user.name}</div>
}
Em um componente de cliente (Client Component):
'use client'
import { useSession } from "next-auth/react"
export default function Dashboard() {
const { data: session, status } = useSession()
if (status === "loading") {
return <div>加载中...</div>
}
if (!session) {
return <div>请先登录</div>
}
return <div>你的用户ID: {session.user.userId}</div>
}
Observação:
- No servidor, use
getServerSession(). - No cliente, use
useSession(). - O componente de cliente deve estar envolvido por
<SessionProvider>, geralmente adicionado ao layout.
Estratégias de gerenciamento de sessão e problemas comuns
Como usar uma sessão JWT corretamente
Se você escolheu JWT, precisa aproveitar bem a estratégia. Veja os pontos principais.
1. Armazene informações extras no JWT, como userId e role
Já mostramos isso no exemplo de callbacks, mas vale reforçar: o callback jwt adiciona dados ao token; o callback session transfere esses dados do token para a session.
Em um projeto real, talvez você também precise armazenar a função do usuário:
callbacks: {
async jwt({ token, user }) {
if (user) {
token.userId = user.id
token.role = user.role // 假设数据库有role字段
}
return token
},
async session({ session, token }) {
session.user.userId = token.userId as string
session.user.role = token.role as string
return session
}
}
2. Defina o tempo de expiração do token
O padrão é 30 dias, mas você pode alterar:
session: {
strategy: "jwt",
maxAge: 7 * 24 * 60 * 60 // 7天
}
Há um detalhe: se o usuário fechar e abrir o navegador, o token continuará lá, a menos que ele faça logout manualmente. Se você quer encerrar a sessão ao fechar o navegador, precisa tratar isso no frontend; o JWT no backend não consegue fazer isso sozinho.
3. A maior limitação do JWT: não é possível revogá-lo ativamente
Essa é a parte mais incômoda do JWT. Imagine que você descubra que a conta de um usuário foi invadida e queira desconectá-lo imediatamente. Não é possível: enquanto o token não expirar, quem estiver com ele continuará tendo acesso.
Alternativas:
- Defina uma expiração mais curta, como uma hora, trocando parte da experiência do usuário por mais segurança.
- Mantenha uma lista de tokens bloqueados, mas isso exige um banco de dados e elimina parte da vantagem do JWT.
- Use Database Session para resolver a questão de vez.
Implementando Database Session com o provedor Credentials
Se você escolheu Database Session desde o início, a configuração é mais simples — desde que use um provedor OAuth, como Google ou GitHub.
Instale um Adapter:
npm install @next-auth/prisma-adapter
Configure:
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { prisma } from "@/lib/prisma"
const handler = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!
})
]
// strategy会自动变成"database",不用手动设
})
O banco criará automaticamente as tabelas User, Session, Account e outras.
Porém, se você usa o provedor Credentials, a situação fica mais complicada. A documentação oficial afirma: o Credentials provider não oferece suporte a database session.
Há várias soluções na internet. Em geral, a ideia é criar manualmente o registro de sessão no callback signIn. Não recomendo isso para iniciantes, pois é fácil cometer erros. Se você realmente precisa combinar Credentials + Database Session, consulte estas discussões:
Outra opção é usar Clerk ou Supabase Auth, que oferecem suporte nativo a essa combinação.
Os cinco erros mais comuns
Eu cometi todos estes erros; esta lista pode poupar bastante tempo:
1. Esquecer NEXTAUTH_SECRET e receber um erro em produção
No desenvolvimento local, é possível deixar NEXTAUTH_SECRET sem valor; o NextAuth.js mostra um aviso, mas funciona. Porém, em plataformas como Vercel e Railway, a ausência dessa variável de ambiente provoca diretamente um erro 500.
Gere o valor com openssl rand -base64 32 e adicione-o às variáveis de ambiente da plataforma de implantação.
2. O provedor Credentials não funciona com database session por padrão
Vale repetir: se você configurar um Adapter e também usar Credentials, ocorrerá um erro. Defina explicitamente session: { strategy: "jwt" } ou implemente manualmente a criação da sessão.
3. useSession não funciona em componentes de servidor
No Next.js 13+ com App Router, os componentes são Server Components por padrão. Se você escrever const session = useSession() em um componente de servidor, ocorrerá um erro, porque hooks só podem ser usados no cliente.
No servidor, use getServerSession():
import { getServerSession } from "next-auth"
const session = await getServerSession()
No cliente, adicione a diretiva 'use client' e use useSession().
4. Problemas de cookie entre domínios
No desenvolvimento você usa localhost:3000; em produção, example.com. Como o domínio do cookie é diferente, o estado do login pode se perder.
Solução: confirme que a variável de ambiente NEXTAUTH_URL aponta para o domínio correto em produção. Não deixe localhost fixo no código.
5. Erro JWEDecryptionFailed
Mensagem: JWEDecryptionFailed: decryption operation failed
Causa: você alterou NEXTAUTH_SECRET, mas o navegador ainda guarda o token anterior. O novo secret não consegue descriptografar esse token, então o erro ocorre.
Solução: limpe os cookies do navegador ou faça login novamente.
Extra: proteja rotas com Middleware
Se você quer exigir login em determinadas páginas, pode usar Middleware:
middleware.ts:
export { default } from "next-auth/middleware"
export const config = {
matcher: ["/dashboard/:path*", "/profile/:path*"]
}
Assim, todas as páginas em /dashboard e /profile verificam a sessão e redirecionam automaticamente para a página de login quando necessário.
Recomendações para projetos reais e próximos passos
Qual solução devo escolher?
Depois de tanta informação, vamos resumir a decisão.
Cenário 1: projeto pessoal, MVP ou blog
- Recomendação: NextAuth.js + JWT + Credentials
- Motivo: é gratuito, simples de configurar e dispensa uma tabela de sessões.
- Desvantagem: se você precisar mais tarde de recursos como “desconectar um usuário”, a migração terá um custo alto.
Cenário 2: aplicação empresarial ou SaaS com orçamento
- Recomendação: Clerk
- Motivo: fica pronto em 30 minutos, oferece uma interface bonita e recursos completos de gerenciamento de usuários, economizando de 40 a 80 horas de desenvolvimento.
- Desvantagem: é pago acima de 10.000 usuários ativos mensais e limita a personalização.
- Complemento: se você usa o banco de dados do Supabase, Supabase Auth também é uma ótima opção, com cota gratuita de 50.000 MAU.
Cenário 3: aplicação empresarial sem orçamento ou que exige controle total
- Recomendação: NextAuth.js + Database Session + provedor OAuth, como Google ou GitHub.
- Motivo: é gratuito, completo e permite encerrar sessões remotamente.
- Desvantagem: você precisa criar a interface de login e administrar o banco de dados.
Cenário 4: sistema de usuários existente que precisa apenas de uma camada de autenticação
- Recomendação: NextAuth.js + Credentials + JWT
- Motivo: é flexível e não interfere na estrutura atual do banco.
- Atenção: você precisa implementar as medidas de segurança, como hash de senha e proteção contra força bruta.
Minha experiência: no primeiro projeto, usei JWT. Seis meses depois, os requisitos mudaram, foi necessário adicionar gerenciamento de usuários e passei dois dias migrando para Database Session. No segundo, avaliei a necessidade desde o início e escolhi Database Session, economizando bastante trabalho.
Roteiro de aprendizado avançado
Depois de fazer o login com Credentials funcionar, você pode aprender:
1. Provedores OAuth, que são mais simples e devem ser uma prioridade
- O login com Google ou GitHub é bem mais simples que Credentials.
- Você não precisa cuidar do hash de senha nem do cadastro; o provedor OAuth faz isso.
- A experiência também é melhor, com login em um clique.
2. Middleware para proteger rotas
- Como mostramos antes, uma linha de código pode proteger um diretório inteiro.
- É muito mais prático do que verificar a sessão individualmente em cada página.
3. Gerenciamento de permissões com várias funções (RBAC)
- Armazene o campo
rolena session. - Exiba conteúdos e conceda permissões conforme a função.
- Como etapa avançada, conheça a biblioteca CASL para controle de permissões granular.
4. Verificação de email e redefinição de senha
- Use o Email Provider do NextAuth.js para enviar links de login por email.
- Implemente o fluxo de esqueci minha senha, enviando um link de redefinição.
Recursos de referência
Documentação oficial (leitura essencial):
- Opções de configuração do NextAuth.js — veja todas as opções disponíveis.
- Documentação do Credentials Provider — detalhes sobre Credentials.
- Session Strategies — comparação oficial entre JWT e Database Session.
Tutoriais úteis:
- Tutorial Learn Next.js em chinês — adicionar autenticação — tutorial em chinês indicado para iniciantes.
- Tutorial de NextAuth.js JWT Session para iniciantes — tutorial detalhado com foco em JWT.
Discussões no GitHub para consultar ao encontrar problemas:
- Database session + Credentials login — solução para combinar Credentials e Database Session.
- FAQ do NextAuth.js — perguntas frequentes oficiais.
Comparações com concorrentes para ajudar na escolha:
- Comparação entre NextAuth, Clerk e Supabase em 2025 — comparação detalhada das três soluções.
Conclusão
Depois de tudo isso, o NextAuth.js se resume a três decisões:
- Qual método de login usar? Credentials ou OAuth? Na maioria dos casos, OAuth, como Google ou GitHub, é mais simples.
- Como armazenar a sessão? JWT ou Database? Use JWT em projetos pessoais e Database em aplicações empresariais.
- Como validar o usuário? Com Credentials, você escreve a lógica; com OAuth, o provedor faz a validação.
Minha sugestão: faça primeiro o menor exemplo funcional deste artigo. Depois que o login estiver funcionando, adicione os recursos aos poucos. Não tente dominar todas as configurações logo no começo; isso só torna o processo desanimador.
O NextAuth.js realmente tem uma curva de aprendizado, mas, depois de dominá-lo, você controla todo o fluxo de autenticação. Se quiser rapidez, Clerk é uma boa escolha; se quiser economizar e aprender, vale investir tempo no NextAuth.js.
Por fim, conte nos comentários qual problema você encontrou. Em que etapa da configuração você travou? Ainda está em dúvida entre JWT e Session?
Leitura recomendada:
-
O próximo artigo está planejado como um “Guia completo de Next.js Middleware”, com proteção de rotas, testes A/B e outros cenários.
-
Se você se interessa por gerenciamento de permissões de usuários, leia meu artigo anterior sobre “práticas de design de permissões RBAC”.
Fluxo completo de configuração de login com Credentials no NextAuth.js
Todas as etapas, da instalação à implementação de login com usuário e senha e ao gerenciamento de sessão
⏱️ Estimated time: 2 hr
- 1
Step 1: Instale e inicialize 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)
• Defina NEXTAUTH_SECRET (gere uma string aleatória)
• Configure o array providers - 2
Step 2: Configure o Credentials Provider
Implemente a lógica de validação:
1. Valide o usuário na função authorize do CredentialsProvider
2. Busque o usuário no banco de dados (ou use dados fixos para teste)
3. Verifique a senha (com bcrypt ou outra biblioteca)
4. Retorne o objeto do usuário (com id, name, email etc.)
Atenção:
• A função authorize deve retornar um objeto de usuário ou null
• O objeto retornado será armazenado na session
• A verificação da senha deve ocorrer no servidor - 3
Step 3: Escolha a estratégia de sessão (JWT ou Session)
Estratégia JWT (padrão):
• Indicada para aplicações sem estado
• Os dados da sessão ficam armazenados no token JWT
• Não exige banco de dados
• Configuração: session: { strategy: 'jwt' }
Estratégia Session (exige banco de dados):
• Indicada para aplicações que precisam revogar logins
• Os dados da sessão ficam armazenados no banco de dados
• Exige um Adapter, como Prisma ou MongoDB
• Configuração: session: { strategy: 'database' } - 4
Step 4: Configure Callbacks para personalizar o fluxo
Callbacks comuns:
• signIn: controla se o login será permitido
• jwt: personaliza o conteúdo do token JWT (estratégia JWT)
• session: personaliza o conteúdo da session
Exemplo:
callbacks: {
async jwt({ token, user }) {
if (user) token.role = user.role
return token
},
async session({ session, token }) {
session.user.role = token.role
return session
}
} - 5
Step 5: Crie a página e os componentes de login
Use a API do NextAuth.js:
• signIn('credentials', { username, password }): inicia o login
• signOut(): encerra a sessão
• useSession(): obtém a sessão atual
• SessionProvider: envolve a aplicação e fornece o contexto da sessão
Exemplo:
const { data: session } = useSession()
if (session) {
return <div>Usuário conectado: {session.user.name}</div>
} - 6
Step 6: Teste e depure
Pontos de teste:
• Verifique se usuário e senha corretos permitem o login
• Verifique se credenciais incorretas são recusadas
• Verifique se a sessão persiste
• Verifique se o logout remove a sessão
Como depurar:
• Consulte os erros no console do navegador
• Confira os logs do servidor
• Ative o modo de depuração do NextAuth.js
• Verifique se as variáveis de ambiente estão definidas corretamente
FAQ
Qual é a diferença entre NextAuth.js, Clerk e Supabase Auth?
• Solução auto-hospedada, gratuita e de código aberto
• Exige que você implemente a interface de login e o gerenciamento de usuários
• Oferece controle total
Clerk:
• Oferece interface completa e painel de gerenciamento
• Passa a ser pago acima de 10.000 usuários ativos mensais
Supabase Auth:
• Indicado para projetos que usam o banco de dados do Supabase
• A integração é simples, mas fica vinculada ao banco
Devo escolher JWT ou Session?
O login com Credentials é seguro?
1) Armazene as senhas com hash, usando bcrypt ou outra biblioteca
2) Execute a lógica de validação no servidor
3) Use HTTPS na transmissão
4) Defina requisitos de senha forte
5) Considere adicionar CAPTCHA para evitar ataques de força bruta
Como personalizar a página de login?
Depois, crie a página de login personalizada e chame signIn('credentials', { username, password }) para iniciar o login.
Também é possível personalizar toda a interface e usar apenas a API do NextAuth.js.
Como obter o usuário conectado no momento?
const { data: session } = useSession()
No servidor, use getServerSession():
const session = await getServerSession(authOptions)
O objeto session contém os dados de user, como id, name e email.
Como implementar controle de funções e permissões?
Quais bancos de dados são compatíveis com NextAuth.js?
19 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
Otimização de desempenho em React Server Components: dados e cache na prática
Guia prático de otimização de desempenho em React Server Components: do problema de waterfall à arquitetura em streaming, com estratégias de busca de dados e cache. Mostra o caminho para reduzir TTFB de 450ms para 45ms, com comparação de 4 abordagens e guia de 5 APIs de cache
Parte 47 de 51
Próximo
JWT ou Session? Um guia prático para escolher sem complicação
Não sabe se deve usar JWT ou Session? Este guia compara as duas estratégias na prática, com configuração do NextAuth.js, desempenho e segurança para ajudar você a decidir.
Parte 49 de 51



Comentários
Entre com GitHub para comentar