Uitleg — Wat is NextAuth?
NextAuth (ook wel Auth.js genoemd) is de standaard authenticatiebibliotheek voor Next.js. Het regelt inloggen, sessies en beveiliging voor je.
Wat NextAuth voor je doet:
- Inloggen met email + wachtwoord (Credentials)
- Sessie bijhouden via een JWT cookie
- Ingebouwde beveiliging (CSRF, token rotatie)
- Makkelijk uitbreidbaar met Google, GitHub, etc.
💡 Overzicht van de flow
- Gebruiker vult email + wachtwoord in
- NextAuth controleert de gegevens via jouw
authorizefunctie - Bij succes: NextAuth slaat een sessie op in een cookie
- Op beveiligde pagina's check je of die sessie bestaat
Stap 1 — Installeer NextAuth en bcrypt
Stop de dev server (Ctrl+C), voer dan uit:
npm install next-auth@beta bcryptjs
💡 Wat is bcrypt?
Wachtwoorden sla je nooit als platte tekst op. bcrypt zet een wachtwoord om in een onleesbare hash. Bij het inloggen vergelijk je de hash — nooit het echte wachtwoord.
Stap 2 — Maak het User model aan
Maak een nieuw bestand models/User.js aan:
models/
└── User.js ← nieuw bestand
// models/User.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
);
const User = mongoose.models.User || mongoose.model('User', userSchema);
export default User;
Let op: wachtwoord nooit terugsturen
Stuur het password veld nooit mee terug in een API response. Je haalt het op uit de database om te vergelijken, maar daarna gebruik je het niet meer.
Stap 3 — Maak auth.js aan
Maak een nieuw bestand auth.js aan in de root van je project (naast package.json):
workout-tracker/
├── app/
├── auth.js ← nieuw bestand (in de root!)
├── lib/
└── models/
// auth.js
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';
import connectDB from './lib/mongodb';
import User from './models/User';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
CredentialsProvider({
name: 'credentials',
credentials: {
email: { label: 'Email', type: 'email' },
password: { label: 'Wachtwoord', type: 'password' },
},
async authorize(credentials) {
if (!credentials?.email || !credentials?.password) {
return null;
}
await connectDB();
const user = await User.findOne({ email: credentials.email });
if (!user) return null;
const isValid = await bcrypt.compare(credentials.password, user.password);
if (!isValid) return null;
// Dit object wordt in de sessie/token opgeslagen
return {
id: user._id.toString(),
email: user.email,
name: user.name,
};
},
}),
],
session: {
strategy: 'jwt', // Sessie opslaan in een cookie als JWT
},
pages: {
signIn: '/login', // Jouw eigen loginpagina
},
});
authorize— wordt aangeroepen als iemand inlogt. Geeftnullterug bij foute gegevens, anders het user-object.session: jwt— de sessie wordt opgeslagen in een cookie, geen extra database nodig.pages.signIn— NextAuth stuurt niet-ingelogde gebruikers naar/login.
Stap 4 — Maak de NextAuth API route aan
Maak een nieuw bestand app/api/auth/[...nextauth]/route.js aan:
app/api/auth/[...nextauth]/route.js ← nieuw bestand
// app/api/auth/[...nextauth]/route.js
import { handlers } from '../../../../auth';
export const { GET, POST } = handlers;
💡 Wat doet deze route?
NextAuth gebruikt intern meerdere endpoints: /api/auth/signin, /api/auth/signout, /api/auth/session, etc. De [...nextauth] map vangt ze allemaal op.
Stap 5 — Voeg AUTH_SECRET toe aan .env.local
Voeg handmatig een veilige secret toe aan je .env.local:
# .env.local
MONGO_URI=mongodb+srv://...
AUTH_SECRET=eenLangeWillekeurigeStringVanMinimaal32Tekens
💡 Tip: genereer een willekeurige string
Je kunt zelf een willekeurige string verzinnen, of gebruik dit commando in de terminal om er een te genereren:
openssl rand -base64 32
Plak de uitvoer als waarde voor AUTH_SECRET.
💡 Auth.js v5 en omgevingsvariabelen
NextAuth v5 herkent AUTH_SECRET automatisch. Je hoeft dit niet expliciet in auth.js te vermelden.
Stap 6 — Maak de AuthProvider aan en voeg toe aan layout
Maak een nieuw bestand app/components/AuthProvider.js aan:
app/components/
└── AuthProvider.js ← nieuw bestand
// app/components/AuthProvider.js
'use client';
import { SessionProvider } from 'next-auth/react';
export default function AuthProvider({ children }) {
return <SessionProvider>{children}</SessionProvider>;
}
Pas daarna app/layout.js aan: voeg AuthProvider toe als wrapper om je bestaande inhoud. Verwijder niets — zet alles wat je al hebt erin:
// app/layout.js
import './globals.css';
import Link from 'next/link';
import AuthProvider from './components/AuthProvider';
export const metadata = {
title: 'Workout Tracker',
description: 'Bijhouden van je workouts',
};
export default function RootLayout({ children }) {
return (
<html lang="nl">
<body>
<AuthProvider>
<nav>
<Link href="/">Home</Link>
<Link href="/workouts">Workouts</Link>
</nav>
<main>{children}</main>
</AuthProvider>
</body>
</html>
);
}
💡 Waarom een aparte wrapper?
SessionProvider is een Client Component. layout.js is standaard een Server Component. Je kunt een Client Component niet direct in een Server Component importeren als het de root is — vandaar de wrapper.
💡 Nav vervangen later
Bij Protected Routes vervang je de <nav> door een <Navbar /> component die automatisch de juiste links toont op basis van of iemand ingelogd is.
Checklist
✅ Check of je hebt:
npm install next-auth@5 bcryptuitgevoerdmodels/User.jsaangemaaktauth.jsaangemaakt in de rootapp/api/auth/[...nextauth]/route.jsaangemaaktAUTH_SECRETin.env.localgezetAuthProvidercomponent aangemaakt en inlayout.jsgezet
Volgende Stap
Auth is geconfigureerd! Nu maken we de registratie- en loginpagina's.
Maak de registratie- en loginformulieren