JWT 令牌似乎是正确的,但收到的响应是 401

Posted

技术标签:

【中文标题】JWT 令牌似乎是正确的,但收到的响应是 401【英文标题】:JWT token appears to be correct but response received is 401 【发布时间】:2019-06-05 21:19:50 【问题描述】:

我正在尝试使用 JWT Bearer Grant Type 连接到 Docebo API,但遇到了问题:

使用下面的代码,我收到以下响应(即使在 https://jwt.io 验证时我的 $token 似乎是正确的):

stdClass Object ( [name] => Unauthorized [message] => Array ( [0] => Your request was made with invalid credentials. ) [code] => 0 [status] => 401 )

这是用于生成 $token 的代码,以及那个错误 ^

<?php 
ini_set('display_errors',1);
error_reporting(E_ALL);

function base64url_encode($data) 
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');


$key = 'example_public_key';

$headers = ['alg'=>'RS256','typ'=>'JWT'];
$headers_encoded = base64url_encode(json_encode($headers));

$today = time();
$tomorrow = time() + (1 * 24 * 60 * 60);
$payload = [
  'iss' => 'example_client_id',
  'sub' => 'example_user',
  'aud' => 'example.docebosaas.com',  
  'iat' => $today,
  'exp' => $tomorrow
];

$payload_encoded = base64url_encode(json_encode($payload));
$signature = hash_hmac('SHA256',"$headers_encoded.$payload_encoded",$key,true);
$signature_encoded = base64url_encode($signature);

$token = "$headers_encoded.$payload_encoded.$signature_encoded";

$curl = curl_init();
$curl_data =  array(
  'token' => $token
); 
curl_setopt_array($curl, array(
  CURLOPT_RETURNTRANSFER => 1,  
  CURLOPT_POSTFIELDS     => $curl_data, 
  CURLOPT_URL => 'https://example.docebosaas.com/manage/v1/user'
)); 
$resp = curl_exec($curl); 
curl_close($curl);

$json_obj = json_decode($resp);
print_r($json_obj);

更新:

根据下面的评论,我现在添加了适当的标头,并且不再收到 401。但是,将 CURL 调用更改为以下有一个新错误:

stdClass Object ( [error] => invalid_grant [error_description] => JWT failed signature verification )

这是更新后的 CURL 调用的代码:

$curl = curl_init();
$curl_data =  array(
 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
 'scope' => 'api',
 'assertion' => $token
); 
curl_setopt_array($curl, array(
 CURLOPT_RETURNTRANSFER => 1,  
 CURLOPT_POSTFIELDS     => $curl_data, 
 CURLOPT_URL => 'https://example.docebosaas.com/oauth2/token'
)); 
$resp = curl_exec($curl); 
curl_close($curl);

$json_obj = json_decode($resp);
print_r($json_obj);

【问题讨论】:

【参考方案1】:

您的 curl 示例不包含我期望的标题,例如:

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
scope=api
assertion=YOUR_SIGNED_JWT

另外,您可能希望改为调用端点 https://&lt;yoursubdomain.docebosaas.com&gt;/oauth2/token 将您的签名 JWT 转换为普通的不记名令牌。然后就可以使用标准的 Authorization 头了:

Authorization: Bearer YOUR_ACCESS_TOKEN

API General Information

【讨论】:

嗨,约翰 - 感谢您提出这个问题。现在我已经添加了这些标头并更改了端点,我收到了这个错误:stdClass Object ([error] => invalid_grant [error_description] => JWT failed signature verification) 我已经更新了我的原始帖子使用我用于 curl 调用的新代码。 错误消息意味着您的签名不起作用,这可能就像没有使用密钥对的正确部分一样简单。您在代码中提及public,通常您会使用private 密钥对进行签名。 public 密钥对用于验证签名。 您可以从私钥生成公钥,但不能从公钥生成私钥。私钥实际上包含构成公钥的两个数字。公钥缺少构成私钥的所有其他内容。

以上是关于JWT 令牌似乎是正确的,但收到的响应是 401的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net Core 3 API 总是返回 401- JwtBearer

JWT 刷新令牌 Angular

过期后使用刷新令牌获取访问令牌(JWT)

浏览器没有响应,但在邮递员中得到 401

Angular 4 和 OAuth - 拦截 401 响应,刷新访问令牌并重试请求

尝试进行身份验证时 JWT 令牌过期?