「読める」ことと「信用してよい」ことは別だ、という点がすべてです。
JWT(JSON Web Token)は、認証情報を1本の文字列にまとめて受け渡すための形式です。暗号化されていません。誰でもデコードして中身を読めます。
だから重要なのは2点です。第一に、秘密にしたい情報をJWTに入れてはいけません。第二に、受け取ったJWTは署名を検証してから信用する必要があります。
読めることと、改ざんされていないことは別の話です。
JWTは xxxxx.yyyyy.zzzzz のように、ピリオドで区切られた3つの部分からできています。
| 部分 | 名前 | 中身 |
|---|---|---|
| 1つ目 | ヘッダー | 署名アルゴリズム(alg)とトークンの種類(typ) |
| 2つ目 | ペイロード | ユーザーIDや有効期限などの情報(クレーム) |
| 3つ目 | 署名 | ヘッダーとペイロードが改ざんされていないことを示す値 |
1つ目と2つ目はBase64URLでエンコードされているだけです。暗号化ではないので、デコードすれば誰でも読めます。Base64を手動で戻しても読めますし、JWTデコードを使えば3つを一度に展開できます。
ペイロードに入る項目をクレームと呼びます。標準的に決まっているものがいくつかあります。
デバッグでいちばんよく見るのは exp です。「ログインできない」の原因が単なる期限切れだった、というのはよくあります。まず期限を確認する癖をつけると、調査が速くなります。
ここが最も誤解されやすい点です。
デコードしただけのペイロードを信用して処理を進めると、誰でも中身を書き換えたトークンを作れてしまいます。「管理者フラグを true にしたペイロードを自分で作って送る」といった攻撃が成立します。
サーバー側では必ず署名を検証してから中身を使ってください。
逆に、ブラウザ側で有効期限を見て画面表示を切り替える、といった用途ならデコードだけでも構いません。セキュリティ上の判断に使うかどうかが境目です。
ログイン状態の保持には、大きく2つの方式があります。JWTを使う方式と、サーバー側にセッションを持つ方式です。どちらが優れているということはなく、性質が違います。
| JWT | サーバーセッション | |
|---|---|---|
| 状態の置き場所 | トークンの中(クライアント側) | サーバー側 |
| サーバーを増やしたとき | そのまま動く | 共有の仕組みが要る |
| 即時失効 | 難しい | 容易 |
| 情報を変えたとき | 再発行するまで古いまま | すぐ反映される |
サーバーを複数台に分散する構成ではJWTが扱いやすく、ログアウトや権限変更を即座に反映したい要件が強い場合はセッションのほうが素直です。
要件から選ぶのであって、新しいほうが良いという話ではありません。
実務では両者を組み合わせる形もよく使われます。短命なJWTを発行し、それを更新するための別のトークンをサーバー側で管理する構成です。この形なら、分散のしやすさと失効のしやすさをある程度両立できます。
こでっとのJWTデコードは、トークンを貼り付けるとヘッダーとペイロードを整形して表示します。すべてブラウザ内で処理され、貼り付けたトークンが外部に送信されることはありません。本番のトークンを扱う場面では、この点が重要になります。
有効期限を日時に直すならUnix時間変換。Base64そのものを個別に扱いたい場合は、同じ かわたれ studio のBase64変換が使えます。
いいえ、暗号化されていません。ヘッダーとペイロードはBase64URLでエンコードされているだけなので、誰でもデコードして読めます。署名は改ざんを検知するためのもので、中身を隠すものではありません。秘密にしたい情報をJWTに入れないでください。
デコードは中身を読むだけの作業で、鍵は不要です。検証は署名を使って改ざんされていないことを確かめる作業で、鍵が必要です。サーバー側でセキュリティ上の判断に使う場合は、必ず検証してから中身を使ってください。デコードした値をそのまま信用すると、偽造されたトークンを受け入れてしまいます。
まずトークンをデコードして exp(有効期限)を確認してください。単なる期限切れであることが多くあります。次に aud や iss が想定どおりか、ヘッダーの alg がサーバーの期待と一致しているかを見ます。サーバーの時計がずれていて期限切れと判定されるケースもあります。
こでっとのJWTデコードはすべてブラウザ内で処理し、入力したトークンを外部に送信しません。ただし一般論として、本番環境の有効なトークンをオンラインのツールに貼り付けるのは避けるべきです。処理がどこで行われるかを確認してから使ってください。