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

Strapi自定义插件中LinkedIn OAuth 2.0令牌交换遇Forbidden错误

问题

开发Strapi自定义插件集成LinkedIn OAuth 2.0认证,授权流程在用户携带授权码重定向回Strapi前一切正常,但用授权码交换访问令牌时持续收到Forbidden错误。

已确认以下内容:

  • 环境变量中配置的客户端ID、客户端密钥正确
  • redirect_uri与LinkedIn开发者门户设置完全一致
  • 应用已配置必要权限(openid、profile、email)
  • 使用Postman携带相同参数手动请求可成功获取令牌并调用/userinfo接口,但代码中始终失败

使用环境:

  • Strapi 4.25.7
  • Node.js v20.15.1
  • LinkedIn API:OAuth 2.0、OpenID Connect

尝试的代码如下:

module.exports = {
  async callback(ctx) {
    try {
      const { code } = ctx.query;
      
      const tokenResponse = await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
          grant_type: 'authorization_code',
          code,
          redirect_uri: 'http://localhost:1337/api/connect/linkedin/callback',
          client_id: process.env.LINKEDIN_CLIENT_ID,
          client_secret: process.env.LINKEDIN_CLIENT_SECRET,
        }),
      });

      const { access_token } = await tokenResponse.json();

      const userResponse = await fetch('https://api.linkedin.com/v2/userinfo', {
        headers: {
          Authorization: `Bearer ${access_token}`,
        },
      });

      const userData = await userResponse.json();
      
      ctx.send(userData);

    } catch (err) {
      ctx.send({ error: err.message }, 500);
    }
  },
};
解决方案

1. 捕获完整的错误响应详情

fetch仅在网络错误时抛出异常,LinkedIn返回403时不会触发catch逻辑。需主动检查响应状态码,获取具体拒绝原因:

const tokenResponse = await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
  // 现有配置
});

if (!tokenResponse.ok) {
  const errorDetails = await tokenResponse.text();
  console.error('令牌请求错误:', tokenResponse.status, errorDetails);
  throw new Error(`请求失败: ${tokenResponse.status} - ${errorDetails}`);
}

2. 验证环境变量加载正确性

Strapi环境变量可能存在加载优先级问题,直接打印变量值确认是否与配置一致:

console.log('Client ID:', process.env.LINKEDIN_CLIENT_ID);
console.log('Client Secret:', process.env.LINKEDIN_CLIENT_SECRET);

确保无多余空格、换行或大小写差异。

3. 统一redirect_uri配置

将redirect_uri移入环境变量,避免硬编码与实际配置的细微偏差:

redirect_uri: process.env.LINKEDIN_REDIRECT_URI,

同步更新.env文件,确保与LinkedIn门户设置完全匹配(含协议、域名、端口、路径)。

4. 确保授权码唯一有效

授权码仅可使用一次,且有效期约10分钟。调试时需每次走完整授权流程,获取新的授权码再执行交换。

5. 手动编码表单参数

替换URLSearchParams为手动编码的表单字符串,避免编码差异问题:

body: `grant_type=authorization_code&code=${encodeURIComponent(code)}&redirect_uri=${encodeURIComponent(process.env.LINKEDIN_REDIRECT_URI)}&client_id=${encodeURIComponent(process.env.LINKEDIN_CLIENT_ID)}&client_secret=${encodeURIComponent(process.env.LINKEDIN_CLIENT_SECRET)}`,

6. 检查Strapi中间件影响

确认Strapi的CORS、代理等中间件未修改内部请求的头信息或参数,必要时临时关闭非核心中间件测试。

内容的提问来源于stack exchange,提问作者B. Revanth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 23:58:09