Next.js+Auth.js配置中间件自动重定向至Cognito登录页遇阻
问题背景
我正在使用Next.js@14.2.2和Auth.js(next-auth@5.0.0-beta.16)开发网站,已完成以下Cognito provider配置,通过“Sign in”按钮可正常登录:
auth.ts
import NextAuth from 'next-auth' import Cognito from 'next-auth/providers/cognito' export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [Cognito], })
app/login/page.tsx
import { auth, signIn } from '@/auth' export default async function Login() { return ( <form action={async () => { 'use server' return await signIn('cognito') }} > <button type="submit">Sign in</button> </form> ) }
遇到的问题
我希望通过middleware保护所有页面,无会话时自动重定向到Amazon Cognito(身份提供商)的登录页,但当前middleware代码无法生效(无会话时停留在受保护页面,不重定向),还出现以下错误日志:
middleware.ts
import { signIn, auth } from "@/auth" export default auth((request) => { if (!request.auth) { signIn('cognito') } }) export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico|login).*)"] }
错误日志
ReadonlyRequestCookiesError: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options at Proxy.callable (webpack-internal:///(middleware)/./node_modules/next/dist/esm/server/web/spec-extension/adapters/request-cookies.js:22:15) at signIn (webpack-internal:///(middleware)/./node_modules/next-auth/lib/actions.js:53:65) ⨯ unhandledRejection: ReadonlyRequestCookiesError: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options at Proxy.callable (webpack-internal:///(middleware)/./node_modules/next/dist/esm/server/web/spec-extension/adapters/request-cookies.js:22:15) at signIn (webpack-internal:///(middleware)/./node_modules/next-auth/lib/actions.js:53:65) ⨯ unhandledRejection: ReadonlyRequestCookiesError: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options at Proxy.callable (webpack-internal:///(middleware)/./node_modules/next/dist/esm/server/web/spec-extension/adapters/request-cookies.js:22:15) at signIn (webpack-internal:///(middleware)/./node_modules/next-auth/lib/actions.js:53:65) GET / 200 in 46ms
注:目前我已经能实现重定向到应用内的/login页面,但希望省去用户点击按钮的步骤,直接跳转到Cognito的登录页,请问有可行方案吗?
解决方案
问题核心是:signIn是Server Action,需要修改Cookie,但middleware中的Cookie是只读的,直接调用会触发报错;同时之前的代码未返回响应,导致不会触发重定向。以下是两种可行方案:
方案1:直接重定向到Auth.js的Cognito登录端点
利用Auth.js内置的登录路由,让它自动处理跳转到Cognito登录页:
import { auth } from "@/auth" import { NextResponse } from "next/server" export default auth((request) => { if (!request.auth) { // 构造登录跳转URL,携带当前页面作为回调地址 const loginUrl = new URL('/api/auth/signin/cognito', request.url) loginUrl.searchParams.set('callbackUrl', request.url) return NextResponse.redirect(loginUrl) } }) export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico|login).*)"] }
方案2:手动构造Cognito授权URL(更直接)
如果想跳过Auth.js的中间路由,可直接拼接Cognito的授权地址(需提前在Cognito控制台配置好回调URL):
import { auth } from "@/auth" import { NextResponse } from "next/server" export default auth((request) => { if (!request.auth) { const cognitoDomain = "你的Cognito用户池域名" const clientId = "你的Cognito应用客户端ID" const callbackUrl = encodeURIComponent(request.url) const cognitoAuthUrl = `${cognitoDomain}/oauth2/authorize?response_type=code&client_id=${clientId}&redirect_uri=${callbackUrl}&scope=openid` return NextResponse.redirect(cognitoAuthUrl) } }) export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico|login).*)"] }
关键说明
- 两种方案都通过
NextResponse.redirect返回重定向响应,这是middleware触发页面跳转的标准方式。 - 方案1更省心,Auth.js会自动处理回调、会话创建等逻辑;方案2适合需要完全控制跳转路径的场景。
内容的提问来源于stack exchange,提问作者Sheile
相关产品推荐
相关产品推荐

