多分あんまり必要とされない知識だと思うがメモ。動機としては以下のような理由で調べていた。
- KeyCloakのユーザのパスワードを、KeyCloakの外にある自家製システムからREST APIで直接更新したい。
- 更新失敗時に時間を置いて後で再試行出来るようにしたいが、後の再試行のために生パスワードを保存したくない。
- 自家製システム内でハッシュ化を行った上でハッシュの方をKeyCloakに渡す形にできないか?これなら再試行が必要な場合も生パスワードでなくハッシュを保存すれば良くなる。
以下、「パスワードハッシュ」「ソルト」などの基本的知識はある前提で書いていく。
KeyCloakのAdmin Consoleで適当なユーザのCredentials→Show Dataを確認すると、自分の建てた環境(KeyCloak 11.0.3)では
algorithm: pbkdf2-sha256
hashIterations: 27500
という結果が出る。
さらにちょっとDBを直接覗いて「credential」テーブルの情報を見てみると、各ユーザーに対応して以下のようなデータが出てくる。
secret: {
"value":"oVD+6dGK/gL+ydKy9DxBIuD1rolSCLjmtW1rq9RxHtOJOf0mjeDajEB+TXMiPPlYiYhEHznD2nahyeVlrRJkPw==",
"salt":"pQE+OvqmkNmzEvIhjckUfw=="
}
credential_data: {
"hashIterations":27500,
"algorithm":"pbkdf2-sha256"
}
credential_dataの方が「Show Data」で表示されている情報のようだ。そしてsecretにパスワードハッシュなどの情報が収録されているらしい。
問題は、生パスワードとソルトからどうすれば自力でsecretのvalueの情報を生成できるのかだ。結論から言えば、例えばPHPの場合以下のように行うことが出来る。
base64_encode(
hash_pbkdf2(
"sha256", // algorithm
"password", // password
base64_decode("pQE+OvqmkNmzEvIhjckUfw=="), // salt
27500, // iteration
64, // byte
TRUE // binary
)
);
valueの値はpdkbf2とsha256で64バイトバイナリ形式の鍵を出力し、それをbase64でエンコードしたものらしい。PHPならばhash_pbkdf2という関数があるのでそれをそのまま利用できる。最後にバイナリフラグをTRUEにしないとバイナリではなく16進数文字列になってしまうので気を付ける。
ちなみにsaltは16バイトのバイナリをbase64エンコードしたものだった。もっとも自分でパスワードハッシュを生成する場合、ソルトは最後にbase64かける所だけ守れば後は自由に生成して良さそうだが。iterationもKeyCloakのデフォが27500なだけで、そこは縛られている訳ではないはず。
こうして生成したハッシュとソルトをAdmin REST APIで/auth/admin/realms/{realm}/users/{id}/reset-passwordエンドポイントに以下のような形で投げればパスワードは更新できるはずである。詳細はこの辺とか。
{
"type": "password",
"temporary": false,
"algorithm": "pbkdf2-sha256",
"hashIterations": 27500,
"hashedSaltedValue":"oVD+6dGK/gL+ydKy9DxBIuD1rolSCLjmtW1rq9RxHtOJOf0mjeDajEB+TXMiPPlYiYhEHznD2nahyeVlrRJkPw==",
"salt":"pQE+OvqmkNmzEvIhjckUfw=="
}
まとめ
- 適当にソルトを生成(KeyCloakに倣えばランダムバイナリ16バイト)
- pdkbf2&sha256で64バイトの鍵をバイナリ形式で生成
- 鍵とソルトをそれぞれbase64エンコード
- reset-passwordエンドポイントに所定の形式で投げる
でパスワード更新可能。
余談だが、KeyCloakのデフォルトではハッシュ関数はPBKDF2のみをサポートしているらしい。ソースはここ。なので標準の状態だと上記のalgorithmにはpbkdf2-sha256以外使えないものと思われる。ただプラグインで自分のハッシュ関数を追加できるらしくて、bcryptなどはgithubにプラグインのリポジトリもある。KeyCloakプラグインの追加方法は調べるのが面倒だったので調べていない。
参考にしたURL
https://www.keycloak.org/docs-api/5.0/rest-api/index.html#_resetpassword
https://qiita.com/ogawa_pro/items/ec25ecf90f2b0fdeff37
https://www.keycloak.org/docs/latest/server_admin/index.html#password-policy-types
https://stackoverrun.com/ja/q/9346466
https://dev.to/carnewal/import-existing-users-with-bcrypt-hashed-passwords-in-keycloak-17oo