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

如何处理sidebase/nuxt-auth中refresh端点的自动请求错误?

在sidebase/nuxt-auth中处理刷新令牌错误并自动登出

sidebase/nuxt-auth基于next-auth实现,你可以通过扩展JWT回调和Session回调来处理刷新令牌失败的场景,自动触发登出操作,具体实现如下:

1. 配置JWT回调处理刷新逻辑

在项目的server/api/auth/[...].ts文件中,修改NuxtAuthHandler的配置,在jwt回调中实现令牌刷新,并捕获刷新失败的错误:

import { NuxtAuthHandler, signOut } from '#auth'
import CredentialsProvider from 'next-auth/providers/credentials'

export default NuxtAuthHandler({
  providers: [
    CredentialsProvider.default({
      name: 'Credentials',
      credentials: {
        username: { label: 'Username', type: 'text' },
        password: { label: 'Password', type: 'password' }
      },
      async authorize(credentials: any) {
        // 替换为自研后端的登录校验逻辑
        const response = await fetch('https://你的后端地址/login', {
          method: 'POST',
          body: JSON.stringify(credentials),
          headers: { 'Content-Type': 'application/json' }
        })
        const user = await response.json()
        if (response.ok && user) {
          return user
        }
        return null
      }
    })
  ],
  callbacks: {
    async jwt({ token, user, account }) {
      // 首次登录时保存令牌信息
      if (account && user) {
        return {
          accessToken: account.access_token,
          refreshToken: account.refresh_token,
          expiresAt: Date.now() + account.expires_in * 1000,
          user
        }
      }

      // 令牌未过期,直接返回
      if (Date.now() < token.expiresAt) {
        return token
      }

      // 尝试刷新令牌
      try {
        const refreshResponse = await fetch('https://你的后端地址/refresh', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ refreshToken: token.refreshToken })
        })

        if (!refreshResponse.ok) {
          throw new Error('Refresh token invalid')
        }

        const newTokens = await refreshResponse.json()
        return {
          ...token,
          accessToken: newTokens.access_token,
          refreshToken: newTokens.refresh_token || token.refreshToken,
          expiresAt: Date.now() + newTokens.expires_in * 1000
        }
      } catch (err) {
        // 刷新失败,标记错误状态
        return { ...token, error: 'RefreshTokenError' }
      }
    },
    async session({ session, token }) {
      // 将令牌数据同步到session
      session.accessToken = token.accessToken
      session.user = token.user

      // 检查到刷新错误,触发登出
      if (token.error === 'RefreshTokenError') {
        await signOut({ redirect: false })
        // 如需跳转登录页,可设置redirect: '/login'
      }

      return session
    }
  }
})

2. 关键逻辑说明

  • 在jwt回调中,当令牌即将过期时发起刷新请求,捕获请求失败的异常,给token添加error: 'RefreshTokenError'标记
  • 在session回调中检查该标记,一旦发现则调用signOut执行登出操作
  • 若需要登出后自动跳转登录页,可将signOut的redirect参数设为目标路径(如'/login')

3. 额外提示

  • 确保自研后端的refresh端点在令牌无效/过期时返回正确的HTTP错误状态码(如401 Unauthorized),这样!refreshResponse.ok才能正确捕获错误
  • 如果你需要在前端页面中处理登出后的状态,可以通过useSession()钩子监听session变化,做相应的UI调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:57:27