Skills authjs
install
source · Clone the upstream repo
git clone https://github.com/TerminalSkills/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/authjs" ~/.claude/skills/terminalskills-skills-authjs && rm -rf "$T"
manifest:
skills/authjs/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
Auth.js (NextAuth) — Authentication for the Web
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
andjwt
callbacks to add custom fields (role, plan, org)session - Server actions —
andsignIn()
work as Next.js server actions; no client-side SDK neededsignOut() - 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