返回

LinkedIn OAuth授权invalid_client错误?解决方法全解析

php

LinkedIn OAuth 授权总是返回 "invalid_client" 错误?解决方法看这里!

最近在集成 LinkedIn OAuth 登录时碰到了一个棘手的问题,无论怎么尝试,获取 access token 时总是返回 invalid_client 错误,HTTP 状态码是 401。 错误信息长这样:

{
    "error": "invalid_client",
    "error_description": "Client authentication failed"
}

第一步,跳转到 LinkedIn 授权页面 ( https://www.linkedin.com/oauth/v2/authorization ) 一切正常。LinkedIn 让我登录、授权,然后把 code 发送到我的回调地址。但问题就出在第二步,用 code 换 token 的时候。

这是我用来换取 token 的 PHP curl 代码:

  $url = 'https://www.linkedin.com/oauth/v2/accessToken';  
  $curlPostarray=array('grant_type' => 'authorization_code','code' => $code,'redirect_uri' => $redirect_uri,'client_id' => $client_id,'client_secret' => $client_secret);
  $ch = curl_init();    
  curl_setopt($ch, CURLOPT_URL, $url);    
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);    
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($curlPostarray));
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
  $data = curl_exec($ch);
  $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
  curl_close($ch);

$curlPostarray 数组的内容如下:

Array
(
    [grant_type] => authorization_code
    [code] => AQQ17WLswbJMyAwpNa7JcTREK3rp0emxrYyGZNWWYG3S8PL58wEsvQPaYLUZbZPPe-7y0b1Ot8fVaARsgsHOnVa2Z3FqeT3Hql4TpCfXyadA8M61VmJQdEqJCwfz_mZ2QLCqkZOGNb_R1dwo7dEfvadFQk8F0P_ar78RkXb5h4Hm4GiRST9YUqM1_xoUMObdPmtFkmzkMGUGcvrj4SU
    [redirect_uri] => https://www.example.com/slpw/plugin_sociallogin/linkedinredirect.php
    [client_id] => 86o7njo0ccd8y6
    [client_secret] => WPL_AP1.xxxxxxxBoS0pn.SEMvrg
)

我可以确定 code、client_id、client_secret 和 redirect_uri 都是正确的(为了安全起见,示例中做了修改)。同样的这段代码,对接其他平台的 OAuth 都没问题。我还试了两个不同的 LinkedIn 应用,两个不同的账号,结果都一样。为了排除 PHP Curl 的问题,我还用了 Rested App(Mac 上的一个 API 测试工具),还是报同样的错。 真是让人头大!

问题根源:揪出幕后黑手

invalid_client 错误通常意味着客户端认证失败。 这可能有几个原因:

  1. Client ID 或 Client Secret 不正确: 最常见的原因。即使你觉得自己输入正确,也可能有肉眼难以察觉的错误,比如多了一个空格、大小写不对等等。
  2. Redirect URI 不匹配: LinkedIn 会检查回调地址是否与你在应用设置中配置的完全一致。
  3. 请求格式问题: 有些人发现请求头中的 Content-Type 设置可能会导致这个问题,确保它被正确设置成了application/x-www-form-urlencoded
  4. 应用权限问题: 检查LinkedIn后台应用是否有相应的权限。
  5. LinkedIn 服务端问题 :虽然少见,但也可能是 LinkedIn 那边出了问题。

解决方案:对症下药,逐个击破

既然知道了可能的原因,那咱就一个个来排查和解决:

1. 仔细核对 Client ID 和 Client Secret

  • 复制粘贴要小心: 从 LinkedIn 开发者后台直接复制 Client ID 和 Client Secret,千万别手动输入。
  • 检查空格: 确保复制的内容里没有多余的空格,尤其是开头和结尾。
  • 大小写敏感: 确认大小写完全一致。
  • +字符导致的问题 。 当将凭证通过 HTTP 或类似渠道传输时,必须特别小心加号字符。加号通常在 URL 或 HTTP 标头中被解释为空格。但是,对于作为客户端凭证或其他上下文中一部分的密码,这些加号在通过 HTTP 以 URL 编码形式传递时应替换为 %2B。因此,在使用 curl 时,请确保始终以 URL 编码的形式传输包含 + 符号的值。

2. 确保 Redirect URI 完全一致

  • 完全匹配: redirect_uri 参数必须和你在 LinkedIn 应用设置中配置的 "Authorized Redirect URLs" 完全一致。 一个字符都不能差!包括协议 (http vs https)、域名、路径,甚至末尾有没有斜杠 /
  • 多个回调地址: 如果你有多个回调地址,确保你用的是其中一个 已经配置好 的。

3. 确认 Content-Type

你的代码里已经设置了 Content-Type: application/x-www-form-urlencoded,这通常是正确的。但为了保险起见,可以再强调一下:

  • 代码确认: 在你的 PHP 代码中,确认设置了正确的 HTTP header:

    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
    

4.检查并修复+字符问题(进阶)

很多OAuth 服务端在实现时,都会遵循URL编码规范. 加号(+)在URL编码会被转换成空格, 因而服务商可能会对这些做强制转换, 如果没有则可能导致授权失败。

  • 使用str_replace替换:
 $client_secret = str_replace('+', '%2B', $client_secret);
 $curlPostarray=array('grant_type' => 'authorization_code','code' => $code,'redirect_uri' => $redirect_uri,'client_id' => $client_id,'client_secret' => $client_secret);
  • 使用rawurlencode 进行url编码:
  $url = 'https://www.linkedin.com/oauth/v2/accessToken';  
  $curlPostarray=array('grant_type' => 'authorization_code','code' => $code,'redirect_uri' => $redirect_uri,'client_id' => $client_id,'client_secret' => $client_secret);

  $postData = '';
  foreach($curlPostarray as $key => $value) {
      $postData .= $key . '='.rawurlencode($value).'&';
  }
  $postData = rtrim($postData, '&');
  
  $ch = curl_init();    
  curl_setopt($ch, CURLOPT_URL, $url);    
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);    
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); //直接传字符串
  // 不需要设置 Content-Type,curl 会自动根据 $postData 的形式设置
  $data = curl_exec($ch);
  $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
  curl_close($ch);
*   `rawurlencode` 会把空格编码成 `%20`,而 `urlencode` 会把空格编码成 `+`。根据 RFC 3986,`rawurlencode` 更符合标准。

5. LinkedIn App 设置检查 (容易忽略)

登录到LinkedIn开发人员控制台,然后选择你的App:

  • 检查 App 状态: 在 "Settings" 部分,确保你的 App 状态是 "Active" (激活的)。
  • 检查 “Auth”: 点击Auth页面,并确保在 "OAuth 2.0 settings"下“Authorized Redirect URLs for your app”包含了回调地址.

6.使用LinkedIn官方提供的调试方法进行逐步调试(进阶):

使用 LinkedIn 官方的API 调试工具 Postman collection, 下载Postman然后导入环境。 使用它能更好的观察数据流动。

7. 尝试新的 LinkedIn 应用

极少数情况下,问题可能出在 LinkedIn 应用本身。可以尝试创建一个全新的 LinkedIn 应用,用新的 Client ID 和 Client Secret 再试一次。
虽然不常见,但是如果上面都确认了, 还不能解决。可以试试这个,没准能撞上大运。

希望以上这些方法可以帮到你,如果问题还没有得到解决。 多刷新 LinkedIn 开发者页面的缓存、更换浏览器测试等等, 有时候也会有一些莫名奇妙的问题。