#javascript #reactjs #cas #openid-connect #oidc-client-js
#javascript #reactjs #cas #OpenID-подключиться #oidc-client-js
Вопрос:
Я пытаюсь войти с помощью Apereo CAS 5.1.1 в моем приложении react, используя OIDC. В поисках библиотек для достижения этой цели я остановился на 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==
С другой стороны, я думаю, что в моем приложении что-то упущено или неправильно настроено, потому что в противном случае каждый пользователь, использующий эту библиотеку, столкнется с одной и той же проблемой.
Итак, мой вопрос: как я могу успешно проверить токен доступа в этом сценарии?
Спасибо.
Ответ №1:
Я обнаружил проблему, возникающую в коде обоих фрагментов кода, взаимодействующих для выполнения проверки.
Оказалось, что версия 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);
Проблема в том, что он кодируется в base64, когда at_hash
должен быть закодирован в base64url в соответствии с этим:
Хэш-значение токена доступа. Его значением является кодировка base64url самой левой половины хэша октетов ASCII-представления значения access_token, где используемый алгоритм хэширования является алгоритмом хэширования, используемым в параметре заголовка alg заголовка JOSE токена ID. Например, если alg равен RS256, хэшируйте значение access_token с помощью SHA-256, затем возьмите самые левые 128 бит и закодируйте их в base64url. Значение at_hash является строкой, чувствительной к регистру.
Эта проблема была решена в следующей версии CAS, по крайней мере, я могу подтвердить, что 5.2.x решила ее, изменив (среди прочего) последнюю строку на:
return EncodingUtils.encodeUrlSafeBase64(hashBytesLeftHalf);
Я надеюсь, что это может быть полезно всем, кто сталкивается с такой же проблемой.