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

NextAuth对接Lark凭证认证无法获取返回值求助

解决NextAuth CredentialsProvider对接Lark无法获取返回值的问题

问题分析

  1. authorize方法判断逻辑错误:用result.ok判断认证成功,但Lark开放平台返回结构里没有ok字段,而是用code=0标识成功;同时未检查HTTP响应状态是否正常。
  2. API接口请求体解析错误:Next.js API路由的req.body已是解析后的JSON对象,无需再用JSON.parse,原写法会导致解析失败,无法正确获取code值。
  3. 缺少JWT回调:仅配置session回调无法将authorize返回的数据存入JWT token,必须通过jwt回调写入数据,才能在session中读取。
  4. 本地API调用冗余:authorize中通过fetch调用本地接口,不如直接导入接口函数,减少不必要的网络请求。

修复步骤及代码

1. 修复handleLarkLogin接口的请求体解析

// handleLarkLogin接口
export default async function handler(req, res) {
  // 直接从解析后的req.body中取code
  const { code: codex } = req.body;
  const Url = "https://open.larksuite.com/open-apis/auth/v3/tenant_access_token/internal";

  const rest = await fetch(Url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify({
      app_id: "你的app_id",
      app_secret: "你的app_secret",
    }),
  });

  const repo = await rest.json();
  // 先校验tenant_access_token是否获取成功
  if (repo.code !== 0 || !repo.tenant_access_token) {
    return res.status(400).json({ code: -1, message: "获取tenant_access_token失败" });
  }

  // 获取用户access_token
  const Urli = "https://open.larksuite.com/open-apis/authen/v1/access_token";
  const resp = await fetch(Urli, {
    method: "POST",
    headers: {
      "Content-Type": "application/json; charset=utf-8",
      // 飞书API要求Authorization需带Bearer前缀
      Authorization: `Bearer ${repo.tenant_access_token}`,
    },
    body: JSON.stringify({
      grant_type: "authorization_code",
      code: codex,
      app_id: "你的app_id",
      app_secret: "你的app_secret",
    }),
  });

  const result = await resp.json();
  res.status(resp.status).json(result);
}

2. 修复[...nextauth.js]逻辑,添加JWT回调

// [...nextauth.js]
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
// 直接导入API函数,避免本地网络请求
import handleLarkLogin from "../../api/handleLarkLogin";

export const authOptions = {
  secret: process.env.SECRET,
  session: {
    strategy: "jwt",
  },
  providers: [
    CredentialsProvider({
      async authorize(credentials, req) {
        const { code } = credentials;
        // 模拟API路由的req/res对象,直接调用handleLarkLogin函数
        const mockRes = {
          status: (status) => ({
            json: (data) => Promise.resolve(data)
          })
        };
        const mockReq = {
          method: "POST",
          body: { code }
        };
        const result = await handleLarkLogin(mockReq, mockRes);

        // 按飞书返回规则判断认证成功:code=0且存在access_token
        if (result.code === 0 && result.access_token) {
          // 返回需要存入token的用户数据
          return {
            id: result.user_id,
            accessToken: result.access_token,
          };
        }
        // 认证失败返回null
        return null;
      },
    }),
  ],
  pages: {
    signIn: "/auth/token",
  },
  callbacks: {
    // JWT回调:将authorize返回的数据存入token
    async jwt({ token, user }) {
      if (user) {
        token.id = user.id;
        token.accessToken = user.accessToken;
      }
      return token;
    },
    // Session回调:从token中读取数据同步到session
    async session({ session, token }) {
      session.user.id = token.id;
      session.user.accessToken = token.accessToken;
      return session;
    },
  },
};

export default NextAuth(authOptions);

3. 前端handleSubmit优化(可选)

// auth/token/index.js
const handleSubmit = async (e) => {
  e.preventDefault(); // 阻止默认表单提交行为
  try {
    const signInResponse = await signIn("credentials", {
      redirect: false,
      code: data,
    });

    if (signInResponse.ok) {
      console.log("登录成功", signInResponse.data);
      // 登录成功后可跳转首页
      // router.push('/');
    } else {
      console.log("登录失败", signInResponse.error);
    }
  } catch (error) {
    console.error("登录出错", error);
  }
};

关键注意点

  • 飞书API Authorization格式:必须添加Bearer 前缀,否则接口调用会失败。
  • 认证状态校验:严格按照飞书返回的code=0判断成功,同时检查核心字段(如access_token)是否存在。
  • JWT与Session联动:必须通过jwt回调存储数据,再通过session回调同步,前端才能获取到用户信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:35:11