42
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Wikipedia の JWT (JSON Web Token) に関する記事が誤っていたので、2020 年 5 月 9 日、英語版日本語版ともに修正を行いました。

wikipedia_jwt_revision.en.png

wikipedia_jwt_revision.ja.png

修正前の記事では、JWT のことを「JSON をベースとしたアクセストークンのためのオープン標準である」と説明していました。しかし JWT は用途を限定しない汎用的なデータフォーマットです。アクセストークンのフォーマットとして JWT を採用することは、JWT の応用事例の一つに過ぎません。なお、アクセストークンのフォーマットは必ずしも JWT とは限りません。→ 参考:『図解 JWS/JWE/JWT/IDトークン/アクセストークンの包含関係

JWT を知らない状態で OAuthOpenID Connect の学習を始めると、「JWT はアクセストークンのための技術である」、「JWT はユーザ認証のための技術である」といった誤解をしてしまうことが多いようです。これは、初めて触れた認可サーバのアクセストークンの実装がたまたま JWT であったり、初めて知った JWT の応用事例が ID トークンであったりすることが原因だと思われます。

この記事では OAuth と OpenID Connect の分野における JWT の様々な利用例を紹介します。同分野の知識を広げるとともに、JWT が用途を限定しない汎用フォーマットであることを改めて確認していきましょう。

ID トークン

OpenID Connect Core 1.0 (以降 OIDC Core) という標準仕様があります。これは遅くとも 2010 年代前半から存在する仕様であり、2024 年 10 月には ISO/IEC 26131:2024 としても承認されました。

この仕様の Section 2. ID Token で、ID トークンが定義されています。当仕様に "The ID Token is represented as a JSON Web Token (JWT)" と明記されている通り、ID トークンは JWT の一種です。

JWT の仕様は、IETF (Internet Engineering Task Force) が承認した RFC 7519: JSON Web Token (JWT) という文書で定義されています。

JWT は、特定の条件を満たした JWS (JSON Web Signature) または JWE (JSON Web Encryption) です。JWS と JWE の仕様はそれぞれ、RFC 7515: JSON Web Signature (JWS)RFC 7516: JSON Web Encryption (JWE) という文書で定義されています。

下図は『図解 JWS/JWE/JWT/IDトークン/アクセストークンの包含関係』という記事からの転載で、JWS、JWE、JWT、IDトークンの包含関係を示しています。

Inclusion_Relation_JWS_JWE_JWT_IDToken.png

ID トークンの例
ID トークン
eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwczovL3NlcnZlci5leGFtcGxlLmNvbSIsCiAic3ViIjogIjI0ODI4OTc2MTAwMSIsCiAiYXVkIjogInM2QmhkUmtxdDMiLAogIm5vbmNlIjogIm4tMFM2X1d6QTJNaiIsCiAiZXhwIjogMTMxMTI4MTk3MCwKICJpYXQiOiAxMzExMjgwOTcwLAogIm5hbWUiOiAiSmFuZSBEb2UiLAogImdpdmVuX25hbWUiOiAiSmFuZSIsCiAiZmFtaWx5X25hbWUiOiAiRG9lIiwKICJnZW5kZXIiOiAiZmVtYWxlIiwKICJiaXJ0aGRhdGUiOiAiMDAwMC0xMC0zMSIsCiAiZW1haWwiOiAiamFuZWRvZUBleGFtcGxlLmNvbSIsCiAicGljdHVyZSI6ICJodHRwOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGciCn0.NTibBYW_ZoNHGm4ZrWCqYA9oJaxr1AVrJCze6FEcac4t_EOQiJFbD2nVEPkUXPuMshKjjTn7ESLIFUnfHq8UKTGibIC8uqrBgQAcUQFMeWeg-PkLvDTHk43Dn4_aNrxhmWwMNQfkjqx3wd2Fvta9j8yG2Qn790Gwb5psGcmBhqMJUUnFrGpyxQDhFIzzodmPokM7tnUxBNj-JuES_4CE-BvZICH4jKLp0TMu-WQsVst0ss-vY2RPdU1MzL59mq_eKk8Rv9XhxIr3WteA2ZlrgVyT0cwH3hlCnRUsLfHtIEb8k1Y_WaqKUu3DaKPxqRi6u0rN7RO2uZYPzC454xe-mg&state=af0ifjsldkj
ヘッダ
{
  "kid": "1e9gdk7",
  "alg": "RS256"
}
ペイロード
{
  "iss": "https://server.example.com",
  "sub": "248289761001",
  "aud": "s6BhdRkqt3",
  "nonce": "n-0S6_WzA2Mj",
  "exp": 1311281970,
  "iat": 1311280970,
  "name": "Jane Doe",
  "given_name": "Jane",
  "family_name": "Doe",
  "gender": "female",
  "birthdate": "0000-10-31",
  "email": "janedoe@example.com",
  "picture": "http://example.com/janedoe/me.jpg"
}

関連情報

リクエストオブジェクト

OIDC Core の Section 6. Passing Request Parameters as JWTs では、認可リクエストのパラメータ群を一つの JWT にまとめる方法が定義されています。この JWT のことをリクエストオブジェクトと呼びます。

OIDC Core の Section 6 で定義されたリクエストオブジェクトですが、その後、若干の破壊的変更を加えて RFC 9101: The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR) という独立した仕様に切り出されました。

リクエストオブジェクトを使うと、次のような複数のリクエストパラメータ群が

authorization-request.png

一つの JWT にまとめられ、request というリクエストパラメータの値として指定されます。

authorization-request+request_ja.png

リクエストオブジェクトの例
リクエストオブジェクト
eyJhbGciOiJSUzI1NiIsImtpZCI6ImsyYmRjIn0.ewogICAgImlzcyI6ICJzNkJoZFJrcXQzIiwKICAgICJhdWQiOiAiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLAogICAgInJlc3BvbnNlX3R5cGUiOiAiY29kZSBpZF90b2tlbiIsCiAgICAiY2xpZW50X2lkIjogInM2QmhkUmtxdDMiLAogICAgInJlZGlyZWN0X3VyaSI6ICJodHRwczovL2NsaWVudC5leGFtcGxlLm9yZy9jYiIsCiAgICAic2NvcGUiOiAib3BlbmlkIiwKICAgICJzdGF0ZSI6ICJhZjBpZmpzbGRraiIsCiAgICAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICAgICJtYXhfYWdlIjogODY0MDAKfQ.Nsxa_18VUElVaPjqW_ToI1yrEJ67BgKb5xsuZRVqzGkfKrOIX7BCx0biSxYGmjK9KJPctH1OC0iQJwXu5YVY-vnW0_PLJb1C2HG-ztVzcnKZC2gE4i0vgQcpkUOCpW3SEYXnyWnKzuKzqSb1wAZALo5f89B_p6QA6j6JwBSRvdVsDPdulW8lKxGTbH82czCaQ50rLAg3EYLYaCb4ik4I1zGXE4fvim9FIMs8OCMmzwIB5S-ujFfzwFjoyuPEV4hJnoVUmXR_W9typPf846lGwA8h9G9oNTIuX8Ft2jfpnZdFmLg3_wr3Wa5q3a-lfbgF3S9H_8nN3j1i7tLR_5Nz-g
ヘッダ
{
  "alg": "RS256",
  "kid": "k2bdc"
}
ペイロード
{
  "iss": "s6BhdRkqt3",
  "aud": "https://server.example.com",
  "response_type": "code id_token",
  "client_id": "s6BhdRkqt3",
  "redirect_uri": "https://client.example.org/cb",
  "scope": "openid",
  "state": "af0ifjsldkj",
  "nonce": "n-0S6_WzA2Mj",
  "max_age": 86400
}

JWT を使うことで、「クライアントからリクエストが送信されて認可サーバに届くまでの間にリクエストパラメータ群が改竄されていない」こと及び「意図したクライアントからのリクエストである」ことを認可サーバが確認できます。この特性はセキュリティ上重要であり、英国オーブンバンキングやブラジルオープンファイナンスなどの世界各国の API エコシステムではリクエストオブジェクトの使用が必須とされています。

【改竄検出】 データを少しでも改竄すると JWT の署名が無効になるので、改竄を検出できます。

【否認防止】 署名者の公開鍵を使って JWT の署名検証に成功した場合、その JWT は署名者の秘密鍵を使って署名されたことが証明されます。秘密鍵は署名者しか持っていないので、当 JWT は当署名者によって生成されたことが保証されます。また、逆の見方をすると、当署名者は当 JWT を自分が生成したという事実を否定できません。

関連情報

CIBA リクエストオブジェクト

OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 (以降 CIBA Core) という標準仕様では、RFC 6749: The OAuth 2.0 Authorization Framework で定義されている OAuth の基本フロー群とは異なる新しいフローを定義しています。

CIBA.ja.png

CIBA フローには、POLL モード、PING モード、PUSH モードという三つのモードがあります。いずれのモードでも、CIBA フローはバックチャネル認証エンドポイントにバックチャネル認証リクエストを投げることから始まります。

ciba_poll.ja.png

このバックチャネル認証エンドポイントは CIBA Core の Section 7.1. Authentication Request で定義されているリクエストパラメータ群を受け取ることができます。

そして、CIBA Core の Section 7.1.1. Signed Authentication Request ではそれらのリクエストパラメータ群を一つの JWT にまとめて渡す方法が定義されています。認可エンドポイントにリクエストオブジェクトを渡す時に request リクエストパラメータを使ったのと同様に、バックチャネル認証リクエストのリクエストパラメータ群をまとめた JWT を渡すときも request リクエストパラメータを使います。

リクエストオブジェクトを含むバックチャネル認証リクエスト
POST /bc-authorize HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

request=eyJraWQiOiJsdGFjZXNidyIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJz
NkJoZFJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJl
eHAiOjE1Mzc4MjAwODYsImlhdCI6MTUzNzgxOTQ4NiwibmJmIjoxNTM3ODE4ODg2
LCJqdGkiOiI0TFRDcUFDQzJFU0M1QldDbk4zajU4RW5BIiwic2NvcGUiOiJvcGVu
aWQgZW1haWwgZXhhbXBsZS1zY29wZSIsImNsaWVudF9ub3RpZmljYXRpb25fdG9r
ZW4iOiI4ZDY3ZGM3OC03ZmFhLTRkNDEtYWFiZC02NzcwN2IzNzQyNTUiLCJiaW5k
aW5nX21lc3NhZ2UiOiJXNFNDVCIsImxvZ2luX2hpbnRfdG9rZW4iOiJleUpyYVdR
aU9pSnNkR0ZqWlhOaWR5SXNJbUZzWnlJNklrVlRNalUySW4wLmV5SnpkV0pmYVdR
aU9uc2labTl5YldGMElqb2ljR2h2Ym1VaUxDSndhRzl1WlNJNklpc3hNek13TWpn
eE9EQXdOQ0o5ZlEuR1NxeEpzRmJJeW9qZGZNQkR2M01PeUFwbENWaVZrd1FXenRo
Q1d1dTlfZ25LSXFFQ1ppbHdBTnQxSGZJaDN4M0pGamFFcS01TVpfQjNxZWIxMU5B
dmcifQ.ELJvZ2RfBl05bq7nx7pXhagzL9R75mUwO-yZScB1aT3mp480fCQ5KjRVD
womMMjiMKUI4sx8VrPgAZuTfsNSvA&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3A
client-assertion-type%3Ajwt-bearer&
client_assertion=eyJraWQiOiJsdGFjZXNidyIsImFsZyI6IkVTMjU2In0.eyJ
pc3MiOiJzNkJoZFJrcXQzIiwic3ViIjoiczZCaGRSa3F0MyIsImF1ZCI6Imh0dHB
zOi8vc2VydmVyLmV4YW1wbGUuY29tIiwianRpIjoiY2NfMVhzc3NmLTJpOG8yZ1B
6SUprMSIsImlhdCI6MTUzNzgxOTQ4NiwiZXhwIjoxNTM3ODE5Nzc3fQ.PWb_VMzU
IbD_aaO5xYpygnAlhRIjzoc6kxg4NixDuD1DVpkKVSBbBweqgbDLV-awkDtuWnyF
yUpHqg83AUV5TA
CIBA リクエストオブジェクトの例
CIBA リクエストオブジェクト
eyJraWQiOiJsdGFjZXNidyIsImFsZyI6IkVTMjU2In0.eyJpc3MiOiJzNkJoZFJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJleHAiOjE1Mzc4MjAwODYsImlhdCI6MTUzNzgxOTQ4NiwibmJmIjoxNTM3ODE4ODg2LCJqdGkiOiI0TFRDcUFDQzJFU0M1QldDbk4zajU4RW5BIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgZXhhbXBsZS1zY29wZSIsImNsaWVudF9ub3RpZmljYXRpb25fdG9rZW4iOiI4ZDY3ZGM3OC03ZmFhLTRkNDEtYWFiZC02NzcwN2IzNzQyNTUiLCJiaW5kaW5nX21lc3NhZ2UiOiJXNFNDVCIsImxvZ2luX2hpbnRfdG9rZW4iOiJleUpyYVdRaU9pSnNkR0ZqWlhOaWR5SXNJbUZzWnlJNklrVlRNalUySW4wLmV5SnpkV0pmYVdRaU9uc2labTl5YldGMElqb2ljR2h2Ym1VaUxDSndhRzl1WlNJNklpc3hNek13TWpneE9EQXdOQ0o5ZlEuR1NxeEpzRmJJeW9qZGZNQkR2M01PeUFwbENWaVZrd1FXenRoQ1d1dTlfZ25LSXFFQ1ppbHdBTnQxSGZJaDN4M0pGamFFcS01TVpfQjNxZWIxMU5BdmcifQ.ELJvZ2RfBl05bq7nx7pXhagzL9R75mUwO-yZScB1aT3mp480fCQ5KjRVDwomMMjiMKUI4sx8VrPgAZuTfsNSvA
ヘッダ
{
  "kid": "ltacesbw",
  "alg": "ES256"
}
ペイロード
{
  "iss": "s6BhdRkqt3",
  "aud": "https://server.example.com",
  "exp": 1537820086,
  "iat": 1537819486,
  "nbf": 1537818886,
  "jti": "4LTCqACC2ESC5BWCnN3j58EnA",
  "scope": "openid email example-scope",
  "client_notification_token": "8d67dc78-7faa-4d41-aabd-67707b374255",
  "binding_message": "W4SCT",
  "login_hint_token": "eyJraWQiOiJsdGFjZXNidyIsImFsZyI6IkVTMjU2In0.eyJzdWJfaWQiOnsiZm9ybWF0IjoicGhvbmUiLCJwaG9uZSI6IisxMzMwMjgxODAwNCJ9fQ.GSqxJsFbIyojdfMBDv3MOyAplCViVkwQWzthCWuu9_gnKIqECZilwANt1HfIh3x3JFjaEq-5MZ_B3qeb11NAvg"
}

CIBA はなじみが薄いかもしれませんが、SBI DigiTrust 社が提供する金融機関向け認証認可基盤サービス Trust Idiom など、日本においても商用環境で実運用されている実績があります。

関連情報

JARM

認可リクエストのパラメータ群をリクエストオブジェクトと呼ばれる一つの JWT にまとめるのと同様に、認可レスポンスのパラメータ群を一つの JWT にまとめるための標準仕様も存在します。それが JWT Secured Authorization Response Mode for OAuth 2.0 (JARM) です。

JARM を使うと、次のような複数のレスポンスパラメータ群が

JARM 未使用時の認可レスポンス
HTTP/1.1 302 Found
Location: https://client.example.com/cb?
  iss=https%3A%2F%2Faccounts.example.com&
  code=PyyFaux2o7Q0YfXBU32jhw.5FXSQpvr8akv9CeRDSd0QA&
  state=S8NJ7uqk5fY4EjNvP_G_FtyJu6pUsvH9jsYni9dMAJw

一つの JWT にまとめられ、response というレスポンスパラメータの値として返ってきます。

JARM 使用時の認可レスポンス
HTTP/1.1 302 Found
Location: https://client.example.com/cb?
  response=eyJraWQiOiJsYWViIiwiYWxnIjoiRVMyNTYifQ.eyAgImlzcyI6ICJodHRwczovL2F
  jY291bnRzLmV4YW1wbGUuY29tIiwgICJhdWQiOiAiczZCaGRSa3F0MyIsICAiZXhwIjogMTMxMT
  I4MTk3MCwgICJjb2RlIjogIlB5eUZhdXgybzdRMFlmWEJVMzJqaHcuNUZYU1FwdnI4YWt2OUNlU
  kRTZDBRQSIsICAic3RhdGUiOiAiUzhOSjd1cWs1Zlk0RWpOdlBfR19GdHlKdTZwVXN2SDlqc1lu
  aTlkTUFKdyJ9.4VdtknVZ9zFYDVLagJpVBD436bjPMcSgOaPDPFgTEkNyCs2uIHYJ2XML6d2w1A
  Usm5GBG77DBisZNhLWfug6dA
JARM の例
JARM
eyJraWQiOiJsYWViIiwiYWxnIjoiRVMyNTYifQ.eyAgImlzcyI6ICJodHRwczovL2FjY291bnRzLmV4YW1wbGUuY29tIiwgICJhdWQiOiAiczZCaGRSa3F0MyIsICAiZXhwIjogMTMxMTI4MTk3MCwgICJjb2RlIjogIlB5eUZhdXgybzdRMFlmWEJVMzJqaHcuNUZYU1FwdnI4YWt2OUNlUkRTZDBRQSIsICAic3RhdGUiOiAiUzhOSjd1cWs1Zlk0RWpOdlBfR19GdHlKdTZwVXN2SDlqc1luaTlkTUFKdyJ9.4VdtknVZ9zFYDVLagJpVBD436bjPMcSgOaPDPFgTEkNyCs2uIHYJ2XML6d2w1AUsm5GBG77DBisZNhLWfug6dA
ヘッダ
{
  "kid": "laeb",
  "alg": "ES256"
}
ペイロード
{
  "iss": "https://accounts.example.com",
  "aud": "s6BhdRkqt3",
  "exp": 1311281970,
  "code": "PyyFaux2o7Q0YfXBU32jhw.5FXSQpvr8akv9CeRDSd0QA",
  "state": "S8NJ7uqk5fY4EjNvP_G_FtyJu6pUsvH9jsYni9dMAJw"
}

認可レスポンスを JWT 化するように認可サーバに依頼するには、認可リクエストに response_mode=jwt というリクエストパラメータを追加します。詳細は JARM の仕様書をご参照ください。

関連情報

クライアントアサーション

OAuth クライアントアプリケーションのクライアントタイプがコンフィデンシャルの場合、トークンエンドポイントなど特定のエンドポイントでクライアント認証が要求されます。

クライアント認証には幾つか種類があります。OAuth のコア仕様である RFC 6749 では、クライアントシークレットという共有鍵を Authorization HTTP ヘッダに埋め込む方法やフォームパラメータとして渡す方法が定義されています。

クライアント認証の方法が別仕様で追加定義されることがあります。RFC 7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization GrantsSection 2.2. Using JWTs for Client Authentication では、JWT を利用したクライアント認証の方法が定義されています。

このクライアント認証方法では、認証に必要な情報を JWT にまとめ、client_assertion リクエストパラメータの値としてサーバに渡します。この JWT をクライアントアサーションと呼びます。

client_assertion.png

詳細は『OAuth 2.0 クライアント認証』をご参照ください。

クライアントアサーションの例
クライアントアサーション
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijd5TmhJSFZlYVBGSUJfMGstWXBpRkFUb21DTHB4SXYtZTJBQUZtQ1JCTEUifQ.eyJpc3MiOiJteV9jbGllbnQiLCJzdWIiOiJteV9jbGllbnQiLCJhdWQiOiJodHRwczovL2FzLmV4YW1wbGUuY29tIiwiaWF0IjoxNzMxODM3MzA4LCJleHAiOjE3MzE4NDA5MDgsImp0aSI6ImQzODdiMDk4LTlhNmQtNDFkMy1hNGY4LTJlNTM1NWE4ZGE1NiJ9.wOhun7XI2h6CZoWJ1ae7nwChvtwJ5DC6GLmEQWF6psrUWFW6ul2SmhO9s_pRdo-Ys-uQKlxipHXUrPWPLkJV-g
ヘッダ
{
  "typ": "JWT",
  "alg": "ES256",
  "kid": "7yNhIHVeaPFIB_0k-YpiFATomCLpxIv-e2AAFmCRBLE"
}
ペイロード
{
  "iss": "my_client",
  "sub": "my_client",
  "aud": "https://as.example.com",
  "iat": 1731837308,
  "exp": 1731840908,
  "jti": "d387b098-9a6d-41d3-a4f8-2e5355a8da56"
}

関連情報

クライアントアテステーション

Verifiable Credentials (証明可能な資格情報) の文脈でウォレット認証をおこなう方法として、新しいクライアント認証 OAuth 2.0 Attestation-Based Client Authentication が提案されています。

このクライアント認証方法では、OAuth-Client-AttestationOAuth-Client-Attestation-PoP という二つの HTTP ヘッダにそれぞれ、クライアントアテステーション JWTクライアントアテステーション PoP JWT、と呼ばれる JWT を指定します。

次の HTTP リクエストは、このクライアント認証方法を用いたトークンリクエストの例です。

クライアントアテステーションを含むトークンリクエスト
POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
OAuth-Client-Attestation: \
eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24rand0IiwiYWxnIjoiRVMyNTY\
iLCJraWQiOiJ6WDl4YkpxQnppTVdLNXZtalhIZ1pUbWlZMTZ4Zm5aeHpTRWEwR3FZNV\
9RIn0.eyJpc3MiOiJodHRwczovL2F0dGVzdGVyLmV4YW1wbGUuY29tIiwic3ViIjoid\
HJhY2syX2Z1bGwiLCJpYXQiOjE3MzIyNDY3NzYsImV4cCI6MTczMjMzMzE3NiwiY25m\
Ijp7Imp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjFBbVZyNEdvSGR\
QZ2s0OExXZFMzVDltNm0xbVA0VlRjajl1c29TQm5DUWsiLCJ5IjoidGUtV0l1VUlxMn\
c4dFhtWHlkbEVYNHBlOWxOZS1QQmNvekE4bjd5OFhURSJ9fX0.vSHXknaA0tGNmK8Ij\
xedEemiRWvODu53sF8dv3cfId0UeggqTVCtLNgWlsqBDvJjp2WmztUV8Q_G2EtbuH2K\
TA
OAuth-Client-Attestation-PoP: \
eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24tcG9wK2p3dCIsImFsZyI6IkV\
TMjU2Iiwia2lkIjoiN3lOaElIVmVhUEZJQl8way1ZcGlGQVRvbUNMcHhJdi1lMkFBRm\
1DUkJMRSJ9.eyJpc3MiOiJ0cmFjazJfZnVsbCIsImlhdCI6MTczMjI0Njc3OCwiZXhw\
IjoxNzMyMzMzMTc4LCJqdGkiOiI3OTBOSElvQ3pmTnZYa2M4IiwiYXVkIjoiaHR0cHM\
6Ly90cmlhbC5hdXRobGV0ZS5uZXQifQ.8ej09ZnGub_74Sa4bGKlvbyuXXH5bR8v1bG\
ZlkYwcx1zceUDSijEIyN3Ia2ORRs0Yh0P2tsdFc88X6s5P0F9Qg

grant_type=authorization_code&
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
クライアントアテステーション JWT の例
クライアントアテステーション JWT
eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24rand0IiwiYWxnIjoiRVMyNTYiLCJraWQiOiJ6WDl4YkpxQnppTVdLNXZtalhIZ1pUbWlZMTZ4Zm5aeHpTRWEwR3FZNV9RIn0.eyJpc3MiOiJodHRwczovL2F0dGVzdGVyLmV4YW1wbGUuY29tIiwic3ViIjoidHJhY2syX2Z1bGwiLCJpYXQiOjE3MzIyNDY3NzYsImV4cCI6MTczMjMzMzE3NiwiY25mIjp7Imp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjFBbVZyNEdvSGRQZ2s0OExXZFMzVDltNm0xbVA0VlRjajl1c29TQm5DUWsiLCJ5IjoidGUtV0l1VUlxMnc4dFhtWHlkbEVYNHBlOWxOZS1QQmNvekE4bjd5OFhURSJ9fX0.vSHXknaA0tGNmK8IjxedEemiRWvODu53sF8dv3cfId0UeggqTVCtLNgWlsqBDvJjp2WmztUV8Q_G2EtbuH2KTA
ヘッダ
{
  "typ": "oauth-client-attestation+jwt",
  "alg": "ES256",
  "kid": "zX9xbJqBziMWK5vmjXHgZTmiY16xfnZxzSEa0GqY5_Q"
}
ペイロード
{
  "iss": "https://attester.example.com",
  "sub": "track2_full",
  "iat": 1732246776,
  "exp": 1732333176,
  "cnf": {
    "jwk": {
      "crv": "P-256",
      "kty": "EC",
      "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
      "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
    }
  }
}
クライアントアテステーション PoP JWT の例
クライアントアテステーション PoP JWT
eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24tcG9wK2p3dCIsImFsZyI6IkVTMjU2Iiwia2lkIjoiN3lOaElIVmVhUEZJQl8way1ZcGlGQVRvbUNMcHhJdi1lMkFBRm1DUkJMRSJ9.eyJpc3MiOiJ0cmFjazJfZnVsbCIsImlhdCI6MTczMjI0Njc3OCwiZXhwIjoxNzMyMzMzMTc4LCJqdGkiOiI3OTBOSElvQ3pmTnZYa2M4IiwiYXVkIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQifQ.8ej09ZnGub_74Sa4bGKlvbyuXXH5bR8v1bGZlkYwcx1zceUDSijEIyN3Ia2ORRs0Yh0P2tsdFc88X6s5P0F9Qg
ヘッダ
{
  "typ": "oauth-client-attestation-pop+jwt",
  "alg": "ES256",
  "kid": "7yNhIHVeaPFIB_0k-YpiFATomCLpxIv-e2AAFmCRBLE"
}
ペイロード
{
  "iss": "track2_full",
  "iat": 1732246778,
  "exp": 1732333178,
  "jti": "790NHIoCzfNvXkc8",
  "aud": "https://trial.authlete.net"
}

私の会社の製品 Authlete 3.0 (発表文書) で OAuth 2.0 Attestation-Based Client Authentication をひっそりとサポートしておりますが (参考: 4.5.2.2. 手順 2 : クライアントアテステーションとクライアントアテステーション PoP)、仕様自体に論点が多く残っており、仕様策定議論も流動的なため、仕様が変更される可能性があります。

DPoP Proof JWT

アクセストークンを利用する際、正当な利用者のみが使えるようにする仕組みがあります。アクセストークン利用者は、アクセストークンを利用する際に自分が正当な利用者であることの証明を提示することが求められます。この仕組みのおかげで、悪者がアクセストークンを盗んでもアクセストークン単体では利用できなくなります。

このように、正当な利用者に紐付けられたアクセストークンを送信者限定 (sender-constrained) アクセストークンと呼びます。

RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens (通称 MTLS) の Section 3. Mutual-TLS Client Certificate-Bound Access Tokens では、クライアントアプリケーション・認可サーバ間の相互 TLS 接続時に利用したクライアント証明書をアクセストークンに紐付ける方法が定義されています。また、RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP) (通称 DPoP) では、クライアントアプリケーションの公開鍵にアクセストークンを紐付ける方法が定義されています。

DPoP を使う場合、クライアントアプリケーションは自分の公開鍵をサーバに渡す必要があります。認可サーバはクライアントアプリケーションが提示した公開鍵をアクセストークンに紐付け、リソースサーバは公開鍵がアクセストークンと紐付いていることを確認します。しかしこのとき、サーバはクライアントが提示した公開鍵を盲目的に信用するわけではありません。公開鍵を提示したクライアントがその公開鍵に対応する秘密鍵を持っていることを確認するのです。

この確認方法として、DPoP proof JWT という JWT が利用されます。クライアントアプリケーションは自身が持つ秘密鍵で署名した DPoP proof JWT をサーバに提示する必要があります。DPoP の詳細については『図解 DPoP (OAuth アクセストークンのセキュリティ向上策の一つ)』をご参照ください。

dpop_18.png

DPoP proof JWT を含むトークンリクエスト
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\
 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\
 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\
 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\
 oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\
 WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\
 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg

grant_type=authorization_code\
&client_id=s6BhdRkqt\
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\
&code_verifier=bEaL42izcC-o-xBk0K2vuJ6U-y1p9r_wW2dFWIWgjz-
DPoP proof JWT の例
DPoP proof JWT
eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCRnMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JEQSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwiaWF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg
ヘッダ
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "x": "l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y": "9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv": "P-256"
  }
}
ペイロード
{
  "jti": "-BwC3ESc6acc2lTc",
  "htm": "POST",
  "htu": "https://server.example.com/token",
  "iat": 1562262616
}

RFC 9449 (DPoP) は Authlete 社のメンバーが著者として名を連ねた初めての IETF RFC です。

関連情報

ユーザ情報レスポンス

OIDC Core の 5.3. UserInfo Endpoint では、ユーザ情報エンドポイントの仕様が定義されています。このエンドポイントに openid スコープを持つアクセストークンを提示すると、ユーザ情報が JSON 形式で返ってきます。

ユーザ情報リクエスト
GET /userinfo HTTP/1.1
Host: server.example.com
Authorization: Bearer SlAV32hkKG
ユーザ情報レスポンス
HTTP/1.1 200 OK
Content-Type: application/json

{
  "sub": "248289761001",
  "name": "Jane Doe",
  "given_name": "Jane",
  "family_name": "Doe",
  "preferred_username": "j.doe",
  "email": "janedoe@example.com",
  "picture": "http://example.com/janedoe/me.jpg"
}

しかし、クライアントアプリケーションの userinfo_signed_response_alg メタデータに署名アルゴリズムが設定されている場合、ユーザ情報エンドポイントから返されるデータのフォーマットは JWT になります。

また、userinfo_signed_response_alg メタデータが設定されていなくても、userinfo_encrypted_response_alg / userinfo_encrypted_response_enc メタデータに暗号アルゴリズムが設定されている場合、同様にユーザ情報エンドポイントから返されるデータのフォーマットは JWT になります。

userinfo_ で始まるこれらのメタデータは OpenID Connect Dynamic Client Registration 1.0 (ISO/IEC 26133:2024) の Section 2. Client Metadata で定義されています。

署名されたユーザ情報レスポンスの例
署名されたユーザ情報レスポンス
eyJraWQiOiJzaHJySzFCS29WZ254aTlqdlVUWHRRbWlzeXpraXpoT29kQ05mYzhsMGR3IiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsInN1YiI6IjEwMDQiLCJhdWQiOlsidHJhY2syX2xpZ2h0Il0sImV4cCI6MTczMjAxNTExOCwiaWF0IjoxNzMxOTI4NzE4fQ.YbdfEMXeHMSLoouZcTHIWCfUJvHU3yfDUYdoqEkHwrO2xH9YRp-eW7K1Gekivk5HUS3ZWBCD30NNTKpXqNGHpw
ヘッダ
{
  "kid": "shrrK1BKoVgnxi9jvUTXtQmisyzkizhOodCNfc8l0dw",
  "alg": "ES256"
}
ペイロード
{
  "iss": "https://trial.authlete.net",
  "sub": "1004",
  "aud": [
    "track2_light"
  ],
  "exp": 1732015118,
  "iat": 1731928718
}

イントロスペクションレスポンス

RFC 7662: OAuth 2.0 Token Introspection では、イントロスペクションエンドポイントの仕様が定義されています。このエンドポイントにアクセストークンまたはリフレッシュトークンを提示すると、そのトークンの情報が JSON 形式で返ってきます。

イントロスペクションレスポンス
{
  "active": true,
  "scope": "openid potential.track2.light.profile",
  "client_id": "track2_light",
  "token_type": "Bearer",
  "exp": 1732014893,
  "sub": "1004",
  "aud": null,
  "iss": "https://trial.authlete.net",
  "auth_time": 1731928492
}

しかし、イントロスペクションエンドポイントが JWT Response for OAuth Token Introspection に準拠するレスポンスを返すように実装されている場合、レスポンスのフォーマットは JWT になります。

署名されたイントロスペクションレスポンス
HTTP/1.1 200 OK
Content-Type: application/token-introspection+jwt

eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGc
iOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6I
mh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIs
InRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczo
vL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcm
Vzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X
2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3Vi
IjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiw
iZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm
9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5Gh
mNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYo
sGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKN
Y0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0
tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFal
eyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA
署名されたイントロスペクションレスポンスの例
署名されたイントロスペクションレスポンス
eyJraWQiOiJ3RzZEIiwidHlwIjoidG9rZW4taW50cm9zcGVjdGlvbitqd3QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4OTIsInRva2VuX2ludHJvc3BlY3Rpb24iOnsiYWN0aXZlIjp0cnVlLCJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcnMuZXhhbXBsZS5jb20vcmVzb3VyY2UiLCJpYXQiOjE1MTQ3OTc4MjIsImV4cCI6MTUxNDc5Nzk0MiwiY2xpZW50X2lkIjoicGFpQjJnb28wYSIsInNjb3BlIjoicmVhZCB3cml0ZSBkb2xwaGluIiwic3ViIjoiWjVPM3VwUEM4OFFyQWp4MDBkaXMiLCJiaXJ0aGRhdGUiOiIxOTgyLTAyLTAxIiwiZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6IkRvZSIsImp0aSI6InQxRm9DQ2FaZDRYdjRPUkpVV1ZVZVRaZnNLaFczMENRQ3JXRERqd1h5NncifX0.przJMU5GhmNzvwtt1Sr-xa9xTkpiAg5IshbQsRiRVP_7eGR1GHYrNwQh84kxOkHCyje2g5WSRcYosGEVIiC-eoPJJ-qBwqwSlgx9JEeCDw2W5DjrblOI_N0Jvsq_dUeOyoWVMqlOydOBhKNY0smBrI4NZvEExucOm9WUJXMuJtvq1gBes-0go5j4TEv9sOP9uu81gqWTr_LOo6pgT0tFFyZfWC4kbXPXiQ2YT6mxCiQRRNM-l9cBdF6Jx6IOrsfFhBuYdYQ_mlL19HgDDOFaleyqmru6lKlASOsaE8dmLSeKcX91FbG79FKN8un24iwIDCbKT9xlUFl54xWVShNDFA
ヘッダ
{
  "kid": "wG6D",
  "typ": "token-introspection+jwt",
  "alg": "RS256"
}
ペイロード
{
  "iss": "https://as.example.com/",
  "aud": "https://rs.example.com/resource",
  "iat": 1514797892,
  "token_introspection": {
    "active": true,
    "iss": "https://as.example.com/",
    "aud": "https://rs.example.com/resource",
    "iat": 1514797822,
    "exp": 1514797942,
    "client_id": "paiB2goo0a",
    "scope": "read write dolphin",
    "sub": "Z5O3upPC88QrAjx00dis",
    "birthdate": "1982-02-01",
    "given_name": "John",
    "family_name": "Doe",
    "jti": "t1FoCCaZd4Xv4ORJUWVUeTZfsKhW30CQCrWDDjwXy6w"
  }
}

JWT Response for OAuth Token Introspection 仕様はあまり知られていませんが、FAPI 2.0 Message Signing を構成する仕様群の一つとなっています。

関連情報

JWT アクセストークン

アクセストークンの実装として JWT を選択する場合、RFC 9068: JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens という仕様を参考にすることができます。ただし、この仕様は次のような問題を抱えているので注意してください。

  • sub クレームが必須となっている。通常、sub クレームの値はアクセストークンの発行を許可したユーザの一意識別子となっている。しかし、クライアントクレデンシャルズフロー (RFC 6749, Section 4.4. Client Credentials Grant) で発行されたアクセストークンには特定のユーザが紐付かないので、ユーザの一意識別子は得られない。この場合、RFC 9068 は sub クレームにクライアントアプリケーションの識別子を設定すべきと言っている。これに対し、「ユーザの識別子が得られない場合は sub クレームは null にすべきだ」という反対意見が仕様策定議論中に出された。しかし、仕様策定議論に参加していた人々の中に「JWT 仕様において sub クレームは必須である」と勘違いしていた人がいたこともあり、反対意見は押し切られて sub クレームは必須となった。

  • aud クレームが必須となっている。これにより、audience を制限しないアクセストークンを発行できない。RFC 9068 の Section 3. Requesting a JWT Access Token は、aud クレームの値の決め方について議論している。その中で、resource パラメータ (参考: RFC 8707: Resource Indicators for OAuth 2.0) が使われた場合は指定された値を aud クレームの値として用いるべきと言っている。これはよい。しかし、resource パラメータが使われなかった場合の aud の値の決め方に問題がある。特に、scope パラメータを元に aud の値を推定すべきという要求事項は、(あるベンダーの実装がそうなっているのは知っているが) scope と audience の間に特別な関係があることを想定しており、不適切である。また、resource パラメータ省略時の意図した挙動、すなわち、「resource パラメータが省略されたときはリソースを制限しない」にも反する。

  • client_id クレームが必須となっている。仕様策定時、この決定は正しかった。しかし、OpenID for Verifiable Credential Issuance が「認可サーバの設定で pre-authorized_grant_anonymous_access_supportedtrue となっている場合、事前認可コードフロー (pre-authorized code flow) において、クライアントアプリケーションを特定する情報を含まないトークンリクエストを許可する」という仕様を導入したため、どのクライアントアプリケーションにも紐付かないアクセストークンが発行されるケースが生じることとなった。この場合、client_id クレームの値は null にせざるをえない。

諸々の反対を押し切って仕様策定されたため、この仕様が広く支持されているとは思えません (個人の感想)。実際、反対意見を表明する記事をわざわざ書いた人もいました (念の為、私ではないです)。ですので、アクセストークンのフォーマットが JWT だからと言って、そのアクセストークンが RFC 9068 に従っていることを前提としてはいけません。

JWT アクセストークンの例

※ RFC 9068 内には JWT アクセストークンの例がないので、下記は Authlete が発行した JWT アクセストークンです。

JWT アクセストークン
eyJhbGciOiJQUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6ImF1dGhsZXRlLWZhcGlkZXYtYXBpLTIwMTgwNTI0In0.eyJzY29wZSI6Im9wZW5pZCBmYXBpci1hY2NvdW50cyIsImNsaWVudF9pZCI6IjkwNTU1MDk2NzEiLCJleHAiOjE3Mjg5MDc4OTYsImlhdCI6MTcyODkwNjk5Niwic3ViIjoiMTAwMSIsImlzcyI6Imh0dHBzOi8vbmV4dHJldmlldy1hcy5hdXRobGV0ZS5uZXQvIiwianRpIjoiand3aUpVTHdKN2lxcHpsUFBsc240R1BYQ0FlOUJBc3o4bWwxWm9GdkNNWSIsImF1dGhfdGltZSI6MTcyODkwNjk5NiwiZ3JhbnRfdHlwZSI6ImF1dGhvcml6YXRpb25fY29kZSJ9.aUgqqjZSKUy2cjKeWiMLdqg-6ElfDYEo30Jlg4--gMZAJIXRpYsnRBbwxEt7H6QrGrTH5aSAqJkBvgNsN_ekPTNMCc-1HFS65PsSiL4cqXTFly3wPyqq1cDXky7mFKT8WkbmtL6OicLdMIepstID_2rkrEYjXTh8rl_oHnWrjY491iLhUdXWWkoQlrp4QWb3Zqwrthqrdb1ZVK2ybTicPiyhJrA206kFY3UQYSBN6tBT5_YpOTpqkATfVqFrsw9LJazEHrREmIuw-j8aYJ8i87rjkAWjMSTEg0E6t5XZyUgj5OjwlptrWqcm71aybPtH1JyuEp72zrnUNSHWVFdQnw
ヘッダ
{
  "alg": "PS256",
  "typ": "at+jwt",
  "kid": "authlete-fapidev-api-20180524"
}
ペイロード
{
  "scope": "openid fapir-accounts",
  "client_id": "9055509671",
  "exp": 1728907896,
  "iat": 1728906996,
  "sub": "1001",
  "iss": "https://nextreview-as.authlete.net/",
  "jti": "jwwiJULwJ7iqpzlPPlsn4GPXCAe9BAsz8ml1ZoFvCMY",
  "auth_time": 1728906996,
  "grant_type": "authorization_code"
}

関連情報

JWT 認可グラント

RFC 7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization GrantsSection 2.1. Using JWTs as Authorization Grants では、JWT 認可グラントと呼ばれるフローを定義しています。このフローは、RFC 6749: The OAuth 2.0 Authorization Framework で定義されている OAuth の基本フロー群とは異なります。

JWT 認可グラントの基本的なアイディアは、「トークンエンドポイントに JWT を提示することでアクセストークンを発行してもらう」というものです。

jwt_authorization_grant.ja.png

しかし、RFC 7523 では、その JWT を誰が生成するかについて定めていません。従って、その JWT の署名を検証するのに用いる鍵の入手方法も仕様では定義されていません。そのため、JWT 認可グラントを利用する際には、少なくとも署名検証用鍵を特定するのに必要な独自規則をそれぞれの運用が定めなければなりません。

JWT 認可グラントはなじみが薄いかもしれませんが、建設業界で実際に利用されています。(参考: 建設業界 DX に関するプレゼンテーション by EARTHBRAIN 社)

関連情報

トークン交換

RFC 8693: OAuth 2.0 Token Exchange では、何らかのトークンを別のトークンと交換するためのフローを定義しています。

token_exchange.ja.png

この仕様は抽象度が高いため、実際に利用する際には詳細を詰める必要があります。例えば、入力として提示するトークンの種類は何か、その正当性はどうやって確認するのか、といった点を決めなければなりません。

入力として提示するトークンのタイプを指定するために subject_token_typeactor_token_type というリクエストパラメータが定義されています。また、出力として要求するトークンのタイプを指定するために requested_token_type というリクエストパラメータが定義されています。RFC 8693 はこれらのトークンタイプのための識別子を幾つか定義しており、その中で urn:ietf:params:oauth:token-type:jwt は、トークンタイプが JWT であることを示すための識別子です。

トークン交換はなじみが薄いかもしれませんが、建設業界で実際に利用されています。(参考: 建設業界 DX に関するプレゼンテーション by EARTHBRAIN 社)

関連情報

エンティティステートメント

OpenID Federation 1.0 という仕様があります。業界内でも最も複雑な仕様のうちの一つです。

この仕様は、異なるネットワークに属する認可サーバとクライアントの間に、トラストチェーン (trust chain) に基づく信頼関係を築く仕組みを定義しています。この仕組みにより、認可サーバにクライアントを事前に登録することなく、認可サーバ・クライアント間で OAuth/OIDC リクエスト・レスポンスのやりとりが可能となります。

openid_federation_overview.ja.png

トラストチェーンに参加するサーバやクライアントはフェデレーションエンティティ (federation entity) と呼ばれます。それぞれのフェデレーションエンティティは、{自身の識別子}/.well-known/openid-federation という URL で、自身に関する情報を公開します。その情報はエンティティコンフィギュレーション (entity configuration) と呼ばれ、形式は JWT です。

また、トラストアンカー (trust anchor) や中間権威機関 (intermediate authority) と呼ばれるトラストチェーンの構築を手助けする第三者機関は、他のフェデレーションエンティティを自身が承認することを示すエンティティステートメント (entity statement) を発行します。このエンティティステートメントの形式も JWT です。なお、エンティティコンフィギュレーションはエンティティステートメントの一種と位置付けられています。

trust_chain_concept_view.png

OpenID Federation 1.0 は、その他にも多くの箇所で JWT を利用しています。ドラフト 41 の時点で、JWT 系統のメディアタイプとして次のものを定義しています。

  • application/entity-statement+jwt
  • application/trust-mark+jwt
  • application/resolve-response+jwt
  • application/trust-mark-delegation+jwt
  • application/jwk-set+jwt
  • application/explicit-registration-response+jwt
エンティティコンフィギュレーションの例
エンティティコンフィギュレーション
eyJhbGciOiJSUzI1NiIsInR5cCI6ImVudGl0eS1zdGF0ZW1lbnQrand0Iiwia2lkIjoiNzhDUTYtb1hpb2ZnTnE1eWVXZ1RLZmo0bnF4Z20xajVMdkJ4U3dFX3hBNCJ9.eyJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsInN1YiI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0IiwiaWF0IjoxNzMxOTc4NjQ3LCJleHAiOjE3MzIwNjUwNDcsImp3a3MiOnsia2V5cyI6W3sia3R5IjoiUlNBIiwiZSI6IkFRQUIiLCJraWQiOiI3OENRNi1vWGlvZmdOcTV5ZVdnVEtmajRucXhnbTFqNUx2QnhTd0VfeEE0IiwiYWxnIjoiUlMyNTYiLCJuIjoieEFMUW5tZFpyOEJuYmx3NWJKQTYzb0hMekwzN3pNN3FaTVZua3ZrNW9iLXZFTlVMUjRfdmZlVVpUeFVqWTJOY1RRLWNQOGxmenJDdTIwRTZURVJwejQ5Mmk2czh6TnptTDJETGZzWUs3amRvajJhZVk3VXFmd3hDbVVMV29BZm92TWRJb3NTYnBnb0VuZ0dGRHVVSzdaYVU0VzIweXRLaWJvekw0eF91WHZfN0xiMERKQk5EdEtsaXRDaEpkMUdKVVZhQlNMcnZPd2hKY2lORndOdGNJc25iUFllN2NPRUh3ZXNsYUJ2Q2Jkc3pNbHdOMnJjdk51TjNMUDgweGN6QWNLSUpZLW1sa2Y2R1Y2T1J3bHFRSnFVQmVKMW4ydjFLR1M1VWpJQnhld1pQWjFoZ3JYLUE2T3BqUXJ5Q1ZfNFFITVRJTF9NakFrYVB3cE1KWUo1aDZRIn1dfSwiYXV0aG9yaXR5X2hpbnRzIjpbImh0dHBzOi8vdHJ1c3QtYW5jaG9yLmF1dGhsZXRlLm5ldC8iLCJodHRwczovL3RydXN0LWFuY2hvci5vaWRjLWZlZGVyYXRpb24ub25saW5lLyJdLCJtZXRhZGF0YSI6eyJvcGVuaWRfcHJvdmlkZXIiOnsiaXNzdWVyIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQiLCJhdXRob3JpemF0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL2F1dGhvcml6YXRpb24iLCJwcm9tcHRfdmFsdWVzX3N1cHBvcnRlZCI6WyJub25lIiwibG9naW4iLCJjb25zZW50Iiwic2VsZWN0X2FjY291bnQiLCJjcmVhdGUiXSwidG9rZW5fZW5kcG9pbnQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldC9hcGkvdG9rZW4iLCJ1c2VyaW5mb19lbmRwb2ludCI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0L2FwaS91c2VyaW5mbyIsImp3a3NfdXJpIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL2p3a3MiLCJyZWdpc3RyYXRpb25fZW5kcG9pbnQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldC9hcGkvcmVnaXN0ZXIiLCJlbmRfc2Vzc2lvbl9lbmRwb2ludCI6bnVsbCwic2NvcGVzX3N1cHBvcnRlZCI6WyJhZGRyZXNzIiwiZW1haWwiLCJvcGVuaWQiLCJvZmZsaW5lX2FjY2VzcyIsInBob25lIiwicHJvZmlsZSIsImZhcGkyOm1zLXJzY3JlcSIsImlkZW50aXR5X2NyZWRlbnRpYWwiLCJvcmcuaXNvLjE4MDEzLjUuMS5tREwiLCJwb3RlbnRpYWwubGlnaHQucHJvZmlsZSIsInBvdGVudGlhbC50cmFjazIuZnVsbC5wcm9maWxlIiwicG90ZW50aWFsLnRyYWNrMi5saWdodC5wcm9maWxlIl0sInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJub25lIiwiY29kZSIsInRva2VuIiwiaWRfdG9rZW4iLCJjb2RlIHRva2VuIiwiY29kZSBpZF90b2tlbiIsImlkX3Rva2VuIHRva2VuIiwiY29kZSBpZF90b2tlbiB0b2tlbiJdLCJyZXNwb25zZV9tb2Rlc19zdXBwb3J0ZWQiOlsicXVlcnkiLCJmcmFnbWVudCIsImZvcm1fcG9zdCIsInF1ZXJ5Lmp3dCIsImZyYWdtZW50Lmp3dCIsImZvcm1fcG9zdC5qd3QiLCJqd3QiXSwiZ3JhbnRfdHlwZXNfc3VwcG9ydGVkIjpbImF1dGhvcml6YXRpb25fY29kZSIsImltcGxpY2l0IiwicGFzc3dvcmQiLCJjbGllbnRfY3JlZGVudGlhbHMiLCJyZWZyZXNoX3Rva2VuIiwidXJuOm9wZW5pZDpwYXJhbXM6Z3JhbnQtdHlwZTpjaWJhIiwidXJuOmlldGY6cGFyYW1zOm9hdXRoOmdyYW50LXR5cGU6ZGV2aWNlX2NvZGUiLCJ1cm46aWV0ZjpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTp0b2tlbi1leGNoYW5nZSIsInVybjppZXRmOnBhcmFtczpvYXV0aDpncmFudC10eXBlOmp3dC1iZWFyZXIiLCJ1cm46aWV0ZjpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpwcmUtYXV0aG9yaXplZF9jb2RlIl0sImFjcl92YWx1ZXNfc3VwcG9ydGVkIjpudWxsLCJzdWJqZWN0X3R5cGVzX3N1cHBvcnRlZCI6WyJwdWJsaWMiLCJwYWlyd2lzZSJdLCJpZF90b2tlbl9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkhTMjU2IiwiSFM1MTIiLCJFUzI1NiIsIkhTMzg0Il0sImlkX3Rva2VuX2VuY3J5cHRpb25fYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiUlNBMV81IiwiUlNBLU9BRVAiLCJSU0EtT0FFUC0yNTYiLCJFQ0RILUVTIiwiRUNESC1FUytBMTI4S1ciLCJFQ0RILUVTK0ExOTJLVyIsIkVDREgtRVMrQTI1NktXIiwiQTEyOEtXIiwiQTE5MktXIiwiQTI1NktXIiwiZGlyIiwiQTEyOEdDTUtXIiwiQTE5MkdDTUtXIiwiQTI1NkdDTUtXIiwiUEJFUzItSFMyNTYrQTEyOEtXIiwiUEJFUzItSFMzODQrQTE5MktXIiwiUEJFUzItSFM1MTIrQTI1NktXIl0sImlkX3Rva2VuX2VuY3J5cHRpb25fZW5jX3ZhbHVlc19zdXBwb3J0ZWQiOlsiQTEyOENCQy1IUzI1NiIsIkExOTJDQkMtSFMzODQiLCJBMjU2Q0JDLUhTNTEyIiwiQTEyOEdDTSIsIkExOTJHQ00iLCJBMjU2R0NNIl0sInVzZXJpbmZvX3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiSFMyNTYiLCJIUzUxMiIsIkVTMjU2IiwiSFMzODQiLCJub25lIl0sInVzZXJpbmZvX2VuY3J5cHRpb25fYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiUlNBMV81IiwiUlNBLU9BRVAiLCJSU0EtT0FFUC0yNTYiLCJFQ0RILUVTIiwiRUNESC1FUytBMTI4S1ciLCJFQ0RILUVTK0ExOTJLVyIsIkVDREgtRVMrQTI1NktXIiwiQTEyOEtXIiwiQTE5MktXIiwiQTI1NktXIiwiZGlyIiwiQTEyOEdDTUtXIiwiQTE5MkdDTUtXIiwiQTI1NkdDTUtXIiwiUEJFUzItSFMyNTYrQTEyOEtXIiwiUEJFUzItSFMzODQrQTE5MktXIiwiUEJFUzItSFM1MTIrQTI1NktXIl0sInVzZXJpbmZvX2VuY3J5cHRpb25fZW5jX3ZhbHVlc19zdXBwb3J0ZWQiOlsiQTEyOENCQy1IUzI1NiIsIkExOTJDQkMtSFMzODQiLCJBMjU2Q0JDLUhTNTEyIiwiQTEyOEdDTSIsIkExOTJHQ00iLCJBMjU2R0NNIl0sInJlcXVlc3Rfb2JqZWN0X3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiSFMyNTYiLCJIUzM4NCIsIkhTNTEyIiwiUlMyNTYiLCJSUzM4NCIsIlJTNTEyIiwiUFMyNTYiLCJQUzM4NCIsIlBTNTEyIiwiRVMyNTYiLCJFUzM4NCIsIkVTNTEyIiwiRVMyNTZLIiwiRWREU0EiXSwicmVxdWVzdF9vYmplY3RfZW5jcnlwdGlvbl9hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJBMTkyR0NNS1ciLCJFQ0RILUVTK0ExMjhLVyIsImRpciIsIkExOTJLVyIsIkExMjhHQ01LVyIsIlBCRVMyLUhTMjU2K0ExMjhLVyIsIlBCRVMyLUhTMzg0K0ExOTJLVyIsIkVDREgtRVMrQTI1NktXIiwiRUNESC1FUytBMTkyS1ciLCJBMTI4S1ciLCJBMjU2R0NNS1ciLCJBMjU2S1ciLCJFQ0RILUVTIiwiUEJFUzItSFM1MTIrQTI1NktXIl0sInJlcXVlc3Rfb2JqZWN0X2VuY3J5cHRpb25fZW5jX3ZhbHVlc19zdXBwb3J0ZWQiOlsiQTEyOENCQy1IUzI1NiIsIkExOTJDQkMtSFMzODQiLCJBMjU2Q0JDLUhTNTEyIiwiQTEyOEdDTSIsIkExOTJHQ00iLCJBMjU2R0NNIl0sImF1dGhvcml6YXRpb25fc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJIUzI1NiIsIkhTNTEyIiwiRVMyNTYiLCJIUzM4NCJdLCJhdXRob3JpemF0aW9uX2VuY3J5cHRpb25fYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiUlNBMV81IiwiUlNBLU9BRVAiLCJSU0EtT0FFUC0yNTYiLCJFQ0RILUVTIiwiRUNESC1FUytBMTI4S1ciLCJFQ0RILUVTK0ExOTJLVyIsIkVDREgtRVMrQTI1NktXIiwiQTEyOEtXIiwiQTE5MktXIiwiQTI1NktXIiwiZGlyIiwiQTEyOEdDTUtXIiwiQTE5MkdDTUtXIiwiQTI1NkdDTUtXIiwiUEJFUzItSFMyNTYrQTEyOEtXIiwiUEJFUzItSFMzODQrQTE5MktXIiwiUEJFUzItSFM1MTIrQTI1NktXIl0sImF1dGhvcml6YXRpb25fZW5jcnlwdGlvbl9lbmNfdmFsdWVzX3N1cHBvcnRlZCI6WyJBMTI4Q0JDLUhTMjU2IiwiQTE5MkNCQy1IUzM4NCIsIkEyNTZDQkMtSFM1MTIiLCJBMTI4R0NNIiwiQTE5MkdDTSIsIkEyNTZHQ00iXSwidG9rZW5fZW5kcG9pbnRfYXV0aF9tZXRob2RzX3N1cHBvcnRlZCI6WyJub25lIiwiY2xpZW50X3NlY3JldF9iYXNpYyIsImNsaWVudF9zZWNyZXRfcG9zdCIsImNsaWVudF9zZWNyZXRfand0IiwicHJpdmF0ZV9rZXlfand0IiwidGxzX2NsaWVudF9hdXRoIiwic2VsZl9zaWduZWRfdGxzX2NsaWVudF9hdXRoIiwiYXR0ZXN0X2p3dF9jbGllbnRfYXV0aCJdLCJ0b2tlbl9lbmRwb2ludF9hdXRoX3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiSFMyNTYiLCJIUzM4NCIsIkhTNTEyIiwiUlMyNTYiLCJSUzM4NCIsIlJTNTEyIiwiUFMyNTYiLCJQUzM4NCIsIlBTNTEyIiwiRVMyNTYiLCJFUzM4NCIsIkVTNTEyIiwiRVMyNTZLIiwiRWREU0EiXSwiZGlzcGxheV92YWx1ZXNfc3VwcG9ydGVkIjpbInBhZ2UiLCJwb3B1cCIsInRvdWNoIiwid2FwIl0sImNsYWltX3R5cGVzX3N1cHBvcnRlZCI6WyJub3JtYWwiXSwiY2xhaW1zX3N1cHBvcnRlZCI6WyJzdWIiLCJ3ZWJzaXRlIiwiem9uZWluZm8iLCJlbWFpbF92ZXJpZmllZCIsImJpcnRoZGF0ZSIsImFkZHJlc3MiLCJnZW5kZXIiLCJwcm9maWxlIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIiwicHJlZmVycmVkX3VzZXJuYW1lIiwiZ2l2ZW5fbmFtZSIsIm1pZGRsZV9uYW1lIiwibG9jYWxlIiwicGljdHVyZSIsInVwZGF0ZWRfYXQiLCJuYW1lIiwibmlja25hbWUiLCJwaG9uZV9udW1iZXIiLCJmYW1pbHlfbmFtZSIsImVtYWlsIl0sInNlcnZpY2VfZG9jdW1lbnRhdGlvbiI6bnVsbCwiY2xhaW1zX2xvY2FsZXNfc3VwcG9ydGVkIjpudWxsLCJ1aV9sb2NhbGVzX3N1cHBvcnRlZCI6bnVsbCwiY2xhaW1zX3BhcmFtZXRlcl9zdXBwb3J0ZWQiOnRydWUsInJlcXVlc3RfcGFyYW1ldGVyX3N1cHBvcnRlZCI6dHJ1ZSwicmVxdWVzdF91cmlfcGFyYW1ldGVyX3N1cHBvcnRlZCI6dHJ1ZSwicmVxdWlyZV9yZXF1ZXN0X3VyaV9yZWdpc3RyYXRpb24iOnRydWUsIm9wX3BvbGljeV91cmkiOm51bGwsIm9wX3Rvc191cmkiOm51bGwsInJldm9jYXRpb25fZW5kcG9pbnQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldC9hcGkvcmV2b2NhdGlvbiIsInJldm9jYXRpb25fZW5kcG9pbnRfYXV0aF9tZXRob2RzX3N1cHBvcnRlZCI6W10sInJldm9jYXRpb25fZW5kcG9pbnRfYXV0aF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkhTMjU2IiwiSFMzODQiLCJIUzUxMiIsIlJTMjU2IiwiUlMzODQiLCJSUzUxMiIsIlBTMjU2IiwiUFMzODQiLCJQUzUxMiIsIkVTMjU2IiwiRVMzODQiLCJFUzUxMiIsIkVTMjU2SyIsIkVkRFNBIl0sImludHJvc3BlY3Rpb25fZW5kcG9pbnQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldC9hcGkvaW50cm9zcGVjdGlvbiIsImludHJvc3BlY3Rpb25fZW5kcG9pbnRfYXV0aF9tZXRob2RzX3N1cHBvcnRlZCI6W10sImludHJvc3BlY3Rpb25fZW5kcG9pbnRfYXV0aF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkhTMjU2IiwiSFMzODQiLCJIUzUxMiIsIlJTMjU2IiwiUlMzODQiLCJSUzUxMiIsIlBTMjU2IiwiUFMzODQiLCJQUzUxMiIsIkVTMjU2IiwiRVMzODQiLCJFUzUxMiIsIkVTMjU2SyIsIkVkRFNBIl0sImNvZGVfY2hhbGxlbmdlX21ldGhvZHNfc3VwcG9ydGVkIjpbInBsYWluIiwiUzI1NiJdLCJ0bHNfY2xpZW50X2NlcnRpZmljYXRlX2JvdW5kX2FjY2Vzc190b2tlbnMiOmZhbHNlLCJiYWNrY2hhbm5lbF90b2tlbl9kZWxpdmVyeV9tb2Rlc19zdXBwb3J0ZWQiOlsicG9sbCIsInBpbmciLCJwdXNoIl0sImJhY2tjaGFubmVsX2F1dGhlbnRpY2F0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL2JhY2tjaGFubmVsL2F1dGhlbnRpY2F0aW9uIiwiYmFja2NoYW5uZWxfYXV0aGVudGljYXRpb25fcmVxdWVzdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIlJTMjU2IiwiUlMzODQiLCJSUzUxMiIsIlBTMjU2IiwiUFMzODQiLCJQUzUxMiIsIkVTMjU2IiwiRVMzODQiLCJFUzUxMiIsIkVTMjU2SyIsIkVkRFNBIl0sImJhY2tjaGFubmVsX3VzZXJfY29kZV9wYXJhbWV0ZXJfc3VwcG9ydGVkIjpmYWxzZSwiZGV2aWNlX2F1dGhvcml6YXRpb25fZW5kcG9pbnQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldC9hcGkvZGV2aWNlL2F1dGhvcml6YXRpb24iLCJwdXNoZWRfYXV0aG9yaXphdGlvbl9yZXF1ZXN0X2VuZHBvaW50IjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL3BhciIsInJlcXVpcmVfcHVzaGVkX2F1dGhvcml6YXRpb25fcmVxdWVzdHMiOmZhbHNlLCJtdGxzX2VuZHBvaW50X2FsaWFzZXMiOm51bGwsImF1dGhvcml6YXRpb25fZGV0YWlsc190eXBlc19zdXBwb3J0ZWQiOlsib3BlbmlkX2NyZWRlbnRpYWwiXSwidHJ1c3RfZnJhbWV3b3Jrc19zdXBwb3J0ZWQiOm51bGwsImV2aWRlbmNlX3N1cHBvcnRlZCI6bnVsbCwiY2xhaW1zX2luX3ZlcmlmaWVkX2NsYWltc19zdXBwb3J0ZWQiOm51bGwsImRwb3Bfc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJSUzI1NiIsIlJTMzg0IiwiUlM1MTIiLCJQUzI1NiIsIlBTMzg0IiwiUFM1MTIiLCJFUzI1NiIsIkVTMzg0IiwiRVM1MTIiLCJFUzI1NksiLCJFZERTQSJdLCJyZXF1aXJlX3NpZ25lZF9yZXF1ZXN0X29iamVjdCI6ZmFsc2UsImF1dGhvcml6YXRpb25fcmVzcG9uc2VfaXNzX3BhcmFtZXRlcl9zdXBwb3J0ZWQiOnRydWUsImdyYW50X21hbmFnZW1lbnRfYWN0aW9uX3JlcXVpcmVkIjpmYWxzZSwiZ3JhbnRfbWFuYWdlbWVudF9hY3Rpb25zX3N1cHBvcnRlZCI6WyJjcmVhdGUiLCJtZXJnZSIsInJlcGxhY2UiXSwiZ3JhbnRfbWFuYWdlbWVudF9lbmRwb2ludCI6bnVsbCwidHJhbnNmb3JtZWRfY2xhaW1zX2Z1bmN0aW9uc19zdXBwb3J0ZWQiOlsiYWxsIiwiYW55IiwiY29udGFpbnMiLCJlbmRzX3dpdGgiLCJlcSIsImdldCIsImd0IiwiZ3RlIiwiaGFzaCIsImx0IiwibHRlIiwibWF0Y2giLCJub25lIiwic3RhcnRzX3dpdGgiLCJ5ZWFyc19hZ28iXSwidHJhbnNmb3JtZWRfY2xhaW1zX3ByZWRlZmluZWQiOm51bGwsImludHJvc3BlY3Rpb25fc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJIUzI1NiIsIkhTNTEyIiwiRVMyNTYiLCJIUzM4NCIsIm5vbmUiXSwiaW50cm9zcGVjdGlvbl9lbmNyeXB0aW9uX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIlJTQTFfNSIsIlJTQS1PQUVQIiwiUlNBLU9BRVAtMjU2IiwiRUNESC1FUyIsIkVDREgtRVMrQTEyOEtXIiwiRUNESC1FUytBMTkyS1ciLCJFQ0RILUVTK0EyNTZLVyIsIkExMjhLVyIsIkExOTJLVyIsIkEyNTZLVyIsImRpciIsIkExMjhHQ01LVyIsIkExOTJHQ01LVyIsIkEyNTZHQ01LVyIsIlBCRVMyLUhTMjU2K0ExMjhLVyIsIlBCRVMyLUhTMzg0K0ExOTJLVyIsIlBCRVMyLUhTNTEyK0EyNTZLVyJdLCJpbnRyb3NwZWN0aW9uX2VuY3J5cHRpb25fZW5jX3ZhbHVlc19zdXBwb3J0ZWQiOlsiQTEyOENCQy1IUzI1NiIsIkExOTJDQkMtSFMzODQiLCJBMjU2Q0JDLUhTNTEyIiwiQTEyOEdDTSIsIkExOTJHQ00iLCJBMjU2R0NNIl0sImNsaWVudF9yZWdpc3RyYXRpb25fdHlwZXNfc3VwcG9ydGVkIjpbImF1dG9tYXRpYyIsImV4cGxpY2l0Il0sImZlZGVyYXRpb25fcmVnaXN0cmF0aW9uX2VuZHBvaW50IjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL2ZlZGVyYXRpb24vcmVnaXN0ZXIiLCJyZXF1ZXN0X2F1dGhlbnRpY2F0aW9uX21ldGhvZHNfc3VwcG9ydGVkIjp7ImF1dGhvcml6YXRpb25fZW5kcG9pbnQiOlsicmVxdWVzdF9vYmplY3QiXSwiYmFja2NoYW5uZWxfYXV0aGVudGljYXRpb25fZW5kcG9pbnQiOlsicmVxdWVzdF9vYmplY3QiLCJwcml2YXRlX2tleV9qd3QiLCJ0bHNfY2xpZW50X2F1dGgiLCJzZWxmX3NpZ25lZF90bHNfY2xpZW50X2F1dGgiXSwiZGV2aWNlX2F1dGhvcml6YXRpb25fZW5kcG9pbnQiOlsicHJpdmF0ZV9rZXlfand0IiwidGxzX2NsaWVudF9hdXRoIiwic2VsZl9zaWduZWRfdGxzX2NsaWVudF9hdXRoIl0sInB1c2hlZF9hdXRob3JpemF0aW9uX3JlcXVlc3RfZW5kcG9pbnQiOlsicmVxdWVzdF9vYmplY3QiLCJwcml2YXRlX2tleV9qd3QiLCJ0bHNfY2xpZW50X2F1dGgiLCJzZWxmX3NpZ25lZF90bHNfY2xpZW50X2F1dGgiXSwidG9rZW5fZW5kcG9pbnQiOlsicHJpdmF0ZV9rZXlfand0IiwidGxzX2NsaWVudF9hdXRoIiwic2VsZl9zaWduZWRfdGxzX2NsaWVudF9hdXRoIl19LCJyZXF1ZXN0X2F1dGhlbnRpY2F0aW9uX3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiXSwicHJlLWF1dGhvcml6ZWRfZ3JhbnRfYW5vbnltb3VzX2FjY2Vzc19zdXBwb3J0ZWQiOmZhbHNlfSwib3BlbmlkX2NyZWRlbnRpYWxfaXNzdWVyIjp7ImNyZWRlbnRpYWxfaXNzdWVyIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQiLCJjcmVkZW50aWFsX2VuZHBvaW50IjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQvYXBpL2NyZWRlbnRpYWwiLCJjcmVkZW50aWFsX3Jlc3BvbnNlX2VuY3J5cHRpb24iOnsiYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiUlNBMV81IiwiUlNBLU9BRVAiLCJSU0EtT0FFUC0yNTYiLCJFQ0RILUVTIiwiRUNESC1FUytBMTI4S1ciLCJFQ0RILUVTK0ExOTJLVyIsIkVDREgtRVMrQTI1NktXIl0sImVuY192YWx1ZXNfc3VwcG9ydGVkIjpbIkExMjhDQkMtSFMyNTYiLCJBMTkyQ0JDLUhTMzg0IiwiQTI1NkNCQy1IUzUxMiIsIkExMjhHQ00iLCJBMTkyR0NNIiwiQTI1NkdDTSJdLCJlbmNyeXB0aW9uX3JlcXVpcmVkIjpmYWxzZX0sImNyZWRlbnRpYWxfY29uZmlndXJhdGlvbnNfc3VwcG9ydGVkIjp7Im9yZy5pc28uMTgwMTMuNS4xLm1ETCI6eyJmb3JtYXQiOiJtc29fbWRvYyIsImRvY3R5cGUiOiJvcmcuaXNvLjE4MDEzLjUuMS5tREwiLCJjbGFpbXMiOnsib3JnLmlzby4xODAxMy41LjEiOnsiZmFtaWx5X25hbWUiOnt9LCJnaXZlbl9uYW1lIjp7fSwiYmlydGhfZGF0ZSI6e30sImlzc3VlX2RhdGUiOnt9LCJleHBpcnlfZGF0ZSI6e30sImlzc3VpbmdfY291bnRyeSI6e30sImlzc3VpbmdfYXV0aG9yaXR5Ijp7fSwiZG9jdW1lbnRfbnVtYmVyIjp7fSwicG9ydHJhaXQiOnt9LCJkcml2aW5nX3ByaXZpbGVnZXMiOnt9LCJ1bl9kaXN0aW5ndWlzaGluZ19zaWduIjp7fSwiYWRtaW5pc3RyYXRpdmVfbnVtYmVyIjp7fSwic2V4Ijp7fSwiaGVpZ2h0Ijp7fSwid2VpZ2h0Ijp7fSwiZXllX2NvbG91ciI6e30sImhhaXJfY29sb3VyIjp7fSwiYmlydGhfcGxhY2UiOnt9LCJyZXNpZGVudF9hZGRyZXNzIjp7fSwicG9ydHJhaXRfY2FwdHVyZV9kYXRlIjp7fSwiYWdlX2luX3llYXJzIjp7fSwiYWdlX2JpcnRoX3llYXIiOnt9LCJpc3N1aW5nX2p1cmlzZGljdGlvbiI6e30sIm5hdGlvbmFsaXR5Ijp7fSwicmVzaWRlbnRfY2l0eSI6e30sInJlc2lkZW50X3N0YXRlIjp7fSwicmVzaWRlbnRfcG9zdGFsX2NvZGUiOnt9LCJyZXNpZGVudF9jb3VudHJ5Ijp7fSwiZmFtaWx5X25hbWVfbmF0aW9uYWxfY2hhcmFjdGVyIjp7fSwiZ2l2ZW5fbmFtZV9uYXRpb25hbF9jaGFyYWN0ZXIiOnt9LCJzaWduYXR1cmVfdXN1YWxfbWFyayI6e319fSwic2NvcGUiOiJvcmcuaXNvLjE4MDEzLjUuMS5tREwiLCJjcmVkZW50aWFsX3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiXX0sIklkZW50aXR5Q3JlZGVudGlhbCI6eyJmb3JtYXQiOiJ2YytzZC1qd3QiLCJ2Y3QiOiJodHRwczovL2NyZWRlbnRpYWxzLmV4YW1wbGUuY29tL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJjbGFpbXMiOnsiZ2l2ZW5fbmFtZSI6eyJkaXNwbGF5IjpbeyJuYW1lIjoi2KfZhNin2LPZhSDYp9mE2LTYrti12YoiLCJsb2NhbGUiOiJhciJ9LHsibmFtZSI6IlZvcm5hbWUiLCJsb2NhbGUiOiJkZSJ9LHsibmFtZSI6IkdpdmVuIE5hbWUiLCJsb2NhbGUiOiJlbiJ9LHsibmFtZSI6Ik5vbWJyZSIsImxvY2FsZSI6ImVzIn0seyJuYW1lIjoi2YbYp9mFIiwibG9jYWxlIjoiZmEifSx7Im5hbWUiOiJFdHVuaW1pIiwibG9jYWxlIjoiZmkifSx7Im5hbWUiOiJQcsOpbm9tIiwibG9jYWxlIjoiZnIifSx7Im5hbWUiOiLgpKrgpLngpJrgpL7gpKjgpYAg4KSX4KSIIOCkqOCkvuCkriIsImxvY2FsZSI6ImhpIn0seyJuYW1lIjoiTm9tZSIsImxvY2FsZSI6Iml0In0seyJuYW1lIjoi5ZCNIiwibG9jYWxlIjoiamEifSx7Im5hbWUiOiLQntCy0L7QsyDQvdGN0YAiLCJsb2NhbGUiOiJtbiJ9LHsibmFtZSI6IlZvb3JuYWFtIiwibG9jYWxlIjoibmwifSx7Im5hbWUiOiJOb21lIFByw7NwcmlvIiwibG9jYWxlIjoicHQifSx7Im5hbWUiOiJGw7ZybmFtbiIsImxvY2FsZSI6InN2In0seyJuYW1lIjoi2YXYs9mE2YXYp9mGINmG2KfZhSIsImxvY2FsZSI6InVyIn1dfSwiZmFtaWx5X25hbWUiOnsiZGlzcGxheSI6W3sibmFtZSI6Itin2LPZhSDYp9mE2LnYp9im2YTYqSIsImxvY2FsZSI6ImFyIn0seyJuYW1lIjoiTmFjaG5hbWUiLCJsb2NhbGUiOiJkZSJ9LHsibmFtZSI6IkZhbWlseSBOYW1lIiwibG9jYWxlIjoiZW4ifSx7Im5hbWUiOiJBcGVsbGlkbyIsImxvY2FsZSI6ImVzIn0seyJuYW1lIjoi2YbYp9mFINiu2KfZhtmI2KfYr9qv24wiLCJsb2NhbGUiOiJmYSJ9LHsibmFtZSI6IlN1a3VuaW1pIiwibG9jYWxlIjoiZmkifSx7Im5hbWUiOiJOb20gZGUgZmFtaWxsZSIsImxvY2FsZSI6ImZyIn0seyJuYW1lIjoi4KSq4KSw4KS_4KS14KS-4KSwIOCkleCkviDgpKjgpL7gpK4iLCJsb2NhbGUiOiJoaSJ9LHsibmFtZSI6IkNvZ25vbWUiLCJsb2NhbGUiOiJpdCJ9LHsibmFtZSI6IuWnkyIsImxvY2FsZSI6ImphIn0seyJuYW1lIjoi06nTqdGA0LjQudC9INC90Y3RgCIsImxvY2FsZSI6Im1uIn0seyJuYW1lIjoiQWNodGVybmFhbSIsImxvY2FsZSI6Im5sIn0seyJuYW1lIjoiU29icmVub21lIiwibG9jYWxlIjoicHQifSx7Im5hbWUiOiJFZnRlcm5hbW4iLCJsb2NhbGUiOiJzdiJ9LHsibmFtZSI6Itiu2KfZhtiv2KfZhtuMINmG2KfZhSIsImxvY2FsZSI6InVyIn1dfSwiYmlydGhkYXRlIjp7ImRpc3BsYXkiOlt7Im5hbWUiOiLYqtin2LHZitiuINin2YTZhdmK2YTYp9ivIiwibG9jYWxlIjoiYXIifSx7Im5hbWUiOiJHZWJ1cnRzZGF0dW0iLCJsb2NhbGUiOiJkZSJ9LHsibmFtZSI6IkRhdGUgb2YgQmlydGgiLCJsb2NhbGUiOiJlbiJ9LHsibmFtZSI6IkZlY2hhIGRlIE5hY2ltaWVudG8iLCJsb2NhbGUiOiJlcyJ9LHsibmFtZSI6Itiq2KfYsduM2K4g2KrZiNmE2K8iLCJsb2NhbGUiOiJmYSJ9LHsibmFtZSI6IlN5bnR5bcOkYWlrYSIsImxvY2FsZSI6ImZpIn0seyJuYW1lIjoiRGF0ZSBkZSBuYWlzc2FuY2UiLCJsb2NhbGUiOiJmciJ9LHsibmFtZSI6IuCknOCkqOCljeCkriDgpJXgpYAg4KSk4KS-4KSw4KWA4KSWIiwibG9jYWxlIjoiaGkifSx7Im5hbWUiOiJEYXRhIGRpIG5hc2NpdGEiLCJsb2NhbGUiOiJpdCJ9LHsibmFtZSI6IueUn-W5tOaciOaXpSIsImxvY2FsZSI6ImphIn0seyJuYW1lIjoi0YLTqdGA0YHTqdC9INOp0LTTqdGAIiwibG9jYWxlIjoibW4ifSx7Im5hbWUiOiJHZWJvb3J0ZWRhdHVtIiwibG9jYWxlIjoibmwifSx7Im5hbWUiOiJEYXRhIGRlIE5hc2NpbWVudG8iLCJsb2NhbGUiOiJwdCJ9LHsibmFtZSI6IkbDtmRlbHNlZGF0dW0iLCJsb2NhbGUiOiJzdiJ9LHsibmFtZSI6Itiq2KfYsduM2K4g2b7bjNiv2KfYpti0IiwibG9jYWxlIjoidXIifV19fSwic2NvcGUiOiJpZGVudGl0eV9jcmVkZW50aWFsIiwiY3J5cHRvZ3JhcGhpY19iaW5kaW5nX21ldGhvZHNfc3VwcG9ydGVkIjpbImp3ayJdLCJjcmVkZW50aWFsX3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRVMyNTYiLCJFUzM4NCIsIkVTNTEyIiwiRVMyNTZLIl0sImRpc3BsYXkiOlt7Im5hbWUiOiJJZGVudGl0eSBDcmVkZW50aWFsIn1dfX0sImp3a3MiOnsia2V5cyI6W3sia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsImtpZCI6IkoxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmsiLCJ4NWMiOlsiTUlJQlhUQ0NBUVNnQXdJQkFnSUdBWXlSMmNJWk1Bb0dDQ3FHU000OUJBTUNNRFl4TkRBeUJnTlZCQU1NSzBveFJuZEtVRGczUXpZdFVVNWZWMU5KVDIxS1FWRmpObTQxUTFGZllscGtZVVpLTlVkRWJsY3hVbXN3SGhjTk1qTXhNakl5TVRRd05qVTJXaGNOTWpReE1ERTNNVFF3TmpVMldqQTJNVFF3TWdZRFZRUUREQ3RLTVVaM1NsQTROME0yTFZGT1gxZFRTVTl0U2tGUll6WnVOVU5SWDJKYVpHRkdTalZIUkc1WE1WSnJNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVBb3BWZWJvSnBZUnljdzFZS2trUk9YZkNwS0VLbDlZMVlQRmhPR2o0eFRnMlVPdW54VHhTSVZrVDk0cUZWSXV1MWhrRW9FMk54ZWxabzMreVRGVU9EREFLQmdncWhrak9QUVFEQWdOSEFEQkVBaUJuRmpTY0JjdkVSbGVMak1DdTVOYnhKS2tOc2EvZ1Foa1hUZkRtYnErVDNnSWdWYXpic1ZkUXZaZ2x1YzluSllReFdselhUOWk2Zit3Z1VLeDBLQ1liajNBPSJdLCJ4IjoiQW9wVmVib0pwWVJ5Y3cxWUtra1JPWGZDcEtFS2w5WTFZUEZoT0dqNHhUZyIsInkiOiJObERycDhVOFVpRlpFX2VLaFZTTHJ0WVpCS0JOamNYcFdhTl9za3hWRGd3IiwiYWxnIjoiRVMyNTYifSx7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJraWQiOiJaYkFBS3doeW5ycUJuWWxIZEVrQkl2TkpGWlpIX2JSZzFLSW9wS2ZaNk84IiwieCI6ImVzaE1ZeXlvRXNIX0ViODVhN283Nm1zWEZQb2tmdk5hZXlZM3U1cURtM00iLCJ5IjoicTBsR01uX1VYaVdKZGdKdFNDTnpoOXpQQzZzN3FLcVFNbzRWMWktNjlqQSIsImFsZyI6IkVTMjU2In1dfX19fQ.r5u5ncsQwq8XuVt6GX1ZMdwQUUqr6wXo6Rb22heHbaFM_CGSkPeLxfluVAaqHY5Ojl3KnaPwtf3lynLrVVkwpmc7XRIE7o8HoHPhD7HLZEKNFTYk-0WMlN28fEUgQ6Mv0TTq10wkAuDab_bj_YaHWXDbk03PzsVCwiNBC8flxhdq2H6TVECy5mNYiIOISsAeDvQVfn4SuHK_B8j0IrA1xcsRr6XPoMl2VbCJP03uifO4kxxoHBj9Asvh2FNOh2Rz_TZ_4iGnFtisygyU0WKM3_DF8taV-rXR6rcozRFbcUsMHPpNMHQtaZuJ5gcvpxsqLTemOUBluwPK7YTYedPotQ
ヘッダ
{
  "alg": "RS256",
  "typ": "entity-statement+jwt",
  "kid": "78CQ6-oXiofgNq5yeWgTKfj4nqxgm1j5LvBxSwE_xA4"
}
ペイロード
{
  "iss": "https://trial.authlete.net",
  "sub": "https://trial.authlete.net",
  "iat": 1731978647,
  "exp": 1732065047,
  "jwks": {
    "keys": [
      {
        "kty": "RSA",
        "e": "AQAB",
        "kid": "78CQ6-oXiofgNq5yeWgTKfj4nqxgm1j5LvBxSwE_xA4",
        "alg": "RS256",
        "n": "xALQnmdZr8Bnblw5bJA63oHLzL37zM7qZMVnkvk5ob-vENULR4_vfeUZTxUjY2NcTQ-cP8lfzrCu20E6TERpz492i6s8zNzmL2DLfsYK7jdoj2aeY7UqfwxCmULWoAfovMdIosSbpgoEngGFDuUK7ZaU4W20ytKibozL4x_uXv_7Lb0DJBNDtKlitChJd1GJUVaBSLrvOwhJciNFwNtcIsnbPYe7cOEHweslaBvCbdszMlwN2rcvNuN3LP80xczAcKIJY-mlkf6GV6ORwlqQJqUBeJ1n2v1KGS5UjIBxewZPZ1hgrX-A6OpjQryCV_4QHMTIL_MjAkaPwpMJYJ5h6Q"
      }
    ]
  },
  "authority_hints": [
    "https://trust-anchor.authlete.net/",
    "https://trust-anchor.oidc-federation.online/"
  ],
  "metadata": {
    "openid_provider": {
      "issuer": "https://trial.authlete.net",
      "authorization_endpoint": "https://trial.authlete.net/api/authorization",
      "prompt_values_supported": [
        "none",
        "login",
        "consent",
        "select_account",
        "create"
      ],
      "token_endpoint": "https://trial.authlete.net/api/token",
      "userinfo_endpoint": "https://trial.authlete.net/api/userinfo",
      "jwks_uri": "https://trial.authlete.net/api/jwks",
      "registration_endpoint": "https://trial.authlete.net/api/register",
      "end_session_endpoint": null,
      "scopes_supported": [
        "address",
        "email",
        "openid",
        "offline_access",
        "phone",
        "profile",
        "fapi2:ms-rscreq",
        "identity_credential",
        "org.iso.18013.5.1.mDL",
        "potential.light.profile",
        "potential.track2.full.profile",
        "potential.track2.light.profile"
      ],
      "response_types_supported": [
        "none",
        "code",
        "token",
        "id_token",
        "code token",
        "code id_token",
        "id_token token",
        "code id_token token"
      ],
      "response_modes_supported": [
        "query",
        "fragment",
        "form_post",
        "query.jwt",
        "fragment.jwt",
        "form_post.jwt",
        "jwt"
      ],
      "grant_types_supported": [
        "authorization_code",
        "implicit",
        "password",
        "client_credentials",
        "refresh_token",
        "urn:openid:params:grant-type:ciba",
        "urn:ietf:params:oauth:grant-type:device_code",
        "urn:ietf:params:oauth:grant-type:token-exchange",
        "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "urn:ietf:params:oauth:grant-type:pre-authorized_code"
      ],
      "acr_values_supported": null,
      "subject_types_supported": [
        "public",
        "pairwise"
      ],
      "id_token_signing_alg_values_supported": [
        "HS256",
        "HS512",
        "ES256",
        "HS384"
      ],
      "id_token_encryption_alg_values_supported": [
        "RSA1_5",
        "RSA-OAEP",
        "RSA-OAEP-256",
        "ECDH-ES",
        "ECDH-ES+A128KW",
        "ECDH-ES+A192KW",
        "ECDH-ES+A256KW",
        "A128KW",
        "A192KW",
        "A256KW",
        "dir",
        "A128GCMKW",
        "A192GCMKW",
        "A256GCMKW",
        "PBES2-HS256+A128KW",
        "PBES2-HS384+A192KW",
        "PBES2-HS512+A256KW"
      ],
      "id_token_encryption_enc_values_supported": [
        "A128CBC-HS256",
        "A192CBC-HS384",
        "A256CBC-HS512",
        "A128GCM",
        "A192GCM",
        "A256GCM"
      ],
      "userinfo_signing_alg_values_supported": [
        "HS256",
        "HS512",
        "ES256",
        "HS384",
        "none"
      ],
      "userinfo_encryption_alg_values_supported": [
        "RSA1_5",
        "RSA-OAEP",
        "RSA-OAEP-256",
        "ECDH-ES",
        "ECDH-ES+A128KW",
        "ECDH-ES+A192KW",
        "ECDH-ES+A256KW",
        "A128KW",
        "A192KW",
        "A256KW",
        "dir",
        "A128GCMKW",
        "A192GCMKW",
        "A256GCMKW",
        "PBES2-HS256+A128KW",
        "PBES2-HS384+A192KW",
        "PBES2-HS512+A256KW"
      ],
      "userinfo_encryption_enc_values_supported": [
        "A128CBC-HS256",
        "A192CBC-HS384",
        "A256CBC-HS512",
        "A128GCM",
        "A192GCM",
        "A256GCM"
      ],
      "request_object_signing_alg_values_supported": [
        "HS256",
        "HS384",
        "HS512",
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "request_object_encryption_alg_values_supported": [
        "A192GCMKW",
        "ECDH-ES+A128KW",
        "dir",
        "A192KW",
        "A128GCMKW",
        "PBES2-HS256+A128KW",
        "PBES2-HS384+A192KW",
        "ECDH-ES+A256KW",
        "ECDH-ES+A192KW",
        "A128KW",
        "A256GCMKW",
        "A256KW",
        "ECDH-ES",
        "PBES2-HS512+A256KW"
      ],
      "request_object_encryption_enc_values_supported": [
        "A128CBC-HS256",
        "A192CBC-HS384",
        "A256CBC-HS512",
        "A128GCM",
        "A192GCM",
        "A256GCM"
      ],
      "authorization_signing_alg_values_supported": [
        "HS256",
        "HS512",
        "ES256",
        "HS384"
      ],
      "authorization_encryption_alg_values_supported": [
        "RSA1_5",
        "RSA-OAEP",
        "RSA-OAEP-256",
        "ECDH-ES",
        "ECDH-ES+A128KW",
        "ECDH-ES+A192KW",
        "ECDH-ES+A256KW",
        "A128KW",
        "A192KW",
        "A256KW",
        "dir",
        "A128GCMKW",
        "A192GCMKW",
        "A256GCMKW",
        "PBES2-HS256+A128KW",
        "PBES2-HS384+A192KW",
        "PBES2-HS512+A256KW"
      ],
      "authorization_encryption_enc_values_supported": [
        "A128CBC-HS256",
        "A192CBC-HS384",
        "A256CBC-HS512",
        "A128GCM",
        "A192GCM",
        "A256GCM"
      ],
      "token_endpoint_auth_methods_supported": [
        "none",
        "client_secret_basic",
        "client_secret_post",
        "client_secret_jwt",
        "private_key_jwt",
        "tls_client_auth",
        "self_signed_tls_client_auth",
        "attest_jwt_client_auth"
      ],
      "token_endpoint_auth_signing_alg_values_supported": [
        "HS256",
        "HS384",
        "HS512",
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "display_values_supported": [
        "page",
        "popup",
        "touch",
        "wap"
      ],
      "claim_types_supported": [
        "normal"
      ],
      "claims_supported": [
        "sub",
        "website",
        "zoneinfo",
        "email_verified",
        "birthdate",
        "address",
        "gender",
        "profile",
        "phone_number_verified",
        "preferred_username",
        "given_name",
        "middle_name",
        "locale",
        "picture",
        "updated_at",
        "name",
        "nickname",
        "phone_number",
        "family_name",
        "email"
      ],
      "service_documentation": null,
      "claims_locales_supported": null,
      "ui_locales_supported": null,
      "claims_parameter_supported": true,
      "request_parameter_supported": true,
      "request_uri_parameter_supported": true,
      "require_request_uri_registration": true,
      "op_policy_uri": null,
      "op_tos_uri": null,
      "revocation_endpoint": "https://trial.authlete.net/api/revocation",
      "revocation_endpoint_auth_methods_supported": [

      ],
      "revocation_endpoint_auth_signing_alg_values_supported": [
        "HS256",
        "HS384",
        "HS512",
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "introspection_endpoint": "https://trial.authlete.net/api/introspection",
      "introspection_endpoint_auth_methods_supported": [

      ],
      "introspection_endpoint_auth_signing_alg_values_supported": [
        "HS256",
        "HS384",
        "HS512",
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "code_challenge_methods_supported": [
        "plain",
        "S256"
      ],
      "tls_client_certificate_bound_access_tokens": false,
      "backchannel_token_delivery_modes_supported": [
        "poll",
        "ping",
        "push"
      ],
      "backchannel_authentication_endpoint": "https://trial.authlete.net/api/backchannel/authentication",
      "backchannel_authentication_request_signing_alg_values_supported": [
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "backchannel_user_code_parameter_supported": false,
      "device_authorization_endpoint": "https://trial.authlete.net/api/device/authorization",
      "pushed_authorization_request_endpoint": "https://trial.authlete.net/api/par",
      "require_pushed_authorization_requests": false,
      "mtls_endpoint_aliases": null,
      "authorization_details_types_supported": [
        "openid_credential"
      ],
      "trust_frameworks_supported": null,
      "evidence_supported": null,
      "claims_in_verified_claims_supported": null,
      "dpop_signing_alg_values_supported": [
        "RS256",
        "RS384",
        "RS512",
        "PS256",
        "PS384",
        "PS512",
        "ES256",
        "ES384",
        "ES512",
        "ES256K",
        "EdDSA"
      ],
      "require_signed_request_object": false,
      "authorization_response_iss_parameter_supported": true,
      "grant_management_action_required": false,
      "grant_management_actions_supported": [
        "create",
        "merge",
        "replace"
      ],
      "grant_management_endpoint": null,
      "transformed_claims_functions_supported": [
        "all",
        "any",
        "contains",
        "ends_with",
        "eq",
        "get",
        "gt",
        "gte",
        "hash",
        "lt",
        "lte",
        "match",
        "none",
        "starts_with",
        "years_ago"
      ],
      "transformed_claims_predefined": null,
      "introspection_signing_alg_values_supported": [
        "HS256",
        "HS512",
        "ES256",
        "HS384",
        "none"
      ],
      "introspection_encryption_alg_values_supported": [
        "RSA1_5",
        "RSA-OAEP",
        "RSA-OAEP-256",
        "ECDH-ES",
        "ECDH-ES+A128KW",
        "ECDH-ES+A192KW",
        "ECDH-ES+A256KW",
        "A128KW",
        "A192KW",
        "A256KW",
        "dir",
        "A128GCMKW",
        "A192GCMKW",
        "A256GCMKW",
        "PBES2-HS256+A128KW",
        "PBES2-HS384+A192KW",
        "PBES2-HS512+A256KW"
      ],
      "introspection_encryption_enc_values_supported": [
        "A128CBC-HS256",
        "A192CBC-HS384",
        "A256CBC-HS512",
        "A128GCM",
        "A192GCM",
        "A256GCM"
      ],
      "client_registration_types_supported": [
        "automatic",
        "explicit"
      ],
      "federation_registration_endpoint": "https://trial.authlete.net/api/federation/register",
      "request_authentication_methods_supported": {
        "authorization_endpoint": [
          "request_object"
        ],
        "backchannel_authentication_endpoint": [
          "request_object",
          "private_key_jwt",
          "tls_client_auth",
          "self_signed_tls_client_auth"
        ],
        "device_authorization_endpoint": [
          "private_key_jwt",
          "tls_client_auth",
          "self_signed_tls_client_auth"
        ],
        "pushed_authorization_request_endpoint": [
          "request_object",
          "private_key_jwt",
          "tls_client_auth",
          "self_signed_tls_client_auth"
        ],
        "token_endpoint": [
          "private_key_jwt",
          "tls_client_auth",
          "self_signed_tls_client_auth"
        ]
      },
      "request_authentication_signing_alg_values_supported": [
        "ES256"
      ],
      "pre-authorized_grant_anonymous_access_supported": false
    },
    "openid_credential_issuer": {
      "credential_issuer": "https://trial.authlete.net",
      "credential_endpoint": "https://trial.authlete.net/api/credential",
      "credential_response_encryption": {
        "alg_values_supported": [
          "RSA1_5",
          "RSA-OAEP",
          "RSA-OAEP-256",
          "ECDH-ES",
          "ECDH-ES+A128KW",
          "ECDH-ES+A192KW",
          "ECDH-ES+A256KW"
        ],
        "enc_values_supported": [
          "A128CBC-HS256",
          "A192CBC-HS384",
          "A256CBC-HS512",
          "A128GCM",
          "A192GCM",
          "A256GCM"
        ],
        "encryption_required": false
      },
      "credential_configurations_supported": {
        "org.iso.18013.5.1.mDL": {
          "format": "mso_mdoc",
          "doctype": "org.iso.18013.5.1.mDL",
          "claims": {
            "org.iso.18013.5.1": {
              "family_name": {
              },
              "given_name": {
              },
              "birth_date": {
              },
              "issue_date": {
              },
              "expiry_date": {
              },
              "issuing_country": {
              },
              "issuing_authority": {
              },
              "document_number": {
              },
              "portrait": {
              },
              "driving_privileges": {
              },
              "un_distinguishing_sign": {
              },
              "administrative_number": {
              },
              "sex": {
              },
              "height": {
              },
              "weight": {
              },
              "eye_colour": {
              },
              "hair_colour": {
              },
              "birth_place": {
              },
              "resident_address": {
              },
              "portrait_capture_date": {
              },
              "age_in_years": {
              },
              "age_birth_year": {
              },
              "issuing_jurisdiction": {
              },
              "nationality": {
              },
              "resident_city": {
              },
              "resident_state": {
              },
              "resident_postal_code": {
              },
              "resident_country": {
              },
              "family_name_national_character": {
              },
              "given_name_national_character": {
              },
              "signature_usual_mark": {
              }
            }
          },
          "scope": "org.iso.18013.5.1.mDL",
          "credential_signing_alg_values_supported": [
            "ES256"
          ]
        },
        "IdentityCredential": {
          "format": "vc+sd-jwt",
          "vct": "https://credentials.example.com/identity_credential",
          "claims": {
            "given_name": {
              "display": [
                {
                  "name": "الاسم الشخصي",
                  "locale": "ar"
                },
                {
                  "name": "Vorname",
                  "locale": "de"
                },
                {
                  "name": "Given Name",
                  "locale": "en"
                },
                {
                  "name": "Nombre",
                  "locale": "es"
                },
                {
                  "name": "نام",
                  "locale": "fa"
                },
                {
                  "name": "Etunimi",
                  "locale": "fi"
                },
                {
                  "name": "Prénom",
                  "locale": "fr"
                },
                {
                  "name": "पहचानी गई नाम",
                  "locale": "hi"
                },
                {
                  "name": "Nome",
                  "locale": "it"
                },
                {
                  "name": "名",
                  "locale": "ja"
                },
                {
                  "name": "Овог нэр",
                  "locale": "mn"
                },
                {
                  "name": "Voornaam",
                  "locale": "nl"
                },
                {
                  "name": "Nome Próprio",
                  "locale": "pt"
                },
                {
                  "name": "Förnamn",
                  "locale": "sv"
                },
                {
                  "name": "مسلمان نام",
                  "locale": "ur"
                }
              ]
            },
            "family_name": {
              "display": [
                {
                  "name": "اسم العائلة",
                  "locale": "ar"
                },
                {
                  "name": "Nachname",
                  "locale": "de"
                },
                {
                  "name": "Family Name",
                  "locale": "en"
                },
                {
                  "name": "Apellido",
                  "locale": "es"
                },
                {
                  "name": "نام خانوادگی",
                  "locale": "fa"
                },
                {
                  "name": "Sukunimi",
                  "locale": "fi"
                },
                {
                  "name": "Nom de famille",
                  "locale": "fr"
                },
                {
                  "name": "परिवार का नाम",
                  "locale": "hi"
                },
                {
                  "name": "Cognome",
                  "locale": "it"
                },
                {
                  "name": "姓",
                  "locale": "ja"
                },
                {
                  "name": "өөрийн нэр",
                  "locale": "mn"
                },
                {
                  "name": "Achternaam",
                  "locale": "nl"
                },
                {
                  "name": "Sobrenome",
                  "locale": "pt"
                },
                {
                  "name": "Efternamn",
                  "locale": "sv"
                },
                {
                  "name": "خاندانی نام",
                  "locale": "ur"
                }
              ]
            },
            "birthdate": {
              "display": [
                {
                  "name": "تاريخ الميلاد",
                  "locale": "ar"
                },
                {
                  "name": "Geburtsdatum",
                  "locale": "de"
                },
                {
                  "name": "Date of Birth",
                  "locale": "en"
                },
                {
                  "name": "Fecha de Nacimiento",
                  "locale": "es"
                },
                {
                  "name": "تاریخ تولد",
                  "locale": "fa"
                },
                {
                  "name": "Syntymäaika",
                  "locale": "fi"
                },
                {
                  "name": "Date de naissance",
                  "locale": "fr"
                },
                {
                  "name": "जन्म की तारीख",
                  "locale": "hi"
                },
                {
                  "name": "Data di nascita",
                  "locale": "it"
                },
                {
                  "name": "生年月日",
                  "locale": "ja"
                },
                {
                  "name": "төрсөн өдөр",
                  "locale": "mn"
                },
                {
                  "name": "Geboortedatum",
                  "locale": "nl"
                },
                {
                  "name": "Data de Nascimento",
                  "locale": "pt"
                },
                {
                  "name": "Födelsedatum",
                  "locale": "sv"
                },
                {
                  "name": "تاریخ پیدائش",
                  "locale": "ur"
                }
              ]
            }
          },
          "scope": "identity_credential",
          "cryptographic_binding_methods_supported": [
            "jwk"
          ],
          "credential_signing_alg_values_supported": [
            "ES256",
            "ES384",
            "ES512",
            "ES256K"
          ],
          "display": [
            {
              "name": "Identity Credential"
            }
          ]
        }
      },
      "jwks": {
        "keys": [
          {
            "kty": "EC",
            "crv": "P-256",
            "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
            "x5c": [
              "MIIBXTCCAQSgAwIBAgIGAYyR2cIZMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK0oxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmswHhcNMjMxMjIyMTQwNjU2WhcNMjQxMDE3MTQwNjU2WjA2MTQwMgYDVQQDDCtKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAopVeboJpYRycw1YKkkROXfCpKEKl9Y1YPFhOGj4xTg2UOunxTxSIVkT94qFVIuu1hkEoE2NxelZo3+yTFUODDAKBggqhkjOPQQDAgNHADBEAiBnFjScBcvERleLjMCu5NbxJKkNsa/gQhkXTfDmbq+T3gIgVazbsVdQvZgluc9nJYQxWlzXT9i6f+wgUKx0KCYbj3A="
            ],
            "x": "AopVeboJpYRycw1YKkkROXfCpKEKl9Y1YPFhOGj4xTg",
            "y": "NlDrp8U8UiFZE_eKhVSLrtYZBKBNjcXpWaN_skxVDgw",
            "alg": "ES256"
          },
          {
            "kty": "EC",
            "crv": "P-256",
            "kid": "ZbAAKwhynrqBnYlHdEkBIvNJFZZH_bRg1KIopKfZ6O8",
            "x": "eshMYyyoEsH_Eb85a7o76msXFPokfvNaeyY3u5qDm3M",
            "y": "q0lGMn_UXiWJdgJtSCNzh9zPC6s7qKqQMo4V1i-69jA",
            "alg": "ES256"
          }
        ]
      }
    }
  }
}

OpenID Federation 1.0 はイタリアで実運用されています。また、オーストラリアなど、他の国にも採用の動きが広がっています。

関連情報

SD-JWT

Selective Disclosure for JWTs という仕様により、選択的開示 (Selective Disclosure) を実現するデータフォーマットの一つとして SD-JWT が定義されています。SD-JWT 自体は JWT ではありませんが、そのデータ構造の一部に JWT が使われています。

sd-jwt.png

この SD-JWT をベースとした Verifiable Credential のフォーマットを定義する仕様が SD-JWT-based Verifiable Credentials (SD-JWT VC) です。

SD-JWT VC の例
SD-JWT VC
eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImRjK3NkLWp3dCJ9.eyJfc2QiOiBbIjBIWm1
uU0lQejMzN2tTV2U3QzM0bC0tODhnekppLWVCSjJWel9ISndBVGciLCAiOVpicGxDN1R
kRVc3cWFsNkJCWmxNdHFKZG1lRU9pWGV2ZEpsb1hWSmRSUSIsICJJMDBmY0ZVb0RYQ3V
jcDV5eTJ1anFQc3NEVkdhV05pVWxpTnpfYXdEMGdjIiwgIklFQllTSkdOaFhJbHJRbzU
4eWtYbTJaeDN5bGw5WmxUdFRvUG8xN1FRaVkiLCAiTGFpNklVNmQ3R1FhZ1hSN0F2R1R
yblhnU2xkM3o4RUlnX2Z2M2ZPWjFXZyIsICJodkRYaHdtR2NKUXNCQ0EyT3RqdUxBY3d
BTXBEc2FVMG5rb3ZjS09xV05FIiwgImlrdXVyOFE0azhxM1ZjeUE3ZEMtbU5qWkJrUmV
EVFUtQ0c0bmlURTdPVFUiLCAicXZ6TkxqMnZoOW80U0VYT2ZNaVlEdXZUeWtkc1dDTmc
wd1RkbHIwQUVJTSIsICJ3elcxNWJoQ2t2a3N4VnZ1SjhSRjN4aThpNjRsbjFqb183NkJ
DMm9hMXVnIiwgInpPZUJYaHh2SVM0WnptUWNMbHhLdUVBT0dHQnlqT3FhMXoySW9WeF9
ZRFEiXSwgImlzcyI6ICJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsICJpYXQiOiA
xNjgzMDAwMDAwLCAiZXhwIjogMTg4MzAwMDAwMCwgInZjdCI6ICJodHRwczovL2JtaS5
idW5kLmV4YW1wbGUvY3JlZGVudGlhbC9waWQvMS4wIiwgImFnZV9lcXVhbF9vcl9vdmV
yIjogeyJfc2QiOiBbIkZjOElfMDdMT2NnUHdyREpLUXlJR085N3dWc09wbE1Makh2UkM
0UjQtV2ciLCAiWEx0TGphZFVXYzl6Tl85aE1KUm9xeTQ2VXNDS2IxSXNoWnV1cVVGS1N
DQSIsICJhb0NDenNDN3A0cWhaSUFoX2lkUkNTQ2E2NDF1eWNuYzh6UGZOV3o4bngwIiw
gImYxLVAwQTJkS1dhdnYxdUZuTVgyQTctRVh4dmhveHY1YUhodUVJTi1XNjQiLCAiazV
oeTJyMDE4dnJzSmpvLVZqZDZnNnl0N0Fhb25Lb25uaXVKOXplbDNqbyIsICJxcDdaX0t
5MVlpcDBzWWdETzN6VnVnMk1GdVBOakh4a3NCRG5KWjRhSS1jIl19LCAiX3NkX2FsZyI
6ICJzaGEtMjU2IiwgImNuZiI6IHsiandrIjogeyJrdHkiOiAiRUMiLCAiY3J2IjogIlA
tMjU2IiwgIngiOiAiVENBRVIxOVp2dTNPSEY0ajRXNHZmU1ZvSElQMUlMaWxEbHM3dkN
lR2VtYyIsICJ5IjogIlp4amlXV2JaTVFHSFZXS1ZRNGhiU0lpcnNWZnVlY0NFNnQ0alQ
5RjJIWlEifX19.dwstJbebupjLSYtA3DGJBjcEDnHrftlVJeeIMwkOePBAcIOq5jC3qG
m-yRcXfvzHY6NQPLtwaIZC76V-p-gQeA~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3Iiw
gImdpdmVuX25hbWUiLCAiRXJpa2EiXQ~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwg
ImZhbWlseV9uYW1lIiwgIk11c3Rlcm1hbm4iXQ~WyI2SWo3dE0tYTVpVlBHYm9TNXRtd
lZBIiwgImJpcnRoZGF0ZSIsICIxOTYzLTA4LTEyIl0~WyJlSThaV205UW5LUHBOUGVOZ
W5IZGhRIiwgInNvdXJjZV9kb2N1bWVudF90eXBlIiwgImlkX2NhcmQiXQ~WyJRZ19PNj
R6cUF4ZTQxMmExMDhpcm9BIiwgInN0cmVldF9hZGRyZXNzIiwgIkhlaWRlc3RyYVx1MD
BkZmUgMTciXQ~WyJBSngtMDk1VlBycFR0TjRRTU9xUk9BIiwgImxvY2FsaXR5IiwgIkt
cdTAwZjZsbiJd~WyJQYzMzSk0yTGNoY1VfbEhnZ3ZfdWZRIiwgInBvc3RhbF9jb2RlIi
wgIjUxMTQ3Il0~WyJHMDJOU3JRZmpGWFE3SW8wOXN5YWpBIiwgImNvdW50cnkiLCAiRE
UiXQ~WyJsa2x4RjVqTVlsR1RQVW92TU5JdkNBIiwgImFkZHJlc3MiLCB7Il9zZCI6IFs
iWEZjN3pYUG03enpWZE15d20yRXVCZmxrYTVISHF2ZjhVcF9zek5HcXZpZyIsICJiZDF
FVnpnTm9wVWs0RVczX2VRMm4zX05VNGl1WE9IdjlYYkdITjNnMVRFIiwgImZfRlFZZ3Z
RV3Z5VnFObklYc0FSbE55ZTdZR3A4RTc3Z1JBamFxLXd2bnciLCAidjRra2JfcFAxamx
2VWJTanR5YzVicWNXeUEtaThYTHZoVllZN1pUMHRiMCJdfV0~WyJuUHVvUW5rUkZxM0J
JZUFtN0FuWEZBIiwgIm5hdGlvbmFsaXRpZXMiLCBbIkRFIl1d~WyI1YlBzMUlxdVpOYT
Boa2FGenp6Wk53IiwgImdlbmRlciIsICJmZW1hbGUiXQ~WyI1YTJXMF9OcmxFWnpmcW1
rXzdQcS13IiwgImJpcnRoX2ZhbWlseV9uYW1lIiwgIkdhYmxlciJd~WyJ5MXNWVTV3ZG
ZKYWhWZGd3UGdTN1JRIiwgImxvY2FsaXR5IiwgIkJlcmxpbiJd~WyJIYlE0WDhzclZXM
1FEeG5JSmRxeU9BIiwgInBsYWNlX29mX2JpcnRoIiwgeyJfc2QiOiBbIldwaEhvSUR5b
1diQXBEQzR6YnV3UjQweGwweExoRENfY3Y0dHNTNzFyRUEiXSwgImNvdW50cnkiOiAiR
EUifV0~WyJDOUdTb3VqdmlKcXVFZ1lmb2pDYjFBIiwgImFsc29fa25vd25fYXMiLCAiU
2Nod2VzdGVyIEFnbmVzIl0~WyJreDVrRjE3Vi14MEptd1V4OXZndnR3IiwgIjEyIiwgd
HJ1ZV0~WyJIM28xdXN3UDc2MEZpMnllR2RWQ0VRIiwgIjE0IiwgdHJ1ZV0~WyJPQktsV
FZsdkxnLUFkd3FZR2JQOFpBIiwgIjE2IiwgdHJ1ZV0~WyJNMEpiNTd0NDF1YnJrU3V5c
kRUM3hBIiwgIjE4IiwgdHJ1ZV0~WyJEc210S05ncFY0ZEFIcGpyY2Fvc0F3IiwgIjIxI
iwgdHJ1ZV0~WyJlSzVvNXBIZmd1cFBwbHRqMXFoQUp3IiwgIjY1IiwgZmFsc2Vd~
Issuer-Signed JWT 部のヘッダ
{
  "alg": "ES256",
  "typ": "dc+sd-jwt"
}
Issuer-Signed JWT 部のペイロード
{
  "_sd": [
    "0HZmnSIPz337kSWe7C34l--88gzJi-eBJ2Vz_HJwATg",
    "9ZbplC7TdEW7qal6BBZlMtqJdmeEOiXevdJloXVJdRQ",
    "I00fcFUoDXCucp5yy2ujqPssDVGaWNiUliNz_awD0gc",
    "IEBYSJGNhXIlrQo58ykXm2Zx3yll9ZlTtToPo17QQiY",
    "Lai6IU6d7GQagXR7AvGTrnXgSld3z8EIg_fv3fOZ1Wg",
    "hvDXhwmGcJQsBCA2OtjuLAcwAMpDsaU0nkovcKOqWNE",
    "ikuur8Q4k8q3VcyA7dC-mNjZBkReDTU-CG4niTE7OTU",
    "qvzNLj2vh9o4SEXOfMiYDuvTykdsWCNg0wTdlr0AEIM",
    "wzW15bhCkvksxVvuJ8RF3xi8i64ln1jo_76BC2oa1ug",
    "zOeBXhxvIS4ZzmQcLlxKuEAOGGByjOqa1z2IoVx_YDQ"
  ],
  "iss": "https://example.com/issuer",
  "iat": 1683000000,
  "exp": 1883000000,
  "vct": "https://bmi.bund.example/credential/pid/1.0",
  "age_equal_or_over": {
    "_sd": [
      "Fc8I_07LOcgPwrDJKQyIGO97wVsOplMLjHvRC4R4-Wg",
      "XLtLjadUWc9zN_9hMJRoqy46UsCKb1IshZuuqUFKSCA",
      "aoCCzsC7p4qhZIAh_idRCSCa641uycnc8zPfNWz8nx0",
      "f1-P0A2dKWavv1uFnMX2A7-EXxvhoxv5aHhuEIN-W64",
      "k5hy2r018vrsJjo-Vjd6g6yt7AaonKonniuJ9zel3jo",
      "qp7Z_Ky1Yip0sYgDO3zVug2MFuPNjHxksBDnJZ4aI-c"
    ]
  },
  "_sd_alg": "sha-256",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
      "y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
    }
  }
}
SD-JWT 化前のペイロード
{
  "vct": "https://bmi.bund.example/credential/pid/1.0",
  "given_name": "Erika",
  "family_name": "Mustermann",
  "birthdate": "1963-08-12",
  "source_document_type": "id_card",
  "address": {
    "street_address": "Heidestraße 17",
    "locality": "Köln",
    "postal_code": "51147",
    "country": "DE"
  },
  "nationalities": [
    "DE"
  ],
  "gender": "female",
  "birth_family_name": "Gabler",
  "place_of_birth": {
    "locality": "Berlin",
    "country": "DE"
  },
  "also_known_as": "Schwester Agnes",
  "age_equal_or_over": {
    "12": true,
    "14": true,
    "16": true,
    "18": true,
    "21": true,
    "65": false
  }
}

参考情報

Key Proof JWT

キーバインディングという仕組みを実現するため、Verifiable Credential 発行依頼時に、Verifiable Credential 発行者に公開鍵を渡します。Verifiable Credential 発行者は、受け取った公開鍵を発行する Verifiable Credential に埋め込みます。

しかし、受け取った公開鍵を盲目的に信用するわけにはいかないので、その公開鍵を提示した者が対応する秘密鍵を持っているかどうかを確認します。その確認ために使うのが鍵証明 (Key Proof) です。公開鍵を提示する者は、その公開鍵を含むデータに対して対応する秘密鍵で署名し、鍵証明という形にして Verifiable Credential 発行者に渡します。

credential_verification_13.png

OpenID for Verifiable Credential Issuance という仕様では、鍵証明のフォーマットとして JWT をベースとした Key Proof JWT を定義しています。

key_proof_jwt.png

Key Proof JWT の例
Key Proof JWT
eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiblVXQW9BdjNYWml0aDhFN2kxOU9kYXhPTFlGT3dNLVoyRXVNMDJUaXJUNCIsInkiOiJIc2tIVThCalVpMVU5WHFpN1N3bWo4Z3dBS18weGtjRGpFV183MVNvc0VZIn19.eyJhdWQiOiJodHRwczovL2NyZWRlbnRpYWwtaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNzAxOTYwNDQ0LCJub25jZSI6IkxhclJHU2JtVVBZdFJZTzZCUTR5bjgifQ.-a3EDsxClUB4O3LeDD5DVGEnNMT01FCQW4P6-2-BNBqc_Zxf0Qw4CWayLEpqkAomlkLb9zioZoipdP-jvh1WlA
ヘッダ
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "nUWAoAv3XZith8E7i19OdaxOLYFOwM-Z2EuM02TirT4",
    "y": "HskHU8BjUi1U9Xqi7Swmj8gwAK_0xkcDjEW_71SosEY"
  }
}
ペイロード
{
  "aud": "https://credential-issuer.example.com",
  "iat": 1701960444,
  "nonce": "LarRGSbmUPYtRYO6BQ4yn8"
}

参考情報

セキュリティイベントトークン

RFC 8417: Security Event Token (SET) は、セキュリティイベントトークン (通称 SET) を定義しています。仕様書に "A SET is a JWT [RFC7519] conforming to this specification." と書かれている通り、SET は JWT の一種です。

SET は、セキュリティやアイデンティティに関するイベントを表現します。例えば、パスワードリセット (Section 2.1.1. SCIM Example)、ログアウト (Section 2.1.2. Logout Example)、同意取得 (Section 2.1.3. Consent Example)、アカウント無効化 (Section 2.1.4. RISC Example)、といったイベントを表現します。

セキュリティイベントトークンを送受信する仕組みを定義したものが OpenID Shared Signals Framework Specification 1.0 (通称 SSF) という仕様です。なお、SSF では、SET のプロファイリングをおこなっています (= 要求事項を追加しています)。例えば、SSF に準拠する SET は typsecevent+jwt であると JWS ヘッダで明示しなければなりません。

下記は Shared Signals 関連の仕様です。

SET の例
SET
eyJ0eXAiOiJzZWNldmVudCtqd3QiLCJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLmNvbS8iLCJqdGkiOiI3NTZFNjk3MTc1NjUyMDY5NjQ2NTZFNzQ2OTY2Njk2NTcyIiwiaWF0IjoxNTIwMzY0MDE5LCJ0eG4iOjg2NzUzMDksImF1ZCI6IjYzNkM2OTY1NkU3NDVGNjk2NCIsInN1Yl9pZCI6eyJmb3JtYXQiOiJwaG9uZSIsInBob25lX251bWJlciI6IisxIDIwNiA1NTUgMDEyMyJ9LCJldmVudHMiOnsiaHR0cHM6Ly9zY2hlbWFzLm9wZW5pZC5uZXQvc2VjZXZlbnQvcmlzYy9ldmVudC10eXBlL2FjY291bnQtZGlzYWJsZWQiOnsicmVhc29uIjoiaGlqYWNraW5nIn19fQ.qV5HuFVpBkpSB1x0uOOPFATHd7fI02exAmpNz0wxuwQT-Gn9VYzqpuhRbyqlbA6Mmo87rvt9Bw2ucxr9LisV5g
ヘッダ
{
  "typ": "secevent+jwt",
  "alg": "ES256"
}
ペイロード
{
  "iss": "https://idp.example.com/",
  "jti": "756E69717565206964656E746966696572",
  "iat": 1520364019,
  "txn": 8675309,
  "aud": "636C69656E745F6964",
  "sub_id": {
    "format": "phone",
    "phone_number": "+1 206 555 0123"
  },
  "events": {
    "https://schemas.openid.net/secevent/risc/event-type/account-disabled": {
      "reason": "hijacking"
    }
  }
}

関連情報

おわりに

OAuth と OpenID Connect の分野における JWT の様々な利用例を見てきました。JWT が用途を限定しない汎用データフォーマットであることを再確認できたと思います。

JWT の解説記事や解説動画は巷に溢れていますので、好きなものを選んで視聴されるのがよいと思います。なお、標準仕様策定者・実装者レベルのマニアックな詳細に興味がある方は、Authlete 社が公開している動画集を是非ご覧ください!

2024 年 11 月にリリースされた Authlete 3.0 もよろしくお願いします! (発表文書)

42
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?