より詳しくJSON Web Token (JWT) を知るには?「JWTハンドブック」をダウンロード
より詳しくJSON Web Token (JWT) を知るには?「JWTハンドブック」をダウンロード

JSON Web Tokenの概要

レベルアップ!JWTハンドブックを無料で入手して、JWTへの理解を深めましょう!

JSON Web Tokenとは?

JSON Web Token (JWT) は標準規格(RFC 7519)で定義されています。この仕様は認証、認可の情報をJSON形式でシステム間で安全にやりとりする際に使用できる、コンパクトで自己完結型のフォーマットを定義しています。デジタル署名を付与することもできるため、検証可能で信頼がおけます。JWTへの署名には共通鍵を使用するHMACアルゴリズムあるいは、公開鍵/秘密鍵ペアを使用するRSAまたはECDSAアルゴリズムを使用できます。

JWTは機密性を保つために暗号化することもできますが、ここでは 署名されたJWT に焦点を当てます。署名されたJWTは完全性を検証でき、暗号化されたトークンは内容を他者から隠すことができます。JWTが秘密鍵を用いて署名された場合、その署名は公開鍵を使うことで、秘密鍵を持つ当事者だけがそのJWTに署名した者であることが確認できます。

JSON Web Tokenはいつ使用すべきか?

JSON Web Tokenが役立つシナリオをいくつかご紹介します。

  • 認証および認可: JWTを使用する最も一般的な利用用途です。ユーザーがログインすると、その後の各リクエストにはJWTが含まれ、ユーザーはそのJWTで許可されたエンドポイント、リソースにアクセスできます。オーバーヘッドが小さく、異なるドメインのシステム間で簡単に使用できるため、シングルサインオンやSPAやモバイルアプリケーション、APIの呼び出しなどでJWTが使用されています。
  • 情報交換: JSON Web Tokenは、システム間で認証や認可の情報を安全にやりとりする際に優れた形式です。JWTには署名できるため、例えば公開鍵/秘密鍵のペアを使用して、送信者が本人であることを確認できます。さらに、署名はヘッダーとペイロードを使って計算して作成されるため、コンテンツが改ざんされていないことも確認できます。

JSON Web Tokenの構成は?

JSON Web Tokenはコンパクトな形態で、ドット(.)で区切られた以下の3つの部分で構成されます。

  • ヘッダー
  • ペイロード
  • 署名

したがって、JWTは一般的に以下のように示されます。

xxxxx.yyyyy.zzzzz

これらの構成部分を見ていきましょう。

ヘッダー

ヘッダーは通常、JWTであるタイプと、HMACとSHA256の組み合わせ(HS256)やRSAとSHA256の組み合わせ(RS256)などのハッシュアルゴリズムの2つの項目で構成されています。

例:

{
  "alg": "HS256",
  "typ": "JWT"
}

その後、このJSONはBase64Url形式でエンコードされ、JWTの最初の部分を形成します。

ペイロード

2番目の部分は、クレームを含むペイロードです。クレームは、エンティティ (通常はユーザー) と追加のメタデータに関する情報です。 クレームには予約済み、パブリック、プライベートの3種類があります。

  • 予約済みのクレーム: 標準規格で定義されているクレームです。必須ではありませんが、相互運用可能なクレームを使用でき、利便性も高いため使用が推奨されています。その中には、iss(発行者)、exp(有効期限)、sub(サブジェクト)、aud(オーディエンス)、その他のクレームなどがあります。

クレーム名がわずか3文字ですが、これはJWTがコンパクトであることを目的としているためです。

  • パブリッククレーム: JWTを使用するユーザーは、これを自由に定義できます。しかし、衝突を回避するにはIANA JSON Web Token (JWT) レジストリで登録するか、衝突に強い名前空間を含むURIとして定義する必要があります。
  • プライベートクレーム: これらのカスタムクレームは、その使用に同意したパーティ間での情報共有を可能にするものであり、予約済みのクレーム、あるいはパブリックのクレームではありません。

以下はペイロードの例です。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

その後、ペイロードはBase64Url形式でエンコードされ、JSON Web Tokenの2番目の部分を形成します。

署名付きトークンの場合でも、改ざんを防いではいますが、この情報は誰でも読むことができることに注意してください。暗号化しない限り、JWTのペイロードやヘッダー要素に機密性のある情報を入れないようにしてください。

署名

署名部分を作成するには、エンコードされたヘッダー、エンコードされたペイロード、シークレット、ヘッダーで指定されたアルゴリズムを使用して署名を行います。

たとえば、HMAC SHA256アルゴリズムを使用する場合、署名は次のように生成されます。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

署名はメッセージが途中で変更されていないことを検証するために使用されます。秘密鍵で署名されたトークンは、JWTの送信元が正しくそのシステムであることを検証できます。

すべてを組み合わせる

出力はドットで区切られた3つのBase64Url形式の文字列であり、HTMLやHTTP環境で簡単に使用できます。また、SAMLのようなXMLベースの標準と比べて、よりコンパクトです。

以下は、先ほどのヘッダーとペイロードをエンコードし、シークレットで署名したJWTの例です。

エンコードされたJWT

JWTを操作してこれらの概念を実際に試したい場合は、jwt.ioデバッガーを使用してJWTのデコード、検証、生成を実行できます。

jwt.ioデバッガー

JSON Web Tokenの仕組みとは?

認証では、ユーザーが資格情報を使用して正常にログインすると、JSON Web Token (JWT)が返されます。トークンは資格情報であるため、セキュリティの問題が起きないように細心の注意を払う必要があります。一般的に、トークンは必要以上に長く保持するべきではありません。

保護されたエンドポイントにユーザーがアクセスしたい場合、ブラウザなどのクライアントはJWTを送信する必要があります。通常は、Bearerスキーマを使用してAuthorizationヘッダーで送信します。したがって、ヘッダーの内容は次のようになります。

Authorization: Bearer <token>

これはステートレスな認証メカニズムになります。サーバーの保護されたエンドポイントは、Authorizationヘッダーに有効なJWTがあるかどうかを確認し、存在した場合には、ユーザーは保護されたリソースへのアクセスを許可されます。JWTにリクエストされた操作に必要なユーザーについてのデータが含まれていれば、データベースへの問い合わせを減らせる可能性があります。ただし、必ずしもそうなるとは限りません。

JWTトークンをHTTPヘッダーで送信する場合は、トークンのサイズが大きくなりすぎないようにする必要があります。サーバーによっては、8KB以上のヘッダーを受け付けないものもあります。例えばユーザーの権限を管理する場合は、トークンに権限情報を集中させるのではなく、Auth0 Fine-Grained Authorizationのようなソリューションの利用も検討できます。

以下の図は、JWTが取得され、APIやリソースへのアクセスに使用される流れを示しています。

JSON Web Tokenの仕組み
  1. アプリケーションまたはクライアントは、認可サーバに認可を要求します。これは、幾つかの認可フローのいずれかを通じて実行されます。例えば、典型的なOpenID Connect準拠のウェブアプリケーションは、認可コードフローを使って「/oauth/authorize」エンドポイントにアクセスします。
  2. 認可が行われると、認可コードがウェブアプリケーションに渡され、ウェブアプリケーションはこの認可コードを使用し「/oauth/token」エンドポイントに対してアクセストークンをリクエストします。認可サーバーはアクセストークンをアプリケーションに返します。
  3. アプリケーションはアクセストークンを使って(APIのような)保護されたリソースにアクセスします。

署名付きトークンの場合、トークンに含まれるすべての情報は、ユーザーやアクセスを許可をしているサードパーティーに公開されます。その情報が変更されることはありませんが、トークンの中にユーザやサードパーティに知られたくないような機密情報を入れないようにご注意して下さい。

JSON Web Tokenを使用すべき理由とは?

JSON Web Token (JWT) の利点について、Simple Web Token (SWT) および XML を使用する Security Assertion Markup Language Token (SAML) と比較してみましょう。

JSONはXMLよりも冗長でないため、エンコード後のサイズも小さくなり、JWTはSAMLよりもコンパクトになります。このため、JWTはHTMLやHTTPの環境に適した選択肢となります。

セキュリティ上の観点でいうと、SWTは共通鍵を使用するHMACアルゴリズムによってのみ署名できます。SAMLでは公開鍵/秘密鍵のペアを使用する複数のアルゴリズムから選択して署名できます。しかし、セキュリティホールを発生させずに、XMLデジタル署名を使用してXMLに署名することは、JWTへの署名のシンプルさに比べて非常に複雑です。

JSONパーサーは、オブジェクトに直接マッピングできるため、ほとんどのプログラミング言語において一般的になっています。しかし、SAMLで使用されるXMLにはドキュメントからオブジェクトへの自然なマッピングはできません。そのため、JWTを使用する方が、SAMLよりも簡単です。

利用実績についていうと、JWTはインターネット規模で使われています。これは複数のプラットフォーム、特にモバイルでのJWTのクライアント側処理の容易さを表しています。

エンコードされたJWTとエンコードされたSAMLの長さの比較

エンコードされたJWTとエンコードされたSAMLの長さの比較

JSON Web Tokenの詳細や、JSON Web Tokenを使用したアプリケーションの認証については、Auth0のJSON Web Tokenランディングページをご覧ください。

JWTのバリデーション(妥当性確認)とベリフィケーション(検証)の違い

JSON Web Token(JWT)のバリデーション(妥当性確認)とベリフィケーション(検証)はセキュリティ上非常に重要ですが、JWTセキュリティの異なる側面に対応しています。バリデーションはトークンが適切に構成され、強制可能なクレームを含んでいることを確認します。ベリフィケーションはトークンが真正で、変更されていないことを確認します。

バリデーションとベリフィケーションの違いについて、さらに詳しく見てみましょう。

JWTのバリデーションとは一般的に、JWTの構造、フォーマット、およびコンテンツの確認を指します。

  • 構造: トークンが標準の3つの部分(ヘッダー、ペイロード、署名)をドットで区切って構成されていることを確認します。
  • フォーマット: 各部分が正しくエンコード(Base64URL)されていること、およびペイロードが期待されるクレームを含んでいることを確認します。
  • コンテンツ: 有効期限(exp)、発行日時(iat)、有効期限以前の日時(nbf)など、ペイロード内のクレームが正しいかどうかを確認し、トークンが期限切れになっていないこと、有効期限以前に使用されていないことなどを確認します。

一方、JWTのベリフィケーションでは、トークンの真正性と完全性を検証します。

  • 署名の検証: これは検証の主な側面であり、JWTの署名部分をヘッダーとペイロードと照合します。これは、秘密鍵または公開鍵を使用して、ヘッダーで指定されたアルゴリズム(HMAC、RSA、ECDSAなど)を使用して行われます。署名が期待されるものと一致しない場合、トークンが改ざんされているか、信頼できるソースからのものではない可能性があります。
  • 発行者検証: issクレームが期待される発行者に一致しているかを検証します。
  • オーディエンスチェック: audクレームが期待されるオーディエンスに一致していることを検証します。

実運用の観点:

バリデーションでは、JWTが妥当であり、期待される標準に準拠し、正しいデータを含んでいることを確認します。

ベリフィケーションでは、JWTが悪意を持って改ざんされていないこと、および信頼できるソースから発行されていることを検証します。

多くのシステムでは、これらの手順は、包括的なセキュリティチェックにおける妥当性の確認と検証の両方を包含する「JWT検証」と呼ばれるものにまとめられることが多々ありますが、両者の区別は存在します。

JWTのデコーディングとエンコーディングの違い

JWTのエンコーディングでは、ヘッダーとペイロードをコンパクトでURLに適した形式に変換します。署名アルゴリズムとトークンタイプを記載するヘッダーと、サブジェクト、有効期限、発行時間などのクレームを含むペイロードの両方をJSONに変換しBase64URLエンコードします。これらのエンコードされた部分は、ドット(.)で連結され、その後、ヘッダーで指定されたアルゴリズムを使用して、シークレットキーまたはプライベートキーで署名が生成されます。この署名もBase64URLエンコードされ、送信や保存に適した形式でトークンを表す最終的なJWT文字列が生成されます。

JWTのデコーディングでは、このプロセスを逆に行い、Base64URLエンコードされたヘッダーとペイロードを再びJSONに変換します。この段階ではキーを必要とせずに誰でもヘッダーおよびペイロードの情報を読み取れます。しかし、この文脈における「デコーディング」は、多くの場合、トークンの署名検証を含んでいます。この検証(ベリフィケーション)ステップでは、エンコーディングに使用したのと同じアルゴリズムとキーを使用し、デコードされたヘッダーとペイロードを再度署名します。新しい署名を元々のJWTに含まれる署名と比較し、両者が一致することでトークンの完全性と真正性が確認され、発行後に改ざんされていないことが保証されます。

JSON Web Tokenの使用を開始

どのスタックやデバイスでも、Auth0でJWTを使った安全な認証を10分以内で実装できます。

無料アカウントを作成