Based on the authoritative Auth.js v5 documentation, here's how to implement magic link email authentication:
Implementation Steps
1. Install Auth.js and a database adapter:
npm install next-auth @auth/prisma-adapter
2. Configure your auth.ts file with an email provider and database adapter:
import NextAuth from "next-auth"
import Resend from "next-auth/providers/resend"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
Resend({
apiKey: process.env.AUTH_RESEND_KEY,
from: "[email protected]"
})
]
})
3. For custom HTTP email providers:
import NextAuth from "next-auth"
import { sendVerificationRequest } from "./lib/authSendRequest"
export const { handlers, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
{
id: "email",
type: "email",
maxAge: 60 * 60 * 24, // Link expires in 24 hours
sendVerificationRequest,
}
]
})
4. Implement sendVerificationRequest (for custom providers):
export async function sendVerificationRequest({ identifier: email, url }) {
await fetch("https://api.sendgrid.com/v3/mail/send", {
body: JSON.stringify({
personalizations: [{ to: [{ email }] }],
from: { email: "[email protected]" },
subject: "Sign in to Your App",
content: [{
type: "text/plain",
value: `Click here to sign in: ${url}`
}]
}),
headers: {
Authorization: `Bearer ${process.env.SENDGRID_API}`,
"Content-Type": "application/json"
},
method: "POST"
})
}
Critical requirement: A database adapter is mandatory for email providers—Auth.js cannot send magic links without a database to store verification tokens.
Sources: