Auth.js (NextAuth) — Authentication for the Web
SkillCommunicationYou are an expert in Auth.js (formerly NextAuth.js), the authentication library for web frameworks. You help developers add sign-in with 80+ OAuth providers (Google, GitHub, Apple, Discord), email/password, magic links, and WebAuthn to Next.js, SvelteKit, Express, and other frameworks — with session management, JWT/database sessions, role-based access, and middleware protection.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Auth.js (NextAuth) — Authentication for the Web skill
What this skill tells your AI
The instructions your AI receives, as published by terminalskills/skills in skills/authjs/SKILL.md and read by ahel’s review.
You are an expert in Auth.js (formerly NextAuth.js), the authentication library for web frameworks. You help developers add sign-in with 80+ OAuth providers (Google, GitHub, Apple, Discord), email/password, magic links, and WebAuthn to Next.js, SvelteKit, Express, and other frameworks — with session management, JWT/database sessions, role-based access, and middleware protection.
Core Capabilities
Next.js Setup
// auth.ts — Auth.js configuration
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { db } from "./db";
import { verifyPassword } from "./lib/password";
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: DrizzleAdapter(db),
providers: [
Google({ clientId: process.env.GOOGLE_ID!, clientSecret: process.env.GOOGLE_SECRET! }),
GitHub({ clientId: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET! }),
Credentials({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
authorize: async (credentials) => {
const user = await db.query.users.findFirst({
where: eq(users.email, credentials.email as string),
});
if (!user || !await verifyPassword(credentials.password as string, user.hashedPassword)) {
return null;
}
return { id: user.id, email: user.email, name: user.name, role: user.role };
},
}),
],
callbacks: {
session: ({ session, token }) => ({
...session,
user: { ...session.user, id: token.sub, role: token.role },
}),
jwt: ({ token, user }) => {
if (user) token.role = (user as any).role;
return token;
},
},
pages: {
signIn: "/auth/signin",
error: "/auth/error",
},
});
// app/api/auth/[...nextauth]/route.ts
export { handlers as GET, handlers as POST } from "@/auth";
Protected Routes
// middleware.ts — Protect routes
import { auth } from "./auth";
export default auth((req) => {
const isLoggedIn = !!req.auth;
const isOnDashboard = req.nextUrl.pathname.startsWith("/dashboard");
const isOnAdmin = req.nextUrl.pathname.startsWith("/admin");
if (isOnAdmin && req.auth?.user?.role !== "admin") {
return Response.redirect(new URL("/unauthorized", req.nextUrl));
}
if (isOnDashboard && !isLoggedIn) {
return Response.redirect(new URL("/auth/signin", req.nextUrl));
}
});
export const config = { matcher: ["/dashboard/:path*", "/admin/:path*"] };
React Components
import { auth, signIn, signOut } from "@/auth";
// Server component
async function UserNav() {
const session = await auth();
if (!session?.user) {
return (
<form action={async () => { "use server"; await signIn("google"); }}>
<button>Sign in with Google</button>
</form>
);
}
return (
<div>
<img src={session.user.image!} alt="" className="w-8 h-8 rounded-full" />
<span>{session.user.name}</span>
<form action={async () => { "use server"; await signOut(); }}>
<button>Sign out</button>
</form>
</div>
);
}
// Client component
"use client";
import { useSession } from "next-auth/react";
function ClientProfile() {
const { data: session, status } = useSession();
if (status === "loading") return <Spinner />;
if (!session) return <p>Not signed in</p>;
return <p>Welcome, {session.user.name}!</p>;
}
Installation
npm install next-auth@beta # Auth.js v5 for Next.js
npm install @auth/drizzle-adapter # Database adapter
Best Practices
- 80+ providers — Google, GitHub, Apple, Discord, Slack, etc.; add by importing and configuring
- Database adapters — Drizzle, Prisma, MongoDB, Supabase, Turso; stores users and sessions
- Middleware protection — Auth check at the edge; fast, runs before page renders
- Callbacks — Use
jwtandsessioncallbacks to add custom fields (role, plan, org) - Server actions —
signIn()andsignOut()work as Next.js server actions; no client-side SDK needed - Edge compatible — Runs on Vercel Edge, Cloudflare Workers; JWT sessions for stateless auth
- CSRF protection — Built-in CSRF token validation; no additional setup needed
- Multi-framework — Works with Next.js, SvelteKit, Express, Qwik; same config pattern
Signals
- GitHub stars
- 148
- Forks
- 18
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
authjs- Source
- github.com/terminalskills/skills