Cognito や Auth0 で、認証時に JWT の検証を行いますが、実際に何をしているかちゃんと理解できてません。 以前書いた Lambda オーソライザーで Auth0 のトークンを検証する で検証をすることはできました。 理解できなくても、SDK とかを利用して処理ができるのは、抽象化がちゃんとされている証拠ではあります。 改めて何をしているか少し確認してみます。
どうやって検証している?
さすが AWS 、良いドキュメントがありました。
理解したいのは「ステップ 2: JWT 署名を検証する」と「ステップ 3: クレームを検証する」部分です。
JWT 署名を検証する
ここの理解が怪しいので、間違っていれば有識者にツッコんでいただきたい。
公開鍵の取得
ヘッダーの情報をもとに、公開鍵を取得。
公開鍵の処理は、ヘッダーのアルゴリズムと JSON ウェブキーセット (JWKS) を利用して、処理を行う。
Cognito : https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json Auth0: https://<Auth0テナント>.auth0.com/.well-known/jwks.json
kid
Claim と、 jwks.json の kid
が同じかチェック。
alg =RS256
が使われているので、n
と e
をデコードした数値を使えば RSA の公開鍵は作成可能。
e
は公開指数で、 AQAB
が指定されてることが多く、デコードすると 65,537 になる。
base64の文字列: AQAB base64変換:000000 010000 000000 000001 2進数へ:00000001 00000000 00000001 16進数へ:0x10001 10進数へ:65537
n
は、RSA暗号のモジュラス(Modulus)で、2つの素数p, qの積...
ここの理解は諦めて RSA 暗号使ってるんだなということだけ把握して、 e
と n
から公開鍵を生成する。
注意点として、alg
を none
に改ざんして検証を回避されないように脆弱性対応が必要。
Payload の暗号化 署名セクションの復号化
取得した公開鍵で、ヘッダーと Payload を暗号化する。
この値が、JWT の署名セクションと同じになるかを検証する。
非対称鍵だから、上記の方法ではなさそう。
勘違いしてたかもなので、再整理。
署名セクションを復号化する。
正確には「秘密鍵」で暗号化したものを「公開鍵」で復号化することはできないがニュアンスとしてはこうなるっぽい。
復号化した内容が、ヘッダーと Paload と同じであるか確認して、改ざんされてないかチェックを行う。
クレームを検証する
トークンの有効期限確認
JWT の Payload の exp
Claim に入ってる値が未来かどうかチェック。
iat
Claim を確認して、発行時間が改ざんされてないかも見たほうが良さそう。
対象者 (aud) のクレームの確認
aud
Claim が、Client ID と同一かチェック。
発行者 (iss) のクレームの確認
以下の値と同一かチェック。
Cognito : `https://cognito-idp.<リージョン>.amazonaws.com/<userpoolID>` Auth0 : `https://<Auth0テナント>.auth0.com/`
以上
この検証がすべて問題なければ、認証済みとみなす。
実際には、自分で実装することはほぼなく、SDK など公開されているサンプルを使うことのほうが多いと思います。
オーソライザーサンプル
Auth0 公式を参考に確認しました。