0

Autenticação Completa no Next.js com NextAuth.js e Middleware

O erro que abre a porta: rotas desprotegidas no App Router

A configuração padrão do NextAuth.js protege exatamente zero rotas. Você instala, configura o provider, faz login funcionar na tela e assume que o resto está seguro. Não está. Qualquer rota server-side ou API route continua acessível sem sessão até que você adicione verificação explícita em cada handler ou configure o middleware corretamente.

Esse post monta uma autenticação completa: configuração do NextAuth.js v5 (Auth.js) no App Router, provider OAuth (GitHub) e credentials, sessão JWT, middleware que protege rotas na edge e callbacks que controlam o que vai no token. O resultado é uma base que você copia, adapta o provider e tem proteção real.

Estrutura do projeto e dependências

Antes de qualquer código, instale o necessário:

npm install next-auth@beta @auth/prisma-adapter @prisma/client prisma bcryptjs
npm install -D @types/bcryptjs

A versão next-auth@beta é o Auth.js v5, que suporta App Router nativamente. Se você ainda usa Pages Router, a API é diferente. Este post assume App Router com Next.js 14+.

A estrutura de arquivos que vamos construir:

src/
├── auth.ts                    # Configuração central do NextAuth
├── middleware.ts               # Proteção de rotas na edge
├── app/
│   ├── api/auth/[...nextauth]/route.ts
│   ├── (protected)/
│   │   └── dashboard/page.tsx
│   ├── login/page.tsx
│   └── layout.tsx
├── lib/
│   └── db.ts                  # Instância do Prisma
└── components/
    └── session-provider.tsx

Configuração central do NextAuth.js v5

O arquivo auth.ts na raiz do src é o ponto central. Tudo parte daqui:

// src/auth.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { PrismaAdapter } from "@auth/prisma-adapter";
import bcrypt from "bcryptjs";
import { db } from "@/lib/db";

export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: PrismaAdapter(db),
  // JWT porque o middleware roda na edge e não tem acesso ao banco
  session: { strategy: "jwt" },
  pages: {
    signIn: "/login",
    error: "/login",
  },
  providers: [
    GitHub({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
    Credentials({
      name: "credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Senha", type: "password" },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) return null;

        const user = await db.user.findUnique({
          where: { email: credentials.email as string },
        });

        if (!user || !user.hashedPassword) return null;

        const passwordMatch = await bcrypt.compare(
          credentials.password as string,
          user.hashedPassword
        );

        if (!passwordMatch) return null;

        // Retorne apenas o que o NextAuth precisa para montar o token
        return {
          id: user.id,
          email: user.email,
          name: user.name,
          role: user.role,
        };
      },
    }),
  ],
  callbacks: {
    // Injeta dados customizados no JWT
    async jwt({ token, user }) {
      if (user) {
        token.role = user.role;
        token.id = user.id;
      }
      return token;
    },
    // Expõe dados do JWT na sessão do client
    async session({ session, token }) {
      if (session.user) {
        session.user.role = token.role as string;
        session.user.id = token.id as string;
      }
      return session;
    },
    // Controla redirecionamento pós-login
    async authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");

      if (isOnDashboard && !isLoggedIn) {
        return Response.redirect(new URL("/login", nextUrl));
      }

      return true;
    },
  },

---

Leia o artigo completo em [https://www.vivodecodigo.com.br/nextjs/nextjs-autenticacao-nextauth-middleware-app-router](https://www.vivodecodigo.com.br/nextjs/nextjs-autenticacao-nextauth-middleware-app-router)
Carregando publicação patrocinada...