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

Next.js 13中NextAuth自定义OAuth Provider如何用URL参数Code换取令牌?

问题描述

我创建了如下NextAuth自定义OAuth Provider:

{
  id: "oidc",
  name: "OIDC",
  type: "oauth",
  authorization: {
    url: "https://www.auth.mywebsite.com/oauth2/authorize",
    params: {
      scope: "openid email profile aws.cognito.signin.user.admin",
      response_type: "code",
      client_id: process.env.CLIENT_ID,
      redirect_uri: "http://localhost:3000",
      identity_provider: "Google-OIDC",
    },
  },
  idToken: true,
  checks: ["state"],
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
},

用户通过该Provider登录后,仅跳转至首页,URL中携带code参数,但无法创建session对象,且自定义Provider未触发如下jwt回调(官方Provider可正常触发):

session: { strategy: "jwt", maxAge: 30 * 24 * 60 * 60 },

callbacks: {
  async jwt({ token, trigger, account, user, session }) {
    console.log("I am here, yes I am");
    // 其余回调逻辑
  }
}

请问如何使用URL参数中的code换取令牌,并解决回调不触发的问题?

解决方案

一、修复Provider配置,让NextAuth自动处理code换令牌

你的自定义Provider缺少令牌交换的核心配置,导致NextAuth无法自动完成code换取令牌的流程,后续session创建和回调触发自然失效。需做以下调整:

  • 添加token字段,指定令牌交换的URL和必要参数
  • 移除authorization.params中的冗余参数:response_type、client_id、redirect_uri会由NextAuth自动处理,无需手动指定
  • 确保redirect_uri指向NextAuth的回调路径(默认是http://localhost:3000/api/auth/callback/oidc),而非首页

修改后的Provider配置:

{
  id: "oidc",
  name: "OIDC",
  type: "oauth",
  authorization: {
    url: "https://www.auth.mywebsite.com/oauth2/authorize",
    params: {
      scope: "openid email profile aws.cognito.signin.user.admin",
      identity_provider: "Google-OIDC",
    },
  },
  // 新增令牌交换配置
  token: {
    url: "https://www.auth.mywebsite.com/oauth2/token",
    params: {
      grant_type: "authorization_code"
    }
  },
  // 若需获取用户信息,补充userinfo配置
  userinfo: {
    url: "https://www.auth.mywebsite.com/oauth2/userInfo"
  },
  idToken: true,
  checks: ["state"],
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
}

二、确保回调触发的配置正确性

  1. 验证主配置层级:确认session和callbacks是NextAuth主配置的同级属性,结构如下:
export default NextAuth({
  providers: [/* 你的自定义Provider */],
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60,
  },
  callbacks: {
    async jwt({ token, trigger, account, user, session }) {
      console.log("I am here, yes I am");
      // 可添加逻辑,比如将令牌存入token
      if (account) {
        token.accessToken = account.access_token;
        token.idToken = account.id_token;
      }
      return token;
    },
    // 如需自定义session返回数据,实现session回调
    async session({ session, token }) {
      session.user.accessToken = token.accessToken;
      return session;
    }
  },
})
  1. 检查环境变量有效性:确认CLIENT_ID和CLIENT_SECRET已正确加载,无拼写错误或空值。

三、手动处理code换令牌(仅作备用方案)

若因特殊场景无法使用NextAuth自动流程,可在前端或API路由中手动发起请求换取令牌:

// 示例:前端获取URL中的code后发起请求
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');

if (code) {
  const tokenResponse = await fetch('https://www.auth.mywebsite.com/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': `Basic ${btoa(`${process.env.NEXT_PUBLIC_CLIENT_ID}:${process.env.NEXT_PUBLIC_CLIENT_SECRET}`)}`
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code: code,
      redirect_uri: 'http://localhost:3000/api/auth/callback/oidc',
      client_id: process.env.NEXT_PUBLIC_CLIENT_ID
    })
  });

  const tokenData = await tokenResponse.json();
  // 后续可将令牌存入存储,或调用NextAuth的signIn方法传入令牌
}

注意:优先使用NextAuth自动流程,手动处理易引发安全风险和兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:46:12