You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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).*)"]
}

关键说明

  1. 两种方案都通过NextResponse.redirect返回重定向响应,这是middleware触发页面跳转的标准方式。
  2. 方案1更省心,Auth.js会自动处理回调、会话创建等逻辑;方案2适合需要完全控制跳转路径的场景。

内容的提问来源于stack exchange,提问作者Sheile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:20:56