トークンの中身
JWTはピリオドで区切られた3つの部分でできています。前の2つはBase64urlでエンコードされたJSONなので誰でも読めます。3つ目が署名です。
- ヘッダー — 署名アルゴリズム(
alg)と種別(typ)が入ります。鍵を複数まわすサービスでは、どの鍵で署名したかを示すkidも付きます。 - ペイロード — クレームが入ります。
subは利用者の識別子、issは発行者、audはこのトークンの想定受け手、exp・iat・nbfは時刻です。 - 署名 — 前の2つを鍵で署名した値です。
時刻のクレームは秒単位の整数だと仕様で決まっています。ミリ秒を入れたトークンはこのツールで数千年先に見えますが、それは発行側の不具合です。
デコードと検証は別物です
ここで中身が読めたことは、そのトークンが本物だという意味ではありません。ペイロードは施錠されていないので誰でも書き換えられますし、署名が合わないことに気づけるのは鍵を持つ側だけです。
だからサーバーはリクエストごとに署名を検証しなければなりません。そのとき、ヘッダーの alg をそのまま信用してはいけません。検証に使うアルゴリズムはサーバー側で固定し、alg が none だったり想定と違ったりすれば拒否します。ヘッダーの指定に従う実装は、署名のないトークンを通してしまう典型的な穴になります。
ペイロードに秘密を入れないでください
トークンを持っている人なら、ブラウザの開発者ツールを開くだけでペイロードを読めます。マイナンバーや社内の管理メモ、決済情報が入っていれば、それはもう公開されたも同然です。
入れてよいのは、利用者IDや権限名、有効期限のように、相手に見られても困らない値だけです。それ以外はサーバーに置き、必要なときに引きます。
他人のトークンを貼る前に
このツールはトークンをどこにも送信しません。ただし有効期限の残ったトークンは、それ自体がログイン資格そのものです。チャットや課題管理システムに貼れば、その時点で読んだ人が使えてしまいます。誤って共有したら、期限切れを待たずにそのセッションを無効化してください。