0

I'm trying to login with Apereo CAS 5.1.1 in my react application using OIDC. Looking for libraries to achieve this, I landed on oidc-client-js 1.7.0, but I'm encountering the following error:

ResponseValidator._validateAccessToken: Failed to validate at_hash dWr5-bD5lv8C1x3VcfFn1Q dWr5+bD5lv8C1x3VcfFn1Q==

Following the trace, I found where the exception is thrown

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));

The problem is that this._joseUtil.hexToBase64Url(a) doesn't add padding (=) and in this particular case the + sign. That's because those characters aren't accepted in an URL. So, the comparison always (or almost always) will be false. For example, in this execution:

dWr5-bD5lv8C1x3VcfFn1Q != dWr5+bD5lv8C1x3VcfFn1Q==

On the other hand, I think there's something I'm missing or misconfigured in my application, because otherwise every person using this library will encounter the same issue.

So, my question is: How can I successfully validate the access token in this scenario?

Thanks.

Carloso
  • 135
  • 1
  • 10

1 Answers1

0

I Found the problem going through the code of both pieces of code interacting to perform the validation.

It turned out that CAS version I was using (5.1.1) has an error in the creation of the access token hash at_hash value.

The class org.apereo.cas.oidc.token.OidcIdTokenGeneratorService has the following method: generateAccessTokenHash. The last lines of code where it actually generates the hash are:

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

The problem is that it encodes to base64 when the at_hash should be encoded in base64url according to this:

Access Token hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the access_token value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is RS256, hash the access_token value with SHA-256, then take the left-most 128 bits and base64url encode them. The at_hash value is a case sensitive string.

This problem was solved in following version of CAS, at least I can confirm that 5.2.x solved it by changing (among other things) the last line to:

return EncodingUtils.encodeUrlSafeBase64(hashBytesLeftHalf);

I hope this could be helpful to anybody who faces the same issue.

Carloso
  • 135
  • 1
  • 10