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
相关产品推荐
相关产品推荐

