2025.04.26
JWTの仕組み
JWTとは
JWTとはHTTPヘッダーやクエリパラメータなどにJSONデータを載せられるようにしたものです。 つまりスペースに制約のある場所に、URLセーフでデータを小さくするためのJSONのフォーマットです。
JSONデータをbase64urlエンコードしま、同時にキー名を短くしてJSONデータをコンパクトにしています。 予約された省略名としてiss, sub, exp, iatなどがあります。
JSONのキーと値のペアはJWTではclaimと呼びます。
ちなみに読み方は、IETF ToolsのJWTに関する記事では、
The suggested pronunciation of JWT is the same as the English word "jot".
と書かれています。ジョットと発音するそうです。
セキュリティの仕組み
JWTはデコードすると中身が見えてしまうので、JSON Web Signature(JWS)という仕組みがあります。改ざんされるかもしれないのでJWTが本物かどうかを確認する仕組みです。
JWT自体を暗号化して中身を見られないようにする仕組みとしてはJSON Web Encryption(JWE)があります。
JWSの署名
改ざん防止で使うのは暗号鍵を使ったデータの署名です。
JWSはヘッダー、ペイロード、シグニチャの3つで構成されます。 ヘッダーにはJWTであることを書く'typ'と、どのアルゴリズムで署名(暗号化)したかを書く'alg'というキーがあります。
手順
- ペイロードをbase64urlエンコードする
- ヘッダーをbase64urlエンコードする
- 1と2を
.
で繋ぐ - 3の結果を暗号鍵とalgに指定された方式で署名し、その結果をさらにbase64urlエンコードする
- 3と4を
.
で繋ぐ(これをJWSコンパクトシリアライゼーションという)
4で生成されたシグニチャは暗号化された1と2と同じ内容になっているので、シグニチャを復号化したときに1と2と全く同じ文字列になるはずということです。
JWSの検証
1と2を繋いだものは暗号化されているわけではないのでbase64デコードされると中身が見えてしまいます。しかしJWSは盗聴を防ぐためのものではないので中身が見られてしまっても許容します。
問題はペイロードを書き換えられたときです。悪意を持った人が、別のデータをbase64urlエンコードしたものを1と2の代わりにくっつけてしまえば改ざんができてしまうため、JWTでは値の検証が大事です。
JWSでは前提として、暗号鍵は信頼している相手しか持っておらず、暗号化した内容は同じ暗号鍵を持っている人しか同じ内容に復号化できず、相手と同じ暗号鍵でシグニチャを復号化すると暗号化する前と同じ内容になっているはず、という仕組みで成り立っています。
JWSではシグニチャを復号化した結果とヘッダーとペイロードを比較することで改ざんされていないかを検証します。
ちなみに一般的にはデータ量を少なくするため、データをbase64urlエンコードした文字列ではなく、その文字列に対するハッシュ値を暗号化しています。 しかし、それを復号化してもハッシュ値は不可逆なので1と2はもちろん取り出せないので、実際には1と2をハッシュ化したものを比較しています。
ちなみにちなみにjwt.ioというサイトでJWSの中身を見れて楽しいです。デバッグもしやすい。
JWTによる認証
IDとパスワードの組み合わせで認証するところを、アプリケーションが発行した認証情報のJWTを提示し、そのJWTがアプリと取り交わした鍵情報で検証することで本人だと確認します。
流れとしては、
- ユーザーがgoogleなどでログインする
- googleのプロバイダーがjwsをユーザーに返す
- 返ってきたjwsをアプリケーションに送りつける
- アプリケーションは受け取ったjwsをgoogleに投げて検証する
- 検証した結果、本人だということがわかったらユーザーのデータを送ってあげる
ちなみにこの作業をIDフェデレーションと呼び、ここでやりとりされる認証情報付きのjwtをIDトークンと呼びます。
JWTを認証に使うメリットとしては検証の仕組みはGoogleなどに任せることでアプリケーションはユーザーのパスワードを持たなくて済むため、パスワードが漏洩してなんやかんやということを防げます。
参考
- https://developer.mamezou-tech.com/blogs/2022/12/08/jwt-auth/
- https://www.okta.com/jp/identity-101/what-is-token-based-authentication/
- https://qiita.com/knaot0/items/8427918564400968bd2b
- https://apidog.com/jp/blog/json-web-token/
- https://jwt.io/#debugger-io