fix: split auth config so middleware uses Edge-compatible module

NextAuth's Credentials provider pulls in Prisma -> pg -> Node.js crypto,
which crashes in the Edge runtime. Extract an auth.config.ts with only
JWT/session callbacks (no DB, no bcrypt) and use NextAuth(authConfig) in
middleware. auth.ts spreads the config and adds the Credentials provider.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jerick
2026-04-20 16:12:15 -04:00
parent 0b4f9f5c0e
commit d41ab0c4e8
3 changed files with 28 additions and 20 deletions

21
src/lib/auth.config.ts Normal file
View File

@@ -0,0 +1,21 @@
import type { NextAuthConfig } from 'next-auth'
// Edge-compatible config — no Node.js-only imports (no Prisma, no bcrypt).
// Used by middleware for JWT verification. Providers are added in auth.ts.
export const authConfig = {
session: { strategy: 'jwt' as const, maxAge: 60 * 60 },
secret: process.env.NEXTAUTH_SECRET,
trustHost: true,
pages: { signIn: '/login' },
callbacks: {
jwt({ token, user }) {
if (user) token.id = user.id
return token
},
session({ session, token }) {
if (token.id) session.user.id = token.id as string
return session
},
},
providers: [],
} satisfies NextAuthConfig

View File

@@ -3,6 +3,7 @@ import Credentials from 'next-auth/providers/credentials'
import bcrypt from 'bcryptjs' import bcrypt from 'bcryptjs'
import { z } from 'zod' import { z } from 'zod'
import { prisma } from '@/lib/prisma' import { prisma } from '@/lib/prisma'
import { authConfig } from '@/lib/auth.config'
const loginSchema = z.object({ const loginSchema = z.object({
email: z.string().email(), email: z.string().email(),
@@ -10,6 +11,7 @@ const loginSchema = z.object({
}) })
export const { handlers, signIn, signOut, auth } = NextAuth({ export const { handlers, signIn, signOut, auth } = NextAuth({
...authConfig,
providers: [ providers: [
Credentials({ Credentials({
credentials: { credentials: {
@@ -32,23 +34,4 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
}, },
}), }),
], ],
session: {
strategy: 'jwt',
maxAge: 60 * 60, // 1 hour
},
secret: process.env.NEXTAUTH_SECRET,
trustHost: true,
pages: {
signIn: '/login',
},
callbacks: {
jwt({ token, user }) {
if (user) token.id = user.id
return token
},
session({ session, token }) {
if (token.id) session.user.id = token.id as string
return session
},
},
}) })

View File

@@ -1,6 +1,10 @@
import { auth } from '@/lib/auth' import NextAuth from 'next-auth'
import { authConfig } from '@/lib/auth.config'
import { NextResponse, type NextRequest } from 'next/server' import { NextResponse, type NextRequest } from 'next/server'
// Use the Edge-compatible config so no Node.js-only modules are bundled here.
const { auth } = NextAuth(authConfig)
// Process-local store — adequate for a self-hosted single-instance deployment. // Process-local store — adequate for a self-hosted single-instance deployment.
const rateLimitStore = new Map<string, { count: number; resetAt: number }>() const rateLimitStore = new Map<string, { count: number; resetAt: number }>()
const RATE_LIMIT = 10 const RATE_LIMIT = 10