这个 HS256 令牌有啥问题?

Posted

技术标签:

【中文标题】这个 HS256 令牌有啥问题?【英文标题】:What is wrong with this HS256 token?这个 HS256 令牌有什么问题? 【发布时间】:2018-08-08 21:32:30 【问题描述】:

我正在使用 jwt-php 和 firebase-tokengenerator 为自定义身份验证流 (https://github.com/firebase/firebase-token-generator-php) 创建令牌。

我不断收到 invalid_custom_token 错误。像这样:


 "error": 
  "errors": [
   
    "domain": "global",
    "reason": "invalid",
    "message": "INVALID_CUSTOM_TOKEN"
   
  ],
  "code": 400,
  "message": "INVALID_CUSTOM_TOKEN"
 

当我将生成的令牌放入 https://jwt.io/ 时,我得到“无效签名”直到我手动更改 UID 或 displayName 中的一个字符。

这是一个生成的令牌,应用时 jwt.io 站点和 Firebase 均失败:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6ZmFsc2UsImRlYnVnIjpmYWxzZSwiZCI6eyJ1aWQiOiI2NTQwMDA0NCIsImRpc3BsYXlOYW1lIjoiV2lsbHkgRSBDb3lvdGUifSwidiI6MCwiaWF0IjoxNTE5ODUyNzE1fQ.ScM_nZtwH1zCyiWnPKNi_JLTVwguKibS5z8FLjo6Lco P>

但如果我更改一个字符,它会突然通过 jwt.io。这可能毫无意义,但在我放弃整个方法并尝试其他方法之前,我已经竭尽全力尝试通过这个愚蠢的步骤......

我使用 Firebase for Google 和 username/pw 身份验证,并尝试将第 3 方身份验证系统 (LTI) 连接到我的项目。

这里是php:

$expires = time() + 3600;
$secret = 'XXXX';

try 
  $generator = new TokenGenerator($secret);
  $token = $generator
    // ->setOption('admin', false)
    // ->setOption('debug', true)
    // ->setOption('expires', $expires)
    ->setData(array('uid' => '65400044', 'displayName' => 'Willy E Coyote'))
    ->create();
 catch (TokenException $e) 
    echo "Error: " . $e->getMessage();

echo $token;

以及使用token的jquery:

success: function(fbToken)
  console.log('Response from FB token generator: ') + console.log(fbToken);
  console.log('Now try Firebase with token...');
  firebase.auth().signInWithCustomToken(fbToken).catch(function(error) 
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    console.log('Errors: ' + error.message);
    // ...
  );

我也不明白为什么控制台中有两次对 Firebase 的调用。第一个不会产生数据但成功(200 代码)。第二个显示错误和400。

我已经为 IAT 的问题做好了准备......我还想知道我是否已经获得了识别我的 Firebase 项目的所有必要信息 - php 脚本中的唯一数据是 Firebase 项目机密。

任何帮助或方向表示赞赏...

【问题讨论】:

jwt.io 需要知道用于签名的秘密。在验证签名下有一个输入字段。如果您不提供密钥,则验证失败。当您更改右侧有效负载中的值时,您会看到验证签名的效果。那是因为调试器双向工作,如果您在右侧更改某些内容,它会使用给定的秘密(默认为“秘密”)计算新签名。当您更改右侧的有效负载时,只需观察左侧会发生什么。 感谢您回答这个问题...您完全正确,我没有完全理解该工具。结果证明该令牌是合法的,但它适用于 SDK 2...并且尝试使用该令牌的代码是 SDK 3。如果您想在背面使用 PHP,那么为 Firebase 自定义身份验证生成令牌的正确方法最后,使用 php-jwt 和本页最底部的示例代码:firebase.google.com/docs/auth/admin/…. 【参考方案1】:

正如您在原始帖子的评论中所写,问题在于您使用了已弃用的令牌生成器,该生成器仅适用于已被 Firebase 弃用的数据库机密。

使用新的 SDK,您必须使用为您的项目生成的私钥签署自定义令牌,您可以通过从项目设置中的 Service Accounts Section 下载凭据文件来检索该私钥。

如果您不想自己实现流程,我建议您查看https://github.com/kreait/firebase-php,它可以让您像这样工作:

use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;

$serviceAccount = ServiceAccount::fromJsonFile('/path/to/credentials.json');

$firebase = (new Factory)
    ->withServiceAccount($serviceAccount)
    ->create();

$uid = 'some-uid';
$additionalClaims = []; // optional

$customToken = $firebase->getAuth()->createCustomToken($uid, $additionalClaims);

您还可以验证由您的客户端应用程序创建的 ID 令牌等,如 https://firebase-php.readthedocs.io/en/latest/ 所述

免责声明:我创建了库:)。

【讨论】:

以上是关于这个 HS256 令牌有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何验证在 jwt.io 上使用 Keycloak 身份验证提供程序创建的 HS256 签名 JWT 令牌

Node.js 中未使用 RS256 算法生成 jsonwebtoken 令牌

HMAC 256 与 HMAC 512 JWT 签名加密

JWT令牌详解

使用带有 RSA 的 JWT 解码 Id 令牌

在 Knock (rails) 中验证用 RS256 签名的 JWT 令牌