JSON Web トークン(JWT)とは何ですか?
5 分で JSON Web トークン(JWT)の基本を明確に理解しましょう。
JSON Web トークン(JWT)は、現代のウェブアプリケーションや OpenID Connect などのオープンスタンダードで広く使用されており、認証と認可を容易にします。公式の RFC 7519 は重要な参照資料ではありますが、初心者にとっては理解するのが難しいかもしれません。この記事では、JWT の核心的なコンセプトに焦点を当て、例を用いてわかりやすい言葉で説明します。
なぜ JWT が必要なのですか?
今日では、2 つのパーティ間でデータを交換する際に JSON を使用するのは非常に一般的です。ユーザを表す JSON オブジェクトを考えてみましょう:
sub
は "subject" の略で、OpenID Connect の 標準クレーム で、ユーザ識別子(ユーザ ID)を表します。
この JSON オブジェクトの 完全性 をどのように保証できるでしょうか?つまり、データが送信中に改ざんされていないことをどのように確認できるでしょうか?一般的な解決策はデジタル署名を使用することです。例えば、公開鍵暗号化を使用して、サーバが JSON オブジェクトにプライベートキーを使用して署名し、クライアントがサーバの公開鍵で署名を検証できます。
要約すると、JWT は JSON オブジェクトとその署名を表す標準化されたアプローチを提供します。
JWT の形式
デジタル署名を作成するためのアルゴリズムが多数存在するため、JWT の署名に使用されるアルゴリズムを明示する必要があります。これは、JSON オブジェクトを構築することで達成されます:
alg
は "algorithm" の略語で、typ
は "type" の略語です。
一般的に、typ
は大文字の JWT
に設定されます。例示によれば、alg
は HS256
を表し、HMAC-SHA256 を意味します(これについてはすぐに説明します)。これは、署名を作成するためのこのアルゴリズムを使用していることを示しています。
次に、JWT を作成するためのすべての要素を紹介します:
- ヘッダー JSON:アルゴリズムとタイプ
- ペイロード JSON:実際のデータ
- 署名:ヘッダーとペイロードをまとめた署名
しかし、スペースや改行などの特定の文字はネットワーク送信に適していません。し たがって、ヘッダーとペイロードは Base64URL-エンコーディング される必要があります。一般的な JWT は次のようになります:
.
はデリミタとして機能します。
すべてをまとめて JWT を作成してみましょう:
ヘッダー
JSON:{"alg":"HS256","typ":"JWT"}
Base64URL エンコーディング:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
ペイロード
JSON:{"sub":"foo","name":"John Doe"}
Base64URL エンコーディング:eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
署名
HMAC-SHA256 では、署名はシークレットで作成されます:
例えば、シークレットが some-great-secret
であれば、署名は XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
になります。
JWT
最終的な JWT は次のようになります:
この有効な JWT は、シークレットを保持している任意のパーティによって検証できます。
署名アルゴリズムの選択
前述のように、デジタル署名を作成するためのさまざまなア ルゴリズムがあります。私たちは HS256
を例にしましたが、シークレットをパーティ間(例えば、クライアントとサーバ)で共有しなければならないため、強力さが不足しているかもしれません。
現実のシナリオでは、クライアントにはシークレットを安全に保管できない公開アプリケーション(React アプリなど)が含まれる可能性があります。その結果、JWT の署名に対する好ましいアプローチは、公開鍵暗号化(つまり、非対称暗号化)を利用することです。最も人気のあるアルゴリズムである RSA から始めましょう。
RSA
RSA は非対称アルゴリズムであり、公開鍵とプライベートキーという2つのキーを使用します。公開鍵は署名の検証に使用され、プライベートキーは署名の作成に使用されます。
RSA のヘッダー JSON は次のようになります:
RS256
は RSA-SHA256 を表し、これは RSA アルゴリズムと SHA256 ハッシュ関数で署名が作成されることを意味します。また、RS384
およびRS512
を使って、それぞれ SHA384 と SHA512 ハッシュ関数で署名を作成することもできます。
署名はプライベートキーで作成されます:
再び、これらの部品を組み立てて JWT を作成することができ、最終的な JWT は次のようになります:
今度は、クライアントがプライベートキーを知らなくても署名を検証できます 。
ECDSA
RSA は広く採用されていますが、署名のサイズが大きく、ヘッダーとペイロードの合計サイズを超えることがあります。Elliptic Curve Digital Signature Algorithm(ECDSA)は、さらにコンパクトな署名を作成でき、よりパフォーマンスが高い非対称アルゴリズムです。
ECDSA のプライベートキーを生成するためには、曲線を選択する必要があります。これはこの記事の範囲を超えていますが、詳細はここで見つけることができます。
ECDSA のヘッダー JSON は次のようになります:
ES256
は ECDSA-SHA256 を表し、これは ECDSA アルゴリズムと SHA256 ハッシュ関数で署名が作成されることを意味します。また、ES384
およびES512
を使って、それぞれ SHA384 と SHA512 ハッシュ関数で署名を作成することもできます。
署名はプライベートキーで作成されます:
最終的な JWT は RSA と同じ構造を保持しますが、署名が大幅に短くなります:
JWT の検証
JWT の検証は、JWT を作成する逆のプロセスであり、簡単です:
- JWT を
.
デリミタを使用して3つの部分(ヘッダー、ペイロード、署名)に分割します。 - ヘッダーとペイロードを Base64URL でデコードします。
- ヘッダーで指 定されたアルゴリズムと公開鍵(非対称アルゴリズムの場合)を使用して署名を検証します。
JWT の検証を支援するための様々なライブラリがあります。たとえば、Node.js とウェブブラウザ用の jose などがあります。
結論
本稿では、JWT の核心的な概念を簡単に説明し、それを作成して検証する方法について概説しました。詳細な部分は未探索のままであり、これらは今後の記事でカバーする予定です。
Logto は、JWT や OpenID Connect などのオープンスタンダードを利用し、すべての開発者にとってシンプルなワークフローでアプリと API を保護します。興味があれば、無料で試してみてください(クレジットカードは不要です)。