omuronの備忘録

個人的な備忘録

Auth0 と Cognito で JWT 検証を理解する

Cognito や Auth0 で、認証時に JWT の検証を行いますが、実際に何をしているかちゃんと理解できてません。 以前書いた Lambda オーソライザーで Auth0 のトークンを検証する で検証をすることはできました。 理解できなくても、SDK とかを利用して処理ができるのは、抽象化がちゃんとされている証拠ではあります。 改めて何をしているか少し確認してみます。

どうやって検証している?

さすが AWS 、良いドキュメントがありました。

docs.aws.amazon.com

理解したいのは「ステップ 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.jsonkid が同じかチェック。
alg =RS256 が使われているので、ne をデコードした数値を使えば 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 暗号使ってるんだなということだけ把握して、 en から公開鍵を生成する。

注意点として、algnone に改ざんして検証を回避されないように脆弱性対応が必要。

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 公式を参考に確認しました。

github.com