git clone https://github.com/Intense-Visions/harness-engineering
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/next-auth-patterns" ~/.claude/skills/intense-visions-harness-engineering-next-auth-patterns-a06988 && rm -rf "$T"
agents/skills/codex/next-auth-patterns/SKILL.mdNext.js Authentication Patterns
Implement authentication with session handling, middleware guards, and Auth.js integration
When to Use
- Protecting pages and API routes from unauthenticated access
- Implementing login, logout, and session refresh flows
- Reading the current user in Server Components and Route Handlers
- Setting up role-based access control (RBAC) at the middleware level
- Integrating OAuth providers (Google, GitHub) or credential-based auth
Instructions
- Use Auth.js (formerly NextAuth.js) v5 for a batteries-included auth layer — it handles OAuth, JWTs, sessions, and CSRF.
- Create
at the project root to configure providers, callbacks, and session strategy.auth.ts - Protect routes in
using the Auth.jsmiddleware.ts
export — redirect unauthenticated users before the page renders.auth - Access the session in Server Components with
— never trust client-supplied user data.auth() - Access the session in Client Components with
fromuseSession()
— wrap the app innext-auth/react
in a Client Component layout wrapper.<SessionProvider> - Use
andsignIn()
fromsignOut()
in Client Components, or call them from Server Actions for progressive enhancement.next-auth/react - Validate authorization (role checks) in Route Handlers and Server Actions — middleware only covers page routes by default.
- Store sensitive user attributes (roles, permissions) in the JWT callback and expose them through the session callback — never rely solely on client state.
// auth.ts — Auth.js v5 configuration import NextAuth from 'next-auth'; import GitHub from 'next-auth/providers/github'; export const { handlers, auth, signIn, signOut } = NextAuth({ providers: [GitHub], callbacks: { async jwt({ token, user }) { if (user) token.role = user.role; // persist role in JWT return token; }, async session({ session, token }) { session.user.role = token.role as string; // expose in session return session; }, }, }); // middleware.ts — route protection export { auth as middleware } from '@/auth'; export const config = { matcher: ['/dashboard/:path*', '/api/protected/:path*'], }; // app/dashboard/page.tsx — server-side session access import { auth } from '@/auth'; import { redirect } from 'next/navigation'; export default async function DashboardPage() { const session = await auth(); if (!session) redirect('/login'); if (session.user.role !== 'admin') redirect('/unauthorized'); return <Dashboard user={session.user} />; }
Details
Auth.js v5 is designed for the App Router and provides
auth() as both a middleware function and a server-side session accessor. The same function works in middleware, Server Components, Route Handlers, and Server Actions.
Session strategies: Auth.js supports JWT sessions (stateless, stored in cookies) and database sessions (stateful, stored in your database). JWT is simpler to deploy; database sessions allow true session revocation. Use database sessions when you need to invalidate sessions on logout or role changes.
Middleware guard scope: The Auth.js middleware
auth export only protects routes matched by config.matcher. API Route Handlers and Server Actions are not automatically protected — always call auth() and check the session inside them independently.
Role-based access: Store roles in the JWT payload via the
jwt callback. The JWT is signed and cannot be tampered with client-side. Read session.user.role in Server Components to make authorization decisions. Never read roles from URL parameters or request bodies for authorization.
OAuth callback URL: OAuth providers require registering the callback URL:
https://yourdomain.com/api/auth/callback/github. In development, use http://localhost:3000/api/auth/callback/github. Auth.js handles the callback route via the handlers export mounted at app/api/auth/[...nextauth]/route.ts.
PKCE and security: Auth.js automatically uses PKCE for OAuth flows and includes CSRF protection for credential login. Do not re-implement these manually.
Source
https://nextjs.org/docs/app/building-your-application/authentication
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.