在Next.js中使用Auth.js同时实现OAuth认证与API接口Basic认证的配置问题求助
在Next.js中使用Auth.js同时实现OAuth认证与API接口Basic认证的配置问题求助
我现在遇到了一个头疼的配置问题:我想在Next.js项目里同时实现OAuth(Google登录)用户认证和API接口的Basic认证保护,但目前的配置完全跑不通——除非我删掉Basic认证的代码,还把API路由从认证规则里排除,这种情况下单独用OAuth认证是完全正常的。
我把相关配置代码和遇到的错误都贴出来,希望能得到大家的帮助:
相关配置文件
auth.config.ts
import type { NextAuthConfig, Session } from 'next-auth'; import Google from "next-auth/providers/google" import { SupabaseAdapter } from "@auth/supabase-adapter" import { NextRequest } from 'next/server'; export const authConfig = { pages: { signIn: '/login' }, callbacks: { authorized({ auth, request: { nextUrl }} : {auth: null | Session, request: NextRequest}) { const isLoggedIn = !!auth?.user; const isOnHomePage = nextUrl.pathname === '/'; if (isOnHomePage) { if (isLoggedIn) { return true; } return false; // 未认证用户重定向到登录页 } else if (isLoggedIn) { return Response.redirect(new URL('/', nextUrl)) } return true; } }, providers: [Google], adapter: SupabaseAdapter({ url: process.env.SUPABASE_URL!, secret: process.env.SUPABASE_SERVICE_ROLE_KEY!, }) } satisfies NextAuthConfig;
auth.ts
import NextAuth from "next-auth"; import { authConfig } from './auth.config'; export const { handlers, signIn, signOut, auth } = NextAuth(authConfig)
middleware.ts
import NextAuth from 'next-auth'; import { authConfig } from './auth.config'; import { NextResponse } from 'next/server'; const { auth } = NextAuth(authConfig); export default auth((req) => { const url = new URL(req.url); // 明确跳过NextAuth的API路由和session端点 if (url.pathname.startsWith('/api/auth/') || url.pathname === '/api/session') { return NextResponse.next(); } if (url.pathname.startsWith('/api/')) { const authHeader = req.headers.get('authorization') ?? ''; if (!authHeader.startsWith('Basic ')) { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic realm="Restricted"' }, }); } const base64 = authHeader.slice(6); let decoded = ''; try { if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') { decoded = Buffer.from(base64, 'base64').toString('utf-8'); } else if (typeof atob === 'function') { decoded = atob(base64); } else { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic realm="Restricted"' }, }); } } catch (err) { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic realm="Restricted"' }, }); } const [username, password] = decoded.split(':'); const validUsername = process.env.API_BASIC_AUTH_USER; const validPassword = process.env.API_BASIC_AUTH_PASS; if (!validUsername || !validPassword || username !== validUsername || password !== validPassword) { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic realm="Restricted"' }, }); } // Basic认证通过,放行到API处理器 return NextResponse.next(); } // 非API路由:继续执行(NextAuth会处理重定向/认证页逻辑) return NextResponse.next(); }); export const config = { // 对API路由和应用页面应用中间件;不要使用否定匹配项 matcher: [ '/api/:path*', '/((?!_next/static|_next/image|.*\\.png$).*)' ], };
遇到的错误
在浏览器控制台里弹出了这个错误:
providers.tsx:36 ClientFetchError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON. at fetchData (client.js:39:22) at async getSession (react.js:97:21) at async SessionProvider.useEffect [as _getSession] (react.js:253:43)
看起来是Auth.js在获取session的时候拿到了HTML内容而不是预期的JSON,导致解析失败。我猜可能是middleware的逻辑和NextAuth的session处理有冲突,但实在不知道该怎么调整,求大佬们指点!
内容来源于stack exchange
相关产品推荐
相关产品推荐

