首页 > 解决方案 > 使用 oidc-client-js 和 Apereo CAS 验证访问令牌失败

问题描述

我正在尝试使用OIDC在我的反应应用程序中使用 Apereo CAS 5.1.1登录。寻找库来实现这一点,我登陆oidc-client-js 1.7.0,但我遇到以下错误:

ResponseValidator._validateAccessToken:无法验证 at_hash dWr5-bD5lv8C1x3VcfFn1Q dWr5+bD5lv8C1x3VcfFn1Q==

跟踪跟踪,我找到了引发异常的位置

var a = s.substr(0, s.length / 2), u = this._joseUtil.hexToBase64Url(a);

return u !== e.profile.at_hash ? 
(i.Log.error("ResponseValidator._validateAccessToken: Failed to validate at_hash", u, e.profile.at_hash), Promise.reject(new Error("Failed to validate at_hash"))) : 
(i.Log.debug("ResponseValidator._validateAccessToken: success"), Promise.resolve(e));

问题是this._joseUtil.hexToBase64Url(a)不添加填充(=),在这种特殊情况下是+符号。这是因为 URL 中不接受这些字符。因此,比较总是(或几乎总是)将是错误的。例如,在此执行中:

dWr5-bD5lv8C1x3VcfFn1Q != dWr5+bD5lv8C1x3VcfFn1Q==

另一方面,我认为我的应用程序中缺少或配置错误的东西,因为否则每个使用这个库的人都会遇到同样的问题。

所以,我的问题是:如何在这种情况下成功验证访问令牌?

谢谢。

标签: javascriptreactjscasopenid-connectoidc-client-js

解决方案


我发现问题是通过两段代码交互来执行验证的代码。

原来我使用的 CAS 版本(5.1.1)在创建访问令牌哈希at_hash值时出错。

该类org.apereo.cas.oidc.token.OidcIdTokenGeneratorService具有以下方法:generateAccessTokenHash. 它实际生成哈希的最后几行代码是:

final byte[] digested = DigestUtils.rawDigest(hashAlg, tokenBytes);
final byte[] hashBytesLeftHalf = Arrays.copyOf(digested, digested.length / 2);
return EncodingUtils.encodeBase64(hashBytesLeftHalf);

问题是当at_hash应该根据这个在base64url中编码时它编码为base64 :

访问令牌哈希值。它的值是access_token值的ASCII表示的八位字节的hash的最左半部分的base64url编码,其中使用的hash算法是ID Token的JOSE Header的alg Header Parameter中使用的hash算法。例如,如果 alg 是 RS256,则使用 SHA-256 对 access_token 值进行散列,然后取最左边的 128 位并使用 base64url 对其进行编码。at_hash 值是区分大小写的字符串。

这个问题在以下版本的 CAS 中得到了解决,至少我可以确认 5.2.x 通过将最后一行更改为(除其他外)解决了它:

return EncodingUtils.encodeUrlSafeBase64(hashBytesLeftHalf);

我希望这对任何面临同样问题的人有所帮助。


推荐阅读