OIDC client library のバグで時間を溶かしたので記録しておきます。
UPDATE
keycloak-js 25.0.4 でついに修正が入りました。これで安心してupgradeできます。よかったね〜
https://github.com/keycloak/keycloak/commit/a95894dbadfb8b9d973bc52f13e331ac3d8dafd2
しかしrelease noteにはありません。なぜ〜〜
https://github.com/keycloak/keycloak/releases
https://github.com/keycloak/keycloak/releases/tag/25.0.4
Issue
keycloak 23 を 25.0.2 にしたら突然 OIDC Clientのアプリが認証で無限 redirect ループするようになった。
症状
- keycloak-js を最新の 25.0.2 にしたら、一部のクライアントは直ったが一部は直らない
- 同じ状態でも発生したりしなかったりする
- local環境で再現できないので手間取った
- keycloakの debug logを出してもエラーは出ていない
- keycloak-jsの方はすぐredirectしてしまうので調査困難
原因
- keycloak-js おそらく 24 から 25.0.2 にはバグがある
- access_token を問題なく取得した後、「こんなんいらん!」と投げ捨てるバグ w
Overview
details
問題のコードは 2022/1/13 からずっと変わっていない
https://github.com/keycloak/keycloak/commit/dea123169f7
dea123169f7 adapters/oidc/js/src/main/js/keycloak.js (Jon Koops 2022-01-13 08:28:30 +0100 805)
if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
dea123169f7 adapters/oidc/js/src/main/js/keycloak.js (Jon Koops 2022-01-13 08:28:30 +0100 806) (kc.refreshTokenParsed &&
kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
dea123169f7 adapters/oidc/js/src/main/js/keycloak.js (Jon Koops 2022-01-13 08:28:30 +0100 807) (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) {
問題のきっかけ
keycloak 24 から access_token の nonce が消えた
Sat Feb 17 19:35:39 2024 +0100
JS adapter incorrectly checked the "nonce" in the access token and which was removed in Keycloak 24.
そのコミット
dea15e25da Only add the nonce claim to the ID Token (mapper for backwards compatibility) Closes #26893
https://github.com/keycloak/keycloak/pull/27588
真の原因
keycloak 24 の変更により、 access_token.nonce
の検証をしている keycloak-js
がこけるようになった
Solutoin
2024-02-08 に直ったもの(5ヶ月経ってるのに 最新 v25.0.2 でもまだ取り込まれていない)
25.0.3で直るのかどうかはわかってない。
https://github.com/keycloak/keycloak/commit/a95894dbad
https://github.com/keycloak/keycloak/issues/26651
a95894dbadf js/libs/keycloak-js/src/keycloak.js (Grzegorz Grzybek 2024-02-08 13:19:32 +0100 805) if (useNonce && (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce)) {
これを node_modules に無理やり当てればいい。
- if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
- (kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
- (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) {
+ if (useNonce && (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce)) {
学び
- すぐ redirect する場合は localStorage に log を入れると便利
- 怪しいところにこういうのを入れて、chrome debug tool > Application > localStorage で確認する
function saveLog() {
const fieldname = `tokenParsedNonce-${new Date().toISOString()}`;
localStorage.setItem(fieldname, "保存したい文字列");
}
}
saveLog()
- vue router はただの被疑者
- redirectするときにhashが無限に増えていく問題があったので vue routerとの相性が悪いんじゃないかと調べたらこういうissueがあった
- vue router周りの大改造をして時間ロス。結果意味なし。でもこの方が安定しそうで結果的にはよかったと思う。
- vue routerを動かす前に
keycloak.init()
するといいらしい。確かに。
export const keycloak = new Keycloak({
realm: "[REDACTED]",
url: "[REDACTED]",
clientId: "[REDACTED]",
});
const kc_options = {
onLoad: "login-required",
checkLoginIframe: false,
flow: "standard",
};
await keycloak.init(kc_options);
app.use(createPinia());
app.use(router);
- token取れて
authSuccess()
呼んでればここは大丈夫やろ、という油断- まさか
authSuccess()
で token 投げ捨てるとは思わなかった
- まさか
http status=200 でここ通ればだいたい ok やろ・・
if (req.status == 200) {
var tokenResponse = JSON.parse(req.responseText);
--> authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard');
よく見たらレスポンスのvalidationしてないのに authSuccess()
してた。これは関数名がミスリーディング..
疑問
100%コケそうなバグなのに、一貫性がないのが謎。keycloak >= 24 がたまにaccess tokenにnonceを入れるバグでもあるのん??
終わりに
みんな!最新バージョンじゃなくてもバグはあるぞ!
どうせなら誰も見つけてないときに見つけて PR 送りたかった!