For Authlete 2.x documentation, see 2.x version.
1. はじめに
この文書は、『OpenID for Verifiable Credential Issuance』(OID4VCI) 仕様、および Authlete が当仕様をどのようにサポートするかを解説します。 優に百枚を超える図を用いて様々な概念の概要と詳細を丁寧に説明します。読者が文書内を行ったり来たりする必要に迫られることなく内容を理解できるよう、説明前の概念を前提知識として使うことを注意深く避けています。また、読者が途中で迷子にならないよう、全体像を説明している途中で詳細説明に入らないようにしています。これらの配慮により、この文書は仕様本体よりも格段に読みやすくなっています。そのため、事前にこの文書を読んでおけば仕様を読む際に大きな助けとなるでしょう。 変更履歴| 日付 | 変更内容 |
|---|---|
| 2023 年 10 月 22 日 | 初版公開。 |
| 2023 年 10 月 27 日 | 『OID4VCI 実装』セクションに幾つかサブセクションを追加。 |
| 2023 年 11 月 15 日 | 下記の仕様変更に追随するため、説明と図を更新。クレデンシャルイシュアの credentials_supported メタデータの型が JSON 配列から JSON オブジェクトに変更された。クレデンシャルオファー内の credentials 配列の要素の型が文字列のみとなった。クレデンシャルオファー内の credentials 配列の要素が credentials_supported オブジェクト内のキーを参照するようになった。 |
| 2023 年 11 月 24 日 | 『OID4VCI デモ』セクションを追加。下記の仕様変更に追随するため説明と図を更新。SD-JWT VC 仕様のドラフト 01 で type クレームが vct クレームへと変更された。 |
| 2023 年 12 月 30 日 | mdoc デモ用のセクションを追加。下記の仕様変更に追随するため説明と図を更新。クレデンシャルオファーの credentials が credential_configurations に変更、user_pin_required が tx_code オブジェクトで置き換え、credential_configurations_supported への名称変更、proof_types_supported が proof_types に変更、credential_response_encryption オブジェクトへの統合、Data Integrity Proof 追加、SD-JWT VC 取り込み、credential_definition 削除と vct/claims の階層移動、/.well-known/jwt-issuer が /.well-known/jwt-vc-issuer に変更、_sd_hash が sd_hash に変更。 |
| 2024 年 1 月 31 日 | 下記の仕様変更に追随するために更新。credential_response_encryption へのメタデータ統合、クレデンシャルレスポンスから format 削除、RAR の format 復活と credential_configuration_id または format 必須化、credential_configurations が credential_configuration_ids に名称変更。 |
| 2024 年 2 月 3 日 | 下記の仕様変更に追随するために更新。cryptographic_suites_supported が credential_signing_alg_values_supported に名称変更。proof_types が proof_types_supported に名称変更され型が JSON オブジェクトへ変更。 |
| 2024 年 5 月 11 日 | 『OID4VCI デモ』セクションに『POTENTIAL 相互運用性イベント / トラック 1 / Light プロファイル』セクションを追加。 |
| 2024 年 6 月 5 日 | mdoc ペイロードの不具合修正を反映するため、『OID4VCI デモ』の『POTENTIAL 相互運用性イベント / トラック 1 / Light プロファイル』セクションを更新。(参考: authlete/cbor PR 10) |
| 2024 年 6 月 6 日 | 『OID4VCI デモ』セクションに『POTENTIAL 相互運用性イベント / トラック 2 / Light プロファイル』セクションを追加。 |
| 2024 年 6 月 11 日 | COSE_Key フォーマットの不具合修正を反映するため、『4.3.2.5. 手順 5 : CWT 鍵証明』セクションを更新。 |
| 2024 年 6 月 28 日 | 『OID4VCI デモ』セクションに『POTENTIAL 相互運用性イベント / トラック 2 / Full プロファイル』セクションを追加。 |
2. OID4VCI 仕様
OID4VCI 仕様は、Verifiable Credential (検証可能な資格証明) の発行に関する規則を定義します。2.1. 中心となる技術用語
2.1.1. Verifiable Credential
『Verifiable Credential 』(検証可能な資格証明) は、OID4VCI 仕様の中心となる技術用語です。以降、本文書では VC と呼ぶことにします。 用語内の『Credential』(資格証明) は、一人のユーザまたは複数のユーザ (または特定可能な任意の実体) に関するデータ集合を表しています。氏名や生年月日といった情報はユーザに関するデータの例です。 用語内の『Verifiable』(検証可能な) は、データ集合が改竄されていないことを検証可能であることを示しています。技術的には、データ集合が電子的に署名されていることを意味します。
2.1.2. Credential Issuer
VC は『Credential Issuer 』(資格証明発行者) により発行されます。クレデンシャルイシュアも技術用語です。仕様はクレデンシャルイシュアの動作を記述しています。
2.1.3. Access Token
VC をクレデンシャルイシュアから取得するためには、発行を要求する際にクレデンシャルイシュアに対して『Access Token 』(アクセストークン) を提示しなければなりません。このアクセストークンとは、OAuth 2.0 の中心となる仕様である RFC 6749 で定義されているアクセストークンを指します。
2.1.4. Authorization Server
アクセストークンは『Authorization Server 』(認可サーバ) により発行されます。認可サーバの基本的な動作は RFC 6749 で定義されており、また、その RFC 6749 を中心として、認可サーバの追加機能を定義する数多くの標準仕様が存在します。OID4VCI 仕様も同様に、VC 発行に使えるアクセストークンを認可サーバが発行できるようにするため、認可サーバに対する追加仕様を定めています。
2.1.5. Wallet
OID4VCI 仕様では、VC を取得するために認可サーバやクレデンシャルイシュアとやりとりするソフトウェアアプリケーションを『Wallet 』(ウォレット) と呼びます。技術的には、VC 発行の文脈ではウォレットは OAuth 2.0 のクライアントアプリケーションとして動作します。そのため、OID4VCI 仕様の文脈では、技術的な観点からは、ウォレットという用語とクライアントアプリケーションという用語は相互に交換可能です。
ただし、本文書では説明しない『OpenID for Verifiable Presentations』の文脈では、ウォレットはクライアントアプリケーションではなくサーバとして動作するので注意してください。
2.1.6. 関係性
次の図は中心となる技術用語間の関係を示しています。
2.2. アクセストークン発行の概要
2.2.1. 事前認可コードフロー
仕様では、VC 発行に使えるアクセストークンを発行するための方法を幾つか定義しています。 それらのうちの一つは完全に新しいもので、『Pre-Authorized Code Flow 』(事前認可コードフロー) と呼ばれます。このフローでは、最初の手順として、ウォレットはクレデンシャルイシュアから『pre-authorized code』(事前認可コード) を取得します。





2.2.2. 認可コードフロー
事前認可コードフロー以外の方法は、伝統的な『Authorization Code Flow 』(認可コードフロー) (RFC 6749, 4.1. Authorization Code Grant) の拡張です。 認可コードフローを復習しましょう。 認可コードフローでは、最初の手順として、クライアントアプリケーション (OID4VCI の文脈ではウォレット) はウェブブラウザを介して認可サーバの『Authorization Endpoint 』(認可エンドポイント) (RFC 6749, 3.1. Authorization Endpoint) に『Authorization Request 』(認可リクエスト) を送ります。






issuer_stateリクエストパラメーターauthorization_detailsリクエストパラメーターscopeリクエストパラメーター

issuer_state リクエストパラメーターは OID4VCI 仕様で定義される新しいパラメーターです。
authorization_details リクエストパラメーターは RFC 9396 OAuth 2.0 Rich Authorization Requests で定義されています。この仕様は RAR と略して呼ばれることがあります。
scope リクエストパラメーターは RFC 6749 The OAuth 2.0 Authorization Framework で定義されているパラメーターです。
この文書を書いている時点では、上記のパラメーター群が組み合わされて使われた場合について仕様は何も言及していません。これらの仕組みが相互排他の関係にあるのか、それとも共存可能なのか明確ではありません。Authlete の現在の実装は、これらの仕組みを全て考慮に入れ、リクエストパラメーターを介して指定された全ての VC の発行に使えるアクセストークンを生成します。
2.2.3. 認可コードフロー + issuer_state
issuer_state リクエストパラメーターは OID4VCI 仕様で定義されています。このリクエストパラメーターを使うためには、認可リクエストをおこなう前に、ウォレットはクレデンシャルイシュアから『Issuer State 』(イシュアステート) を取得しておく必要があります。

issuer_state リクエストパラメーターの値として含む認可リクエストをおこないます。



2.2.4. 認可コードフロー + authorization_details
RAR 仕様 (RFC 9396) は、認可に関する詳細情報を伝えるための汎用的なパラメーターとしてauthorization_details を定義しています。このパラメーターをどのように使うかは、それぞれの運用に任されています。
このパラメーターの値は JSON 配列であり、配列の各要素は JSON オブジェクトです。このオブジェクトは『RAR オブジェクト』と呼ばれます。

"type" プロパティだけは必須です。このプロパティは RAR オブジェクトが何を表しているのかを示します。
そして OID4VCI 仕様は、ウォレットが欲しい VC に関する情報を含む RAR オブジェクトであることを示すための特別な "type" 値として "openid_credential" を定義しています。

2.2.5. 認可コードフロー + scope
scope リクエストパラメーターは OAuth 2.0 の中心仕様 (RFC 6749) で定義されている伝統的なパラメーターの一つです。クライアントアプリケーションが欲しい権限を列挙するのが、このパラメーターの元来の用途です。ユーザがリクエストを承認すれば、認可サーバは要求された権限を持つアクセストークンを発行します。

scope リクエストパラメーターは元々意図していた用途外でも利用されてきました。そして、OID4VCI 仕様も同様に scope リクエストパラメーターの使い方を拡張します。
クレデンシャルイシュアは、自身が発行可能な VC を『Credential Configuration 』(クレデンシャル設定) として管理しており、そのリストをある場所で公開しています。各クレデンシャル設定は "scope" プロパティを持つことがあります。

"scope" プロパティの値を scope リクエストパラメーターに含めることができます。

"scope" プロパティに持つ場合もあります。
OAuth 2.0 の中心仕様 (RFC 6749)
が未知の
scope 値を無視するように認可サーバに要求しているため、クレデンシャル設定の
"scope" プロパティの値をサポートするスコープ値として認可サーバに明示的に登録する必要がある可能性が高いです。加えて、OpenID Federation
を利用している場合、VC 発行のための scope 値をメタデータポリシーが意図せずに削除することがないよう、注意が必要です。2.3. クレデンシャル発行の概要
認可サーバからアクセストークンを取得すれば、ウォレットはアクセストークンを提示することにより、クレデンシャルイシュアに VC の発行を要求することができます。 基本的な手順では、ウォレットはクレデンシャルイシュアのクレデンシャルエンドポイントにアクセストークンを含むクレデンシャルリクエストを送ります。

2.3.1. 遅延クレデンシャル発行
しかし、要求された時点で VC が用意できていないこともありえます。たとえば、裏で時間のかかるオフライン処理が走っているかもしれません。 このような場合、クレデンシャルイシュアは代わりに『Transaction ID 』(トランザクション ID) を発行します。


"error":"issuance_pending") を返すでしょう。このような場合、ウォレットは後ほど再び『Deferred Credential Request 』(遅延クレデンシャルリクエスト) を実行します。
2.3.2. 一括クレデンシャル発行
ウォレットは一度に複数の VC を入手したいことがあるかもしれません。そのような場合のために『Batch Credential Endpoint 』(一括クレデンシャルエンドポイント) があります。 ウォレットはアクセストークンを含む『Batch Credential Request 』(一括クレデンシャルリクエスト) を一括クレデンシャルエンドポイントに送信します。


2.4. アクセストークン発行の詳細
ここまでの説明で、アクセストークン発行とクレデンシャル発行の概要を見てきました。この節ではアクセストークン発行の詳細について見ていこうと思います。2.4.1. クレデンシャルオファー
クレデンシャルイシュアが事前認可コードを発行する際、それを直接発行する代わりに、それを内包する『Credential Offer 』(クレデンシャルオファー) を発行します。



2.4.1.1. 値によるクレデンシャルオファー発行
クレデンシャルオファーをウォレットに送信するために URL が使われます。この URL はcredential_offer というクエリパラメーターを伴う『Credential Offer Endpoint 』(クレデンシャルオファーエンドポイント) です。そのクエリパラメーターの値はクレデンシャルオファーの内容です。

credential_offer_endpoint というクライアントメタデータを定義しています。しかし、仕様が言及している「URL を QR コードで表現する手法」が用いられる場合は特に、どのウォレットに対してクレデンシャルオファーを発行しようとしているかをクレデンシャルイシュアは知ることができないので、クレデンシャルイシュアはウォレットのメタデータの情報を知りえません。このような場合のため、クレデンシャルオファーエンドポイントの代替として openid-credential-offer:// が定義されています。

上記のような理由から、クレデンシャルイシュアはクレデンシャルオファーの生成と転送をそれぞれ独自の方法で実装するでしょう。そのため、相互運用性はあまり期待できません。
2.4.1.2. 参照によるクレデンシャルオファー発行
クレデンシャルオファーは参照によってウォレットに渡されるかもしれません。具体的には、URL は発行されたクレデンシャルオファーの内容ではなく、その配置場所に関する情報を含んでいるかもしれません。この場合、その場所を示すためにcredential_offer_uri クエリパラメーターが用いられます。

credential_offer_uri クエリパラメーターの値は、発行されたクレデンシャルオファーの内容を返すエンドポイントを指しています。



2.4.1.3. クレデンシャルオファーの内容
クレデンシャルオファーの実際の内容は JSON オブジェクトです。
"credential_issuer" プロパティの値として置かれます。

"credential_configuration_ids"
配列に置かれます。配列要素の詳細については後ほど紹介します。

"grants" プロパティがあります。"grants" プロパティの値は JSON オブジェクトです。その "grants" JSON オブジェクト内のキーは、authorization_code のようなグラントタイプ (認可種別) の識別子です。
"grants" JSON オブジェクト内の各エントリの値もまた JSON オブジェクトで、それぞれ、キーが示すグラントタイプに関連するプロパティ群を含んでいます。
イシュアステートの場合は、その値は "grants" JSON オブジェクト内の "authorization_code" JSON オブジェクト内の "issuer_state" プロパティの値として置かれます。

"grants" JSON オブジェクト内の "urn:ietf:params:oauth:grant-type:pre-authorized_code" JSON オブジェクト内の "pre-authorized_code" プロパティの値として置かれます。ここで登場する "urn:ietf:params:oauth:grant-type:pre-authorized_code" は、事前認可コードフローに割り当てられた新しい識別子です。

"urn:ietf:params:oauth:grant-type:pre-authorized_code" JSON オブジェクトは、トランザクションコード
の情報を保持する "tx_code" JSON オブジェクトを含むことがあります。tx_code
オブジェクトが含まれていた場合、事前認可コードを用いたトークンリクエストはトランザクションコードを含まなければなりません。
詳細については後ほど記述します。


2.4.1.4. クレデンシャルオファー内の “credential_configuration_ids”
クレデンシャルオファー内の"credential_configuration_ids"
プロパティは、クレデンシャルイシュアが提供する VC に関する設定を保持しています。
このプロパティの値は JSON 配列です。各配列要素は JSON 文字列です。
要素の値はクレデンシャル設定の識別子を表しています。

2.4.2. 事前認可コードフローの詳細
事前認可コードが得られれば、ウォレットはその事前認可コードを用いてトークンリクエストを実行できます。 次の表は、事前認可コードフローに準拠するトークンリクエストで必要とされるリクエストパラメーター群を列挙したものです。| パラメーター | 説明 |
|---|---|
grant_type | 値は "urn:ietf:params:oauth:grant-type:pre-authorized_code" でなければなりません。 |
pre-authorized_code | 事前認可コード |
tx_code | トランザクションコード。クレデンシャルオファーが tx_code オブジェクトを含んでいれば、このパラメーターは必須です。 |
tx_code オブジェクトと共に発行されていれば、tx_code パラメーターは必須になります。
この場合、何らかの方法でトランザクションコードがユーザに届けられるものと想定されます。
tx_code
オブジェクトは次表に挙げるプロパティを含んでいることがあります。
| パラメーター | 説明 |
|---|---|
length | トランザクションコードの長さ。 |
input_mode | トランザクションコードの入力モード。事前定義されている値は "numeric" と "text"。 |
description | 配送チャネルなど、トランザクションコードに関する情報。 |
private_key_jwt クライアント認証が用いられる場合、client_assertion リクエストパラメーターと client_assertion_type リクエストパラメーターが必要となります。
OID4VCI 仕様の野心的な試みの一つは、認可サーバの設定に依存しますが (具体的には
pre-authorized_grant_anonymous_access_supported
サーバメタデータが true の場合ですが)、クライアントアプリケーションを特定する情報を何も含まないトークンリクエストが許容される場合があります。
実際にそのようなトークンリクエストが実行された場合、特定のクライアントアプリケーションに紐付かないアクセストークンが発行されることになります。access_token, token_type, expires_in) に加えて、c_nonce レスポンスパラメーターと
c_nonce_expires_in レスポンスパラメーターを含む場合があります。
これらのレスポンスパラメーター群の詳細は後ほど説明します。
2.4.3. 発行可能クレデンシャル
VC 用アクセストークンを発行する手段が幾つか用意されているものの、アクセストークンの実装の観点から言えば、全て一つの共通の目標に収束します。それは、発行可能な VC 種別に関する情報をアクセストークンに紐付けることです。 この文書では、その情報を『Issuable Credential 』(発行可能クレデンシャル) と呼びます。ただし、この用語は公式のものではないので、その点はご留意ください。 クレデンシャルオファーの"credential_configuration_ids" 配列の要素 JSON 文字列です。
それらは、クレデンシャル設定を参照することにより発行可能クレデンシャルを間接的に指定しています。

"credential_configuration_ids" 配列の要素数は 1 ですが、配列が複数の要素を含むことはありえます。
それらの要素により、クレデンシャルオファーが表す発行可能クレデンシャル群の集合が形成されます。


issuer_state リクエストパラメーターを用いる認可リクエストは、イシュアステートを含むクレデンシャルオファーで指定される発行可能クレデンシャル群に紐付いたアクセストークンを要求していると言えます。

"type":"openid_credential" を持つ RAR オブジェクトは、発行可能クレデンシャルのベースとなるクレデンシャル設定を
credential_configuration_id プロパティを使って指定します。

format プロパティを使うこともあります。

openid_credential タイプの RAR オブジェクトでは、
credential_configuration_id プロパティと
format プロパティは相互排他の関係にあります。scope リクエストパラメーター内の値は、クレデンシャル設定の "scope" プロパティを介して一つ以上の発行可能クレデンシャルを間接的に指定するかもしれません。




2.5. クレデンシャル検証
VC のフォーマットを議論するためには、それらが意図する目的を理解する必要があります。VC の検証処理を一つ一つ見ていくことにしましょう。 まず始めに、クレデンシャルイシュアは VC に含めるデータを用意します。この例では、name (氏名)、birthdate (生年月日)、address (住所) を使います。






ただし、技術的には、VC とそれに対応する VP が完全に一致する場合もあります。


2.5.1. キーバインディング
ところで、ベリファイアは次の事項をどうすれば確認できるでしょうか?- VP が当ホルダーによって提示されたこと
- VP の元となった VC はクレデンシャルイシュアが当ホルダーに対して発行したものであること



厳密に言えば、キーバインディングの仕組みに用いられる公開鍵は常にホルダーと結びついているとは限りません。かわりに、ホルダーが管理しているデバイスのうちの一つと結びついているか、さらには、ホルダーが直接管理しているわけではないデバイスと結びついているかもしれません。このような場合を考慮し、この仕組みは『ホルダーバインディング』とは呼ばれなくなりました。







2.6. 選択的開示
VP を提示する際、ホルダーは VC の内容の一部のみを開示することを選ぶかもしれません。例えば、VC が氏名、生年月日、住所を含んでいるとき、ホルダーは氏名と生年月日のみを開示し、住所の情報は省くことを選択するかもしれません。 このように情報を選んで開示することを『Selective Disclosure 』(選択的開示) と言います。

- 理論の複雑さ
- 実装の容易さ
- ライセンス費用
- 使用する際の法的制限
- ハードウェアセキュリティモジュール製品によるサポート
- アルゴリズムの頑健性/安全性を業界がどの程度信じているか
2.6.1. SD-JWT
SD-JWT は JWT (RFC 7519 JSON Web Token (JWT)) を利用して選択的開示を実現するフォーマットです。 通常の JWT のペイロード部には、クレーム名とクレーム値の組が含まれています。




"_sd" 配列内に置かれます。


~) で連結し、一つの文字列を作ります。




公開鍵を埋め込まず、代わりに参照を含めることもあります。

キーバインディング JWT を生成するのはホルダー/ウォレットの役目であり、クレデンシャルイシュアの役目ではありません。そのため、VC フォーマットが SD-JWT に基づいている場合でも、クレデンシャルイシュアがそれを発行する際には VC にキーバインディング JWT は含まれません。


2.7. VC フォーマット
2.7.1. VC フォーマットをめぐる混乱
VC フォーマットをめぐる混乱は、複数の競合する仕様が存在し、それぞれが課題を抱え、依然として開発中であることから来ています。また、様々な国家、地域、業界の組織が異なるフォーマットを推進していることも状況を複雑にしています。 VC となると、多くの人が W3C Verifiable Credentials Data Model (W3C VCDM) を思い浮かべます。これは主に、当文書が『イシュア・ホルダー・ベリファイア』の三者間モデルを定義している一次情報源とみなされることが多いからです。しかし、W3C VCDM 自体も完全無欠というわけではなく、実際に議論は続いています。バージョン 1.1 は 2022 年 3 月 3 日にリリースされましたが、現在バージョン 2.0 の議論が進んでいます。 外部から観察したときに、さらに状況を複雑にしているのは、Securing Verifiable Credentials using JOSE and COSE (w3c/vc-jose-cose) という名前の仕様です。その仕様は Abstract セクションで “defines how to secure credentials and presentations conforming to the VC-DATA-MODEL” と述べていますが、当仕様は W3C VCDM の要求事項と衝突している部分が幾つかあります。例えば、W3C VCDM は"typ" ヘッダパラメーターの値は "JWT" であることを要求していますが、w3c/vc-jose-cose はこの要求に従っていません。また、W3C VCDM は VC や VP を埋め込むための場所として "vc" クレームと "vp" クレームを導入していますが、w3c/vc-jose-cose はこれらのクレームを利用していません。
さらに新参者を混乱させるのは、OID4VCI 仕様は W3C VCDM に基づくクレデンシャルフォーマットのプロファイルとして jwt_vc_json、jwt_vc_json-ld、ldp_vc を定義しているものの、OpenID 業界で当仕様に貢献しているほとんどの人は、それらのクレデンシャルフォーマットプロファイル群をサポートする気がないことです。彼らは現在、その労力を SD-JWT や ISO/IEC 18013-5 (Personal identification - ISO-compliant driving licence - Part 5: Mobile driving licence (mDL) application) をベースとする VC フォーマットの仕様策定と実装に注いでいます。
OAuth や OpenID Connect を議論する人々にとって ISO/IEC 18013-5 が扱いにくい理由は、そのフォーマットが、Concise Binary Object Representation (CBOR) (RFC 8949) や CBOR Object Signing and Encryption (COSE) (RFC 9052, RFC 9053) というあまり馴染みのないバイナリフォーマットに基づくからです。また、ISO/IEC 18013-5 に関する詳細な技術情報がオンライン上であまり得られないのは、ISO 標準文書は購入しないと手に入らないからです。
VC 検証のための公開鍵を配布する方法も課題です。ベリファイアが VC を受け取った際、その VC が
OID4VCI 仕様に従って発行されたかどうかは分かりません。そのため、クレデンシャルイシュアのメタデータ
(/.well-known/openid-credential-issuer)
を開始点として公開鍵を探すことをベリファイアに強制することは理想的とは言えません。
代替となる開始点として、ウェルノーンパス /.well-known/jwt-issuer が
SD-JWT-based Verifiable Credentials (SD-JWT VC)
という仕様内で提案されました。しかし、パス名が汎用的過ぎ、JWT
発行関連の他の仕様群と簡単に衝突する恐れがあるので、後日パス名は
/.well-known/jwt-vc-issuer に変更されました。
それでも依然として、このパス名は、VC のフォーマットが JWT
ベースであることを不必要に想定しているという問題を抱えています。
そのため、この解決方法を好まない人々もいます。
実際に OpenID Federation を活用しているイタリアのエコシステムは
/.well-known/jwt-vc-issuer を使わないことを決めました。
彼らは代わりに openid_credential_issuer
という新しいエンティティタイプ識別子を定義し、エンティティコンフィギュレーションの
"metadata"."openid_credential_issuer" オブジェクトに
VC 検証用の公開鍵を埋め込むことにしました。
関連する議題として、OAuth 2.0 Attestation-Based Client Authentication
と呼ばれる新しいクライアント認証方式が現在開発中です。
この方式のため、ウォレットはあらかじめ『Attester 』(証人)
から『Wallet Attestation 』を取得しておく必要があります。
というのは、クライアント認証を実行するときにそれが必要になるからです。
アテステーションの受け手 (例えば認可サーバ) は、アテステーションの署名を検証するための公開鍵をアテスタから取得しなければなりません。
ここで、アテステーション用の公開鍵配布は、先に述べた VC と似たような問題となります。
そして、/.well-known/jwt-vc-issuer がここでも選択肢の一つとして提案されています。
これはまさに予想された通りの懸念事項です。つまり、アテスタとクレデンシャルイシュアを同じサーバ上で動かすことが技術的に不可能になるのです
(それら二つを同じサーバ上で動かすことが概念的に適切かどうかは別問題です)。
加えて、アテステーションのフォーマットが JWT かどうかは本質ではないのです。
しかし、アテステーションベースのクライアント認証に関してより深刻な問題は、
基本的な概念について完全な合意にまだ達していないことです (参照:
ISSUE 61)。
2.7.2. VC フォーマットの本質的機能
前節で述べたように、VC フォーマットに関する多くの課題があります。しかし、VC フォーマットに期待される本質的機能は次のものに要約できると我々は考えています。- 検証可能性
- キーバインディング
- 選択的開示
2.7.3. SD-JWT VC
SD-JWT は汎用的なデータフォーマットで、それ自体は VC フォーマットではありません。しかし、特定の要求事項を追加することにより、SD-JWT に基づく VC フォーマット定義することは可能です。SD-JWT-based Verifiable Credentials (SD-JWT VC) はそのような目的で作られた仕様です。 SD-JWT の概要については既に見てきたので、ここでは SD-JWT VC のポイントを下表に簡潔に紹介するにとどめます。詳細については SD-JWT VC 仕様を参照してください。 | メディアタイプ | application/vc+sd-jwt | | クレデンシャルイシュアが署名する JWT | 場所 | 名前 | 要否 | 説明 | | ヘッダ | alg | 必須 | JWT 仕様 (RFC 7519) で要求されている通り。 | | typ | 必須 | vc+sd-jwt | | ペイロード | iss | 必須 | クレデンシャルイシュアの識別子。 | | iat | 必須 | 発行日時 | | nbf | 任意 | VC 無効期間終了日時 (VC 有効期間開始日時) | | exp | 任意 | 有効期限終了日時 | | cnf | 条件により必須 | 暗号的キーバインディングが要請されていれば必須。 公開鍵を表す “jwk” プロパティを含むべき。 (参照: RFC 7800) | | vct | 必須 | VC 種別を示す識別子。 | | status | 任意 | VC の状態確認方法に関する情報。 | | sub | 任意 | VC のサブジェクトの識別子。 | | キーバインディング JWT | 場所 | 名前 | 要否 | 説明 | | ヘッダ | alg | 必須 | JWT 仕様 (RFC 7519) で要求されている通り。 | | typ | 必須 | kb+jwt (SD-JWT 仕様で要求されている通り) | | ペイロード | iat | 必須 | 発行日時 | | aud | 必須 | キーバインディング JWT の受信者。典型的にはベリファイア。 | | nonce | 必須 | リプレイ攻撃の軽減策のための文字列 | | sd_hash | 必須 | クレデンシャルイシュアが署名した JWT と選択したディスクロージャ群のハッシュ値。 | クレデンシャルイシュアが署名する JWT 内のvct クレームの実際の値、およびそのクレデンシャル種別固有の追加クレーム群は、それぞれの運営主体が決めることであり、SD-JWT VC 仕様の対象範囲外です。
2.7.4. 他の VC フォーマット
この文書ではjwt_vc_json などの他の VC フォーマットについては説明しません。
2.8. アクセストークン用のクレデンシャル情報
VC フォーマットについて見てきたので、アクセストークン用のクレデンシャル情報の議題に戻ることができます。
2.8.1. RAR オブジェクト内のクレデンシャル情報
RAR オブジェクトのタイプがopenid_credential の場合、その RAR
オブジェクトは発行可能クレデンシャルに関する情報を含んでいます。
そのような RAR オブジェクトは必ず credential_configuration_id
プロパティまたは format プロパティを含んでいなければなりません。
この二つのプロパティは相互排他の関係にあります。
2.8.1.1. credential_configuration_id プロパティを含む RAR オブジェクト
credential_configuration_id
プロパティの値は、クレデンシャルイシュアメタデータ内のクレデンシャル設定を参照します。

credential_configuration_id プロパティが参照するクレデンシャル設定は、
発行可能クレデンシャルを構築するためのベースとしてのみ使われるということが推察されます。
別の言い方をすると、クレデンシャルオファー内で参照されるクレデンシャル設定とは異なり、RAR
オブジェクト内で参照されるクレデンシャル設定は、クレデンシャルフォーマット (及び他の必須プロパティ;
vc+sd-jwt フォーマットの場合における vct や mso_mdoc フォーマットの場合における doctype など)
の情報を取得するためだけに利用されるということです。結果として、RAR
オブジェクトにはウォレットが入手したいクレーム群が列挙されることが想定されます。
クレーム群を列挙する方法は、クレデンシャルのフォーマットによって異なります。例えば、仕様書内の例によれば、
jwt_vc_json フォーマットではクレーム群を列挙するのに credential_definition
プロパティを用います。
mso_mdoc フォーマットは claims プロパティを用います。
2.8.1.2. format プロパティを含む RAR オブジェクト
credential_configuration_id プロパティの代わりに format プロパティを使う場合、
RAR オブジェクトは発行可能クレデンシャルに関する完全な情報を含まなければなりません。
下記の例では VC フォーマットとして mso_mdoc が指定されています。このフォーマットでは
doctype プロパティが必須なので、結果として doctype プロパティも含まれています。
2.8.2. クレデンシャル設定内のクレデンシャル情報
クレデンシャル設定の情報は『Credential Issuer Metadata 』(クレデンシャルイシュアメタデータ) の一部として記述されます。 メタデータは JSON オブジェクトで、credentials_configurations_supported
JSON オブジェクトを含んでいます。そのオブジェクト内のエントリは、クレデンシャルイシュアがサポートする
VC のクレデンシャル設定を表しています。

format プロパティは全ての対応クレデンシャルオブジェクトに含まれていますが、claims
プロパティは幾つかのフォーマットの場合のみ存在します。
2.9. クレデンシャル発行の詳細
これまでの説明でアクセストークン発行の詳細を見てきました。次はクレデンシャル発行の詳細について見ていきます。2.9.1. 鍵証明
『クレデンシャル検証』の節で説明したとおり、キーバインディング可能な VC を取得したいのであれば、ウォレットは鍵証明を提供することになります。
2.9.1.1. 鍵証明 JWT
定義により、鍵証明は公開鍵またはその鍵への参照を含んでいます。JWT に基づく鍵証明の場合、鍵情報を含めるために次に挙げる複数の方法を利用できます。鍵証明 JWT は、これらのうちの一つだけを使わなければなりません。jwkヘッダパラメーター (RFC 7515, 4.1.3)x5cヘッダパラメーター (RFC 7515, 4.1.6)kidヘッダパラメーター (RFC 7515, 4.1.4)
OID4VCI 仕様の現在のドラフトは、
kid ヘッダパラメーターと trust_chain ヘッダパラメーターを組み合わせてキーバインディング用の公開鍵を指定できるかのような印象を与えるかもしれません。しかし、補助的な規則や仕組みが導入されない限り、その組み合わせは機能しません。
jwk ヘッダパラメーターを使用する場合、公開鍵は JWK (RFC 7517 JSON Web Key (JWK)) 形式で埋め込まれます。

jwk ヘッダパラメーターの値は公開鍵を表す JSON オブジェクトです。


x5c ヘッダパラメーターを使用する場合、公開鍵用の X.509 証明書を用意する必要があります。その証明書の DER 表現を base64 でエンコードしたものを x5c JSON 配列の一番目の要素として含めなければなりません。証明書チェーンも用意できるのであれば、証明書と一緒に含めることもできます。x5c パラメーターが期待しているフォーマットの詳細については RFC 7515, 4.1.6. “x5c” (X.509 Certificate Chain) Header Parameter を参照してください。

kid ヘッダパラメーターを使用する場合、その値は公開鍵へと解決可能な DID URL であるべきです。


-
issクレームはクライアントアプリケーション (ウォレット) の識別子を表しており、ほとんどの場合は必須です。唯一の例外は、アクセストークンが事前認可コードフローで発行され、そのアクセストークン用のトークンリクエストがクライアントアプリケーションを特定する情報を含んでいない場合です。そのようなトークンリクエストは、サーバが事前認可コードフローにおいて匿名アクセスを許可している場合に受け入れられます。この機能を認可サーバがサポートしているかどうかは、真偽値サーバメタデータであるpre-authorized_grant_anonymous_access_supportedにより示されます。 -
audクレームはクレデンシャルイシュアの識別子を表しており、常に必須です。 -
iatクレームは鍵証明 JWT の発行日時を表しており、詳細な定義は RFC 7519, 4.1.6. “iat” (Issued At) Claim にあります。 -
nonceクレームは、トークンレスポンスまたはクレデンシャルレスポンスに含まれるc_nonceに対応します。トークンレスポンスがc_nonceパラメーターを含んでいる場合、nonceクレームは必須です。また、トークンレスポンスがc_nonceパラメーターを含んでいない場合でも、クレデンシャルイシュアはnonceクレームを要求するかもしれません。c_nonceの詳細は後ほど説明します。

2.9.1.2. その他の鍵証明
この文書では CWT に基づく鍵証明など、他の鍵証明の説明はしません。 それらについては OID4VCI 仕様を参照してください。2.9.2. c_nonce
鍵証明リプレイへの主要な対抗策として、クレデンシャルイシュアは鍵証明にnonce を含めることを要求するかもしれません。このクレームの値は、認可サーバまたはクレデンシャルイシュアから c_nonce レスポンスパラメーターとして提供されます。
認可サーバからのトークンレスポンスには c_nonce および c_nonce_expires_in
レスポンスパラメーターが含まれるかもしれません。c_nonce_expires_in は
c_nonce の有効期間の秒数を表しています。

c_nonce レスポンスパラメーターの値を鍵証明 JWT の nonce の値として使用します。


nonce クレームが含まれていない場合、または、指定された nonce 値の期限が切れている場合、クレデンシャルエンドポイントはエラー応答を返します。そのエラー応答は、期待される c_nonce 値、または、新しい c_nonce 値のどちらかを含んでいます。また、nonce 値が有効な場合でも、クレデンシャルレスポンスは将来の利用を想定して c_nonce を含んでいるかもしれません。いずれの場合も、クレデンシャルイシュアが nonce を鍵証明に含めることを要求する場合、クレデンシャルレスポンスに c_nonce が含まれます。

c_nonce を用いて新しい鍵証明を再生成し、その新しい鍵証明を添えて再度クレデンシャルリクエストを実行できます。

c_nonce の概要を示しています。

2.9.3. クレデンシャルリクエスト
クレデンシャルリクエストは、アクセストークンと JSON 形式のペイロードを含む HTTP POST リクエストです。ペイロードにはクレデンシャル情報および任意の鍵証明が含まれます。
クレデンシャルレスポンスの暗号化のために
credential_response_encryption
プロパティが含まれることもありますが、ここでは取り上げません。2.9.3.1. クレデンシャルリクエスト内のクレデンシャル情報
クレデンシャルリクエスト内のクレデンシャル情報は、必須の"format" プロパティと、フォーマット固有のプロパティを含んでいます。例えば、"format" プロパティの値が "jwt_vc_json" であれば、"credential_definition" プロパティがあるものと期待されます。

given_name クレーム、family_name クレーム、degree クレームのみを含む jwt_vc_json フォーマットの VC を要求するというものです。
しかし、幾つかの問題があります。
- 指定された条件を満たす発行可能クレデンシャルを決めるのは簡単ではない。
- 複数の発行可能クレデンシャルが条件を満たす可能性がある。
- 条件のわずかな違いで、異なる発行可能クレデンシャルが選ばれる可能性がある。
- 提示されたアクセストークンが指定された条件を満たす VC を要求する権限を持っているか確認するのは簡単ではない。
OID4VCI 仕様は最近、
format パラメーターと相互排他の関係となる
credential_identifier パラメーターを導入しました。
しかし、そのクレデンシャルインスタンス識別子は (クレデンシャルイシュアがサポートしていれば)
openid_credential タイプの RAR オブジェクトが使われたときのみ利用可能で、
また、仕様は、クレデンシャルインスタンス識別子は scope
パラメーターが使われたときは利用できないと述べています。credential_identifier
は限定的なユースケースに対して設計された解決法に過ぎず、上述した問題の解にはなりません。
Issue 197
の議論も参照してください。2.9.3.2. クレデンシャルリクエスト内の鍵証明情報
クレデンシャルリクエスト内の鍵証明情報は"proof" プロパティにより表されます。プロパティの値は JSON オブジェクトです。

"proof" オブジェクトには、鍵証明のフォーマットを示す "proof_type" プロパティが必ず含まれます。
"proof_type" プロパティの値が "jwt" の場合、鍵証明として JWT が使用されます。この場合、"proof" オブジェクトには "jwt" プロパティが含まれます。"jwt" プロパティの値は、鍵証明 JWT 仕様に準拠する JWT です。


2.9.4. クレデンシャルレスポンス
クレデンシャルレスポンスは JSON を含む HTTP レスポンスです。2.9.4.1. VC を含むクレデンシャルレスポンス
VC の発行に成功した場合、VC は"credential" プロパティの値として JSON に含まれます。"credential" プロパティの値のフォーマットは、VC のフォーマットに依存します。

"credential" プロパティの値は SD-JWT フォーマットの JSON 文字列です。

c_nonce レスポンスパラメーターと
c_nonce_expires_in レスポンスパラメーターが含まれることがあります。


~) を区切り文字として連結されています。なお、キーバインディング JWT はウォレットが生成するので、クレデンシャルイシュアが発行したときには VC はキーバインディング JWT を含んでいないので注意してください。

typヘッダパラメーターの値は"vc+sd-jwt"である。- ペイロードにはキーバインディングのために
"cnf"."jwk"が含まれている。 - ペイロードには
"_sd_alg"プロパティが含まれており、これはディスクロージャ用のハッシュアルゴリズムを示している。 - ペイロードには
"given_name"のようなユーザクレームが含まれていない。代わりに"_sd"配列があり、ユーザクレームのディスクロージャのダイジェスト値を保持している。


"_sd_alg" プロパティで示されるハッシュアルゴリズムを用いて計算され、"_sd" 配列に列挙されます。ダイジェスト値の順番は、SD-JWT 内のディスクロージャの順番とは独立していなければなりません。この例では、ダイジェスト値は ASCII コードの順番で並べられています。


2.9.4.2. トランザクション ID を含むクレデンシャルレスポンス
要求された VC が用意できていない場合、クレデンシャルエンドポイントは VC の代わりにトランザクション ID を返します。トランザクション ID は"transaction_id" レスポンスパラメーターの値としてクレデンシャルレスポンスに含まれます。次のものは OID4VCI 仕様から抜粋した例です。
2.9.4.3. エラーを含むクレデンシャルレスポンス
クレデンシャルリクエストを成功裡に処理できない場合、クレデンシャルエンドポイントはエラー応答を返します。エラーの種別は"error" レスポンスパラメーターで示されます。次のものは仕様から抜粋したエラーの例です。
nonce クレームの欠落や期限切れなどの理由により鍵証明が正しくない場合、エラーコード "invalid_proof" が使われます。そのような場合のエラー応答の例を仕様から転載します。
2.9.5. 遅延クレデンシャルリクエスト
ウォレットは、トランザクション ID を使い遅延クレデンシャルエンドポイントにリクエストを送ることができます。このリクエストは JSON を含む HTTP POST リクエストで、その JSON 内の"transaction_id" プロパティがトランザクション ID の値を保持しています。
2.9.6. 遅延クレデンシャルレスポンス
遅延クレデンシャルエンドポイントは JSON を含む HTTP レスポンスを返します。 VC が成功裡に発行されていれば、その JSON は"credential" プロパティを含みます。
このプロパティの値が発行された VC です。
"error" パラメーターを含むエラー応答が返されます。特に、要求された VC がまだ用意できていない場合はエラーコード "issuance_pending" が使われます。
2.9.7. 一括クレデンシャルリクエスト
クレデンシャルイシュアの一括クレデンシャルエンドポイントに一括クレデンシャルリクエストを送ることで、ウォレットは一度に複数の VC を要求することができます。 一括クレデンシャルリクエストは JSON を含む HTTP POST リクエストで、"credential_requests" JSON 配列を含んでいます。配列は JSON オブジェクトのリストで、一つ一つがクレデンシャルリクエストを表しています。




2.9.8. 一括クレデンシャルレスポンス
一括クレデンシャルレスポンスは JSON を含む HTTP レスポンスで、"credential_responses" JSON 配列を含んでいます。配列は JSON オブジェクトのリストで、一つ一つがクレデンシャルレスポンスを表しています。配列の要素は、一括クレデンシャルリクエストの "credential_requests" 配列の要素に対応しています。


c_nonce と c_nonce_expires_in をトップレベルプロパティとして含んでいるかもしれません。


2.10. 公開鍵配布
VC や VP の署名を検証するため、ベリファイアはクレデンシャルイシュアが VC に署名する際に使った秘密鍵に対応する公開鍵を取得する必要があります。 VC の署名を検証するための公開鍵を配布する方法は OIDC4VCI 仕様の範囲外の事項です。しかし、ここで幾つか提案されている手法について見ていきましょう。2.10.1. X.509 証明書の埋め込み
公開鍵配布の一つの方法として、VC 内に公開鍵用の X.509 証明書を埋め込む方法があります。 JWT ベースの VC の場合、その目的のために"x5c" ヘッダパラメーター (RFC 7515, 4.1.6) が使われることになるでしょう。
2.10.2. エンティティコンフィギュレーションに埋め込み
OpenID Federation 仕様を活用する方法では、クレデンシャルイシュアのエンティティコンフィギュレーションに公開鍵を埋め込みます。 イタリアのエコシステムでは、クレデンシャルイシュアを表す新しいエンティティタイプ識別子としてopenid_credential_issuer を定義し、その "jwks" メタデータをクレデンシャルイシュアの公開鍵を置く場所として使っています。

この文書を書いている時点では、
"jwks"、"jwks_uri"、"signed_jwks_uri" はまだクレデンシャルイシュアのメタデータとして定義されていません。2.10.3. jwt-vc-issuer
/.well-known/jwt-vc-issuer も公開鍵配布方法として提案されています。
このウェルノーンパスは、公開鍵を探す開始点となることを意図しています。

"jwks_uri" プロパティが、発行者の JWK Set の場所を示しています。
ベリファイアはその JWK Set 内に目当ての公開鍵を見つけることができるでしょう。
JWT VC 発行者のメタデータは
"jwks_uri" ではなく "jwks" を含んでいるかもしれません。
何らかの理由により JWT VC 発行者が JWK Set 用の独立したエンドポイントを提供できない場合に、このようなことが起こります。2.11. 仕様の要約
OID4VCI 仕様は VC 発行の規則を定義しています。仕様の二つの主要議題は『アクセストークン発行』と『クレデンシャル発行』です。 アクセストークン発行のため、仕様は発行可能クレデンシャルを指定する方法を幾つか定義しており、これには (1) クレデンシャルオファー内の事前認可コードを使う方法、 (2) クレデンシャルオファー内のイシュアステートを使う方法、 (3)"type":"openid_credential" を持つ RAR オブジェクトを使う方法、
(4) credential_configurations_supported
メタデータ内のエントリを参照する scope 値を使う方法、が含まれます。
クレデンシャル発行のため、仕様は三つのエンドポイント、すなわち、(1) クレデンシャルエンドポイント、(2) 一括クレデンシャルエンドポイント、(3) 遅延クレデンシャルエンドポイント、を導入しています。
クレデンシャル情報が幾つかの場所に現れます。その場所とは、
(1) credential_configurations_supported
メタデータ、(2) RAR オブジェクト、(3) クレデンシャルリクエスト、(4) 一括クレデンシャルリクエスト、です。
これらの間の一貫性や一意識別性が欠けているため、仕様は意図した目的を完全には達成できないかもしれません。
しかし、完全な相互運用性は犠牲になるものの、実世界のエコシステムは、それぞれ補助的な仕様で補うことで、彼らの個別のニーズを満たす
VC を発行することができるでしょう。
仕様は VC フォーマットの詳細には立ち入りませんが、
jwt_vc_json、jwt_vc_json-ld、ldp_vc、mso_mdoc、vc+sd-jwt
に関連する規則を取り決めました。これらの中で、最近最も注目を集めているのは
SD-JWT VC と mdoc (ISO/IEC 18013-5:2021) です。
eIDAS 2.0 は SD-JWT ベースと mdoc ベースのフォーマットのサポートを必須としています。
公開鍵配布方法も仕様の対象外です。公開鍵配布の方法として、(1) X.509 証明書を VC 自身に埋め込む方法、
(2) クレデンシャルイシュアのエンティティコンフィギュレーション内の
"openid_credential_issuer"."jwks" を使う方法、
(3) /.well-known/jwt-vc-issuer を使う方法、が提案されています。
OID4VCI 仕様には依然として改善の余地がありますが、実世界のエコシステムは実用的な妥協と補助的仕様により
OID4VCI 仕様を補足することで、それぞれの特定のニーズに対応することができるでしょう。
3. OID4VCI 実装
3.1. Authlete 概要
開発者は、OID4VCI 仕様に準拠した自身のクレデンシャルイシュアおよび認可サーバ・OpenID プロバイダを Authlete を利用して作成することができます。 ほとんどのベンダーは認可サーバなどのフロントエンドサーバの実装を直接提供していますが、Authlete は異なるアプローチを取っています。Authlete は、開発者自身がフロントエンドサーバを実装するのに使うことのできる Web API のセットを提供します。Authlete はフロントエンドサーバ群の後ろに配置され、エンドユーザからは見えません。
- 任意の技術コンポーネントを開発者が選べる
- ユーザ認証方法
- ユーザ管理システム
- API ゲートウェイ
- プログラミング言語
- Web フレームワーク
- クラウドサービス
- ユーザデータに対する完全な制御
- ユーザデータを OAuth/OIDC ベンダーのサーバにアップロードする必要はありません。
- ユーザデータの保護に関するさまざまな規制への対応。
- エンドユーザ向けフロントエンドサーバに対する完全な制御
- UI/UX のすべての側面にわたる企業ブランドの管理。
- システム設計における適切なレイヤ分離の強制
- API 認可がユーザ管理・ユーザ認証から分離される。
- OAuth/OIDC プロトコル処理が API ゲートウェイやフロントエンドサーバから分離される。
企業のアーキテクトは、ビジネスの成功のためにユーザのアイデンティティ管理とサービスの Web API の完全な制御が必要であることを認識するようになり、Authlete が提供する『OAuth/OIDC component as a Service』アプローチがその解決策であることに気付き始めました。EIC 2023 で行われたこのトピックに関するパネルディスカッション『Security Offered as Components Empowering Enterprises to Gain Control』を是非ご視聴ください。
3.2. Authlete 設定
3.2.1. Authlete バージョン
OID4VCI 仕様は、2024 年 4 月頃リリース予定の Authlete 3.0 からサポートされます。 それまでの間、お客様とビジネスパートナー向けにトライアルサーバが利用可能です。OID4VCI の試験利用にご興味のある方はお問い合わせください。
3.2.2. Authlete サーバ設定
Authlete サーバで『Verifiable Credentials』機能を有効にしておく必要があります。オンプレミス版の Authlete を利用されている場合は、この機能を有効にするために設定ファイル (authlete-server.properties) 内に次の行が含まれていることを確認してください。
3.2.3. Authlete サービス設定
| プロパティ | 型 | 説明 | | verifiableCredentialsEnabled | 真偽値 | OID4VCI 仕様のサポートなどの Verifiable Credentials 関連機能の有効化・無効化を制御するフラグです。 | | credentialIssuerMetadata | credentialIssuer | 文字列 | このサービスがクレデンシャルイシュアとして動作する際のクレデンシャルイシュア識別子。 このプロパティは OID4VCI で定義されている credential_issuer メタデータに対応します。 値は、スキーム https、クエリー部無し、フラグメント部無し、の有効な URL でなければなりません。 また、Authlete 固有の制限として、アスキー文字のみ、最大長 200 という制限があります。 クレデンシャルイシュアとして動作するためにはこのプロパティを設定しなければなりません。 | | authorizationServers | 文字列の配列 | このサービスがクレデンシャルイシュアとして動作する際に認可処理を任せる認可サーバ群の識別子群。 このプロパティは OID4VCI で定義されている authorization_servers メタデータに対応します。 値は HTTP でアクセス可能な URL でなければなりません。 | | credentialEndpoint | 文字列 | このサービスがクレデンシャルイシュアとして動作する際のクレデンシャルエンドポイントの URL。 このプロパティは OID4VCI で定義されている credential_endpoint メタデータに対応します。 値は、スキーム https、フラグメント部無し、の有効な URL でなければなりません。 また、Authlete 固有の制限として、アスキー文字のみ、最大長 200 という制限があります。 クレデンシャルイシュアとして動作するためにはこのプロパティを設定しなければなりません。 | | batchCredentialEndpoint | 文字列 | このサービスがクレデンシャルイシュアとして動作する際の一括クレデンシャルエンドポイントの URL。 このプロパティは OID4VCI で定義されている batch_credential_endpoint メタデータに対応します。 値は、スキーム https、フラグメント部無し、の有効な URL でなければなりません。 また、Authlete 固有の制限として、アスキー文字のみ、最大長 200 という制限があります。 バッチクレデンシャルエンドポイントを実装するかどうかは任意です。 | | deferredCredentialEndpoint | 文字列 | このサービスがクレデンシャルイシュアとして動作する際の遅延クレデンシャルエンドポイントの URL。 このプロパティは OID4VCI 仕様で定義されている deferred_credential_endpoint メタデータに対応します。 値は、スキーム https、フラグメント部無し、の有効な URL でなければなりません。 また、Authlete 固有の制限として、アスキー文字のみ、最大長 200 という制限があります。 クレデンシャルイシュアのクレデンシャルエンドポイントまたは一括クレデンシャルエンドポイントがトランザクション ID を発行することがある場合、遅延クレデンシャルエンドポイントを実装しなければなりません。 | | credentialResponseEncryptionAlgValuesSupported | 文字列の配列 | クレデンシャルレスポンス暗号化においてサポートされる JWE alg アルゴリズム群。 このプロパティは OID4VCI 仕様で定義されている credential_response_encryption.alg_values_supported メタデータに対応します。 有効な値は、“ECDH_ES” 等、 JWEAlg 列挙型の値です。非対称鍵系アルゴリズムのみ指定可能です。 | | credentialResponseEncryptionEncValuesSupported | 文字列の配列 | クレデンシャルレスポンス暗号化においてサポートされる JWE enc アルゴリズム群。 このプロパティは OID4VCI 仕様で定義されている credential_response_encryption.enc_values_supported メタデータに対応します。 有効な値は、“A256GCM” 等、 JWEEnc 列挙型の値です。 | | requireCredentialEncryptionResponse | 真偽値 | クレデンシャルレスポンスを常に暗号化するかどうかを示すフラグです。 このプロパティは OID4VCI 仕様で定義されている credential_response_encryption.encryption_required メタデータに対応します。 このプロパティが真に設定されている場合、全てのクレデンシャルリクエストは、 credential_response_encryption JSON オブジェクトを含まなければなりません。 | | credentialsSupported | 文字列 | このサービスがクレデンシャルイシュアとして動作する際にサポートするクレデンシャル群。 このプロパティは OID4VCI 仕様で定義されている credential_configurations_supported メタデータに対応します。 値は JSON オブジェクトでなければなりません。非アスキー文字を含めることもできますが、 Authlete 固有の制限として、最大文字数は 16383 に制限されます。 クレデンシャルイシュアとして動作するためには、このプロパティを設定しなければなりません。 後方互換性のため、このプロパティの名前は credentialConfigurationsSupported には変更されず、 credentialsSupported のままとなります。 | | credentialOfferDuration | 数値 | クレデンシャルオファーの有効時間のデフォルト値を秒数で表すプロパティです。 /vci/offer/create API への API コールが duration リクエストパラメーターを含んでいないか、またはその値が 0 以下の場合、このプロパティの値がデフォルト値として使われます。 このプロパティの値が 0 以下の場合、Authlete サーバ単位で設定されているデフォルト値が使われます。 | | preAuthorizedGrantAnonymousAccessSupported | 真偽値 | このプロパティは、事前認可コードフローにおいて匿名クライアントからのトークンリクエストを許可するかどうかを示しています。 このプロパティは OID4VCI 仕様で定義されている pre-authorized_grant_anonymous_access_supported メタデータに対応します。 | | cnonceDuration | 数値 | c_nonce 有効時間を秒数で表すプロパティです。 認可サーバのトークンエンドポイントが Verifiable Credential 発行に使用できるアクセストークンを発行する際、アクセストークンと同時に c_nonce を発行します。 また、クレデンシャルイシュアのクレデンシャルエンドポイントとバッチクレデンシャルエンドポイントは、提示された c_nonce が有効期限切れの場合、新しい c_nonce を発行します。 このプロパティはそれらの c_nonce の有効時間として用いられます。 このプロパティの値が 0 以下の場合、Authlete サーバ単位で設定されているデフォルト値が使われます。 | | credentialTransactionDuration | 数値 | クレデンシャルリクエストまたは一括クレデンシャルリクエストの結果として発行されるトランザクション ID の有効時間のデフォルト値を秒数で表すプロパティです。 このプロパティの値が 0 以下の場合、Authlete サーバ単位で設定されているデフォルト値が使われます。 | | credentialDuration | 数値 | Verifiable Credential のデフォルト有効時間を秒数で表すプロパティです。 /vci/single/issue API や /vci/batch/issue API などの Authlete API は Verifiable Credential を発行します。このプロパティは、それらの Verifiable Credential のデフォルト有効時間を指定します。 値 0 は Verifiable Credential が期限切れしないことを示します。この場合、Verifiable Credential は有効期間を示すプロパティを持ちません。たとえば、JWT ベースの Verifiable Credential であれば、exp クレーム (RFC 7519, Section 4.1.4) を持たないでしょう。 Verifiable Credential を発行する Authlete API は、有効時間を上書きするリクエストパラメーターを認識します。 例えば、/vci/single/issue API のリクエストには order オブジェクトが含まれており、そのオブジェクトの credentialDuration パラメーターでデフォルト有効時間を上書きできます。 | | credentialJwks | 文字列 | Verifiable Credential に署名するための秘密鍵を含む JWK セット文書。 /vci/single/issue API や /vci/batch/issue API などの Authlete API は Verifiable Credential を発行します。 このプロパティの内容はこれらの API により参照されます。 Verifiable Credential を発行する可能性のある Authlete API は署名に使う秘密鍵の鍵 ID を指定するリクエストパラメーターを認識します。 例えば、/vci/single/issue API のリクエストには order オブジェクトが含まれており、そのオブジェクトの signingKeyId パラメーターで署名に使う秘密鍵の鍵 ID を指定することができます。 鍵 ID が指定されていないとき、Authlete は自動的に秘密鍵を選択します。 この credentialJwks プロパティが更新される際に JWK セット文書内の JWK 群が kid プロパティ (RFC 7517, Section 4.5) を含んでいない場合、Authlete は自動的に kid プロパティを挿入します。 SHA-256 ハッシュアルゴリズムを用いて計算した JWK Thumbprint (RFC 7638) が kid プロパティの値として使われます。 | | credentialJwksUri | 文字列 | クレデンシャルイシュアの JWK セット文書を公開する場所を指す URL。 この URL は、JWT イシュアメタデータの jwks_uri プロパティーの値として使用されます。 メタデータそのものは /.well-known/jwt-issuer で公開されます。 JWT イシュアメタデータの詳細については SD-JWT-based Verifiable Credentials (SD-JWT VC) を参照してください。 |3.3. Authlete APIs
3.3.1. OID4VCI 用 Authlete API の全体像
以下の図は、フロントエンドサーバ(クレデンシャルイシュアおよび認可サーバ)のエンドポイントと Authlete API の関係を示しています。Authlete API の詳細については以降の節で説明します。
3.3.2. Authlete API コール
Authlete 2.x と Authlete 3.0 の大きな違いの一つに、Authlete API の呼び出し方の違いがあります。 Authlete 2.x およびそれ以前のバージョンでは、API キーと API シークレットの組 (例えば、サービス API キーとサービス API シークレット) を用いて Authlete API をコールします。 一方、Authlete 3.0 では、アクセストークンを用いて Authlete API をコールします。 開発者は、以前の物とはかなり異なる新しいウェブコンソールを使い、Authlete API 用のアクセストークンを取得できます。 Authlete 2.x およびそれ以前のバージョンでは、二つの別々のウェブコンソール、すなわち、 (認可サーバや OpenID プロバイダに対応するサービスを管理するための) サービスオーナーコンソールと (クライアントアプリケーションを管理するための) デベロッパーコンソールがありました。 しかし、Authlete 3.0 では、提供されるウェブコンソールは一つだけであり、その表示と機能は提示されたアクセストークンの権限に従って変化します。| Authlete 2.x | Authlete 3.0 | |
|---|---|---|
| 保護 | API キー & API シークレット | アクセストークン |
| ウェブコンソール | サービスオーナーコンソールとデベロッパーコンソール | 単一のコンソール |
/api/{サービスID}/auth/authorization のように、パス部にサービス ID を含んでいます。
ここで {サービスID} はサービスの識別子 (つまり Authlete 2.x におけるサービス API キー) です。
| Authlete バージョン | API パスの例 |
|---|---|
| Authlete 2.x | /api/auth/authorization |
| Authlete 3.0 | /api/{サービスID}/auth/authorization |
他の文書と同様に、この文書では API パスのプレフィックス『
/api/{サービスID}』を省略します。authlete.properties) の内容を
3.4. クレデンシャルオファー発行
既に述べたように、クレデンシャルオファー発行処理はクレデンシャルイシュアによって異なります。 例えば、Webブラウザ経由でユーザとやりとりした後、クレデンシャルイシュアは次のような QR コードを発行するかもしれません。
openid-credential-offer://?credential_offer={CredentialOffer}”
を表していて、{CredentialOffer} の部分が下記のクレデンシャルオファーを保持しています。
openid-credential-offer://?credential_offer_uri={CredentialOfferUri}
{CredentialOfferUri} は
https%3A%2F%2Ftrial.authlete.net%2Fapi%2Foffer%2FTctoiNm9lYASTBT6XRGb8RQsrClKczCxDtqLY1jLvpk
のような URL エンコードされた URL です。
3.4.1. /vci/offer/create API
いずれにしても、クレデンシャルオファーをサポートするクレデンシャルイシュアは、クレデンシャルオファーを作成できなければなりません。
この機能のため、Authlete は /vci/offer/create API を提供します。次の表は当 API の要約です。
| /vci/offer/create API へのリクエスト |
| HTTP メソッドとContent-Type | GET | (クエリパラメーター) |
| POST | application/json |
| POST | application/x-www-form-urlencoded |
| リクエストパラメーター | credentialConfigurationIds | 文字列の配列で、クレデンシャルオファーの “credential_configuration_ids”
プロパティの値として用いられます。このリクエストパラメーターは必須です。 |
| authorizationCodeGrantIncluded | “grants” オブジェクト内に “authorization_code”
オブジェクトを含めるかどうかを示す真偽値 (true または false) です。 |
| issuerStateIncluded | “grants” オブジェクト内の “authorization_code”
オブジェクトに “issuer_state” プロパティを含めるかを示す真偽値
(true または false) です。
このパラメーターが true の場合、Authlete はイシュアステートを生成し、
“authorization_code” オブジェクト内に “issuer_state”
プロパティの値として配置します。 |
| preAuthorizedCodeGrantIncluded | “grants” オブジェクト内に
“urn:ietf:params:oauth:grant-type:pre-authorized_code”
オブジェクトを含めるかどうかを示す真偽値 (true または false) です。
このパラメーターが true の場合、Authlete は事前認可コードを生成し、
“urn:ietf:params:oauth:grant-type:pre-authorized_code”
オブジェクト内に “pre-authorized_code” プロパティの値として配置します。 |
| txCode | 事前認可コードに紐づけるトランザクションコードです。
このパラメーターが空でなければ
“urn:ietf:params:oauth:grant-type:pre-authorized_code”
オブジェクトに tx_code オブジェクトが埋め込まれます。
結果として、事前認可コードを用いるトークンリクエストは、このパラメーターで指定された値を
tx_code リクエストパラメーターの値として使わなければなりません。 |
| txCodeInputMode | トランザクションコードの入力モードです。このパラメーターで指定された値は
tx_code オブジェクト内の input_mode
プロパティの値として用いられます。
OID4VCI 仕様で事前定義された値は “numeric” と “text”
のみですが、将来の拡張性のため、/vci/offer/create API
は事前定義されたもの以外の値も受け付けます。 |
| txCodeDescription | トランザクションコードの説明です。このパラメーターで指定された値は
tx_code オブジェクト内の description
プロパティの値として用いられます。 |
| subject | クレデンシャルオファーに紐付けるユーザのサブジェクト (一意識別子) です。
このパラメーターは必須です。 |
| duration | クレデンシャルオファーの有効秒数です。
このパラメーターが 0 より大きい場合、その値が発行されるクレデンシャルオファーの有効時間として用いられます。
それ以外の場合、サービスの credentialOfferDuration プロパティの値が用いられます。 |
| context | クレデンシャルオファーに紐付ける、用途制限のない任意の文字列です。
開発者は好きなようにこのパラメーターを利用できます。
Authlete はこのパラメーターの内容について関知しません。 |
| properties | クレデンシャルオファーに紐付けるエクストラプロパティで、用途制限のないキー・バリューの組です。
エクストラプロパティは、最終的にクレデンシャルオファーを使って作成されるアクセストークンに紐付けられます。 |
| jwtAtClaims | JWT アクセストークンのペイロード部に追加するクレーム群を JSON オブジェクト形式で表したものです。
このパラメーターは、サービスが発行するアクセストークンの形式が JWT の場合のみ意味があります。
別の言い方をすると、サービスの accessTokenSignAlg
プロパティの値が設定されている場合のみ意味があります。
追加クレームは、最終的にクレデンシャルオファーを使って作成されるアクセストークンに紐付けられます。 |
| authTime | クレデンシャルオファーを発行する過程で行われたユーザ認証が実行された時刻。
時刻は Unix エポックからの経過秒数で表されます。 |
| acr | クレデンシャルオファーを発行する過程で行われたユーザ認証の認証コンテキストクラス参照。 |
例えば、次のコマンドラインでクレデンシャルオファーが生成されます。
/vci/offer/create API は次のような JSON を返します。
"info" オブジェクトが生成されたクレデンシャルオファーの情報を含んでいます。
"info" オブジェクト内の "credentialOffer" プロパティが生成されたクレデンシャルオファーです。
上記例中の "credentialOffer" プロパティを読みやすく整形すると次のようになります。
"credentialOffer" プロパティの値があれば、次の要素を連結することで
URL を構築できます。
- クレデンシャルオファーエンドポイント。
openid-credential-offer://など。 ?credential_offer=- URL エンコードした
"credentialOffer"の値
/vci/offer/create API へのリクエストとそのレスポンスは、それぞれ
authlete-java-common ライブライ内の
CredentialOfferCreateRequest Java クラスと
CredentialOfferCreateResponse Java クラスで表現されます。
詳細はライブラリの JavaDoc を参照してください。
3.4.2. The /vci/offer/info API
/vci/offer/info API はクレデンシャルオファーの情報を返します。
この API はクレデンシャルオファーの識別子を指定する identifier
リクエストパラメーターを受け付けます。
| /vci/offer/info API へのリクエスト |
| HTTP メソッドとContent-Type | GET | (パスパラメーター) |
| POST | application/json |
| POST | application/x-www-form-urlencoded |
| リクエストパラメーター | identifier | クレデンシャルオファーの識別子。API コールが HTTP GET リクエストの場合、識別子は
/vci/offer/info/ のようにパスの末尾で指定されます。 |
識別子は /vci/offer/create API のレスポンスに含まれます。"info" オブジェクト内の
"identifier" プロパティの値が識別子です。前節の例では、その値は
9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc
となっています。
次のコマンドラインは、前節で作成されたクレデンシャルオファーの情報を問い合わせます。
/vci/offer/info API は次のような JSON を返します。
内容は /vci/offer/create API が返すものとほぼ同じです。
/vci/offer/info API の主目的は、ウォレットからの問い合わせに対してクレデンシャルオファーの情報を返すエンドポイントを、開発者がクレデンシャルイシュア上に実装するのを助けることです。

- クレデンシャルオファーエンドポイント。
openid-credential-offer://など。 ?credential_offer_uri=- URL エンコードしたクレデンシャルオファーの識別子を含むエンドポイントの URL。例えば
https://trial.authlete.net/api/offer/9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEcなど。
3.4.3. クレデンシャルオファー発行の例
Java で書かれたサンプル認可サーバの実装である authlete/java-oauth-server はクレデンシャルイシュアとしても機能します。開発者が任意のクレデンシャルオファーを生成するための HTML ページが/api/offer/issue エンドポイントにより提供されます。Authlete 3.0 を使う
java-oauth-server インスタンスが現在 https://trial.authlete.net で稼働しており、試用を目的として
https://trial.authlete.net/api/offer/issue エンドポイントを利用できます。

inga を使用してください。
| サブジェクト | ログイン ID | パスワード |
|---|---|---|
| 1001 | john | john |
| 1002 | jane | jane |
| 1003 | max | max |
| 1004 | inga | inga |
3.5. クレデンシャルエンドポイント実装
下記の Authlete API を用いてクレデンシャルエンドポイントを実装することができます。| Authlete API | 説明 | |
|---|---|---|
| 1 | /auth/introspection | 提示されたアクセストークンの有効性を確認し、アクセストークンの情報を返します。 |
| 2 | /vci/single/parse | 受け取ったクレデンシャルリクエストを解析して有効性を確認し、クレデンシャルリクエストの情報を返します。 |
| 3 | /vci/single/issue | Verifiable Credential またはトランザクション ID を発行し、クレデンシャルレスポンスを用意します。 |

/auth/introspection API に渡します。

/auth/introspection API はアクセストークンの有効性を確認し、アクセストークンの情報を返します。

/vci/single/parse API に送ります。

アクセストークンの有効性確認は既に終わっているのに、なぜ
/vci/single/parse
API にアクセストークンを送るのだろうと思われるかもしれません。この理由は、Authlete
の実装では c_nonce はアクセストークンと紐付けられているからです。
クレデンシャルリクエストは鍵証明を含んでいることがあり、その鍵証明の nonce
クレームの有効性を確認するため、Authlete はアクセストークンに紐付いた c_nonce
の値を知る必要があります。/vci/single/parse API はクレデンシャルリクエストの解析と有効性確認をおこない、クレデンシャルリクエストの情報を返します。


/vci/single/issue API に送ります。

再び Authlete にアクセストークンを送る理由は、アクセストークンに紐付く
c_nonce
が期限切れした場合に値をリフレッシュする必要があるためです。/vci/single/issue API は VC またはトランザクション ID
を発行し、クレデンシャルレスポンスの内容を用意します。

/vci/single/issue API が用意したレスポンスの内容をクレデンシャルレスポンスのメッセージボディとして使用できます。



3.5.1. クレデンシャル発行指示
クレデンシャル発行指示を用意する手順は次の通りです。3.5.1.1. クレデンシャル発行指示 ステップ 1
アクセストークン情報からアクセストークンに紐付くユーザのサブジェクト (= 一意識別子) を取得します。/auth/introspection API のレスポンス (IntrospectionResponse 参照)
に含まれる "subject" プロパティがサブジェクトの値を保持しています。

3.5.1.2. クレデンシャル発行指示 ステップ 2
サブジェクトで特定されるユーザの情報をユーザデータベースから取り出します。
3.5.1.3. クレデンシャル発行指示 ステップ 3
アクセストークン情報からアクセストークンに紐付く発行可能クレデンシャルの情報を取得します。/auth/introspection API のレスポンスに含まれる "issuableCredentials"
プロパティが情報を文字列として保持しています。この文字列は JSON 配列としてパースする必要があります。

3.5.1.4. クレデンシャル発行指示 ステップ 4
クレデンシャルリクエスト情報からクレデンシャルリクエストに含まれるクレデンシャル情報を取得します。/vci/single/parse API のレスポンス (CredentialSingleParseResponse 参照)
内の "info" オブジェクトはクレデンシャルリクエストに関する様々な情報を保持しています。
その "info" オブジェクト内の "format" プロパティと "details"
プロパティを併せたものがクレデンシャル情報を表します。

"details" プロパティの値は文字列です。この文字列は JSON オブジェクトとしてパースする必要があります。
その JSON オブジェクトの内容は、"format" パラメーター、"proof" パラメーター、
"credential_response_encryption" パラメーターが含まれていないことを除き、
クレデンシャルリクエストとほぼ同じです。
3.5.1.5. クレデンシャル発行指示 ステップ 5
クレデンシャル情報がいずれかの発行可能クレデンシャルのサブセットであるかどうかを調べることにより、 アクセストークンがクレデンシャルリクエストのための必要な権限を持っていることを確認します。
vct の値によりクレームの集合を決め、個々のクレームを一つ一つ指定する必要をなくす」という提案があります。
この提案は、JSON オブジェクト同士の包含関係を機械的に調べることでアクセストークンの権限をチェックすることを不可能にします。
そのため、アクセストークンが十分な権限を持っていることの確認は、クレデンシャルイシュアがそれぞれの方針に基づいて実装することになります。
包含関係に基づく権限チェックは Authlete に実装済みではありますが、無効にしてあります。
3.5.1.6. クレデンシャル発行指示 ステップ 6
クレデンシャル情報に基づき、発行する VC に埋め込むユーザクレームの集合を決定し、ユーザデータベースから取り出しておいたデータセットからそれらのユーザクレーム群の情報を取得します。
3.5.1.7. クレデンシャル発行指示 ステップ 7
集めたデータを使いクレデンシャル発行指示を作成します。
| プロパティ | 型 | 説明 |
|---|---|---|
requestIdentifier | 文字列 | Authlete がクレデンシャルリクエストに割り当てた識別子。/vci/single/parse API のレスポンスに含まれる info.identifier プロパティがその識別子です。このプロパティは必須です。 |
credentialPayload | 文字列 | 発行する VC に追加するペイロード。この文字列のフォーマットは JSON オブジェクトでなければなりません。ユーザクレームの集合を JSON に変換後、このプロパティにセットしてください。このプロパティは任意です。 |
issuanceDeferred | 真偽値 | クレデンシャル発行を遅延させるかどうかを示すフラグです。このプロパティが true の場合、/vci/single/issue API は VC の代わりにトランザクション ID を発行します。 |
credentialDuration | 整数 | VC の有効秒数。このプロパティが正の整数の場合、有効時間として使われます。値が 0 の場合、サービスのデフォルト有効時間が使われます。負の整数の場合、VC は有効期限を持ちません。 |
signingKeyId | 文字列 | 発行する VC の署名に使う秘密鍵の鍵 ID。省略された場合、Authlete は自動的に鍵を選択します。 |
3.5.1.8. クレデンシャル発行指示 ステップ 8
/vci/single/issue API へのリクエスト (CredentialSingleIssueRequest 参照) を用意します。

3.5.1.9. クレデンシャル発行指示 ステップ 9
用意したリクエストを/vci/single/issue API に送ります。

3.5.1.10. クレデンシャル発行指示 ステップの要約
次の図はクレデンシャル発行指示を用意する手順の要約です。
3.6. 一括クレデンシャルエンドポイント実装
執筆予定。4. OID4VCI デモ
4.1. 事前認可コードフロー + 鍵証明 + SD-JWT VC
4.1.1. セットアップ
このデモで使うリソースをダウンロードします。4.1.2. 事前認可コード
『事前認可コード』を含む『クレデンシャルオファー』を生成するため、 https://trial.authlete.net/api/offer/issue にアクセスします。
inga、inga を入力し、
Pre-authorized code grant included にチェックがついていることを確認し、
Submit ボタンを押します。これにより、結果ページが表示されます。

pre-authorized_code プロパティの値が発行された事前認可コードです。
次の手順で使うので、発行された事前認可コードをシェル変数 PRE_AUTHORIZED_CODE に設定します。
4.1.3. アクセストークン
事前認可コードフローを用いて『トークンリクエスト』を送ります。 このデモのクライアントはパブリッククライアントなので、クライアント認証は要求されません。 つまり、クライアント認証に関連するリクエストパラメーターを追加する必要はありません。access_token パラメーターと c_nonce パラメーターが含まれます。
後ほど使うので、これらのレスポンスパラメーターの値をシェル変数に設定します。
4.1.4. 鍵証明
保有者の鍵holder.jwk と generate-key-proof スクリプトを用いて、JWT 形式の『鍵証明』を生成します。
この JWK ファイルとスクリプトは oid4vci-demo レポジトリに含まれています。
generate-key-proof スクリプトは次のような鍵証明を生成します。
generate-key-proof スクリプトの実行結果は、次のようにすることで直接シェル変数
KEY_PROOF_JWT に設定することができます。
4.1.5. SD-JWT VC
生成した鍵証明と一緒に、『クレデンシャルエンドポイント』に『クレデンシャルリクエスト』を送ります。credential パラメーターの値が発行された SD-JWT VC です。
この SD-JWT VC がシェル変数 SD_JWT に設定されている場合、decode-sd-jwt
スクリプトを次のように起動することで、SD-JWT VC の内容をデコードすることができます。
4.2. 認可コードフロー + PAR + DPoP + mdoc
4.2.1. セットアップ
このデモで使うリソースをダウンロードします。4.2.2. リクエスト URI
DPoP 用の秘密鍵dpop.jwk と generate-dpop-proof スクリプトを用いて
DPoP proof JWT (RFC 9449) を生成します。
generate-dpop-proof スクリプトは次のような DPoP proof JWT を生成します。
htu クレームの値が PAR エンドポイントの URL であることに注目してください。
DPoP ヘッダが含まれていること、及び (2) scope パラメーターが
org.iso.18013.5.1.mDL を含んでいることです。
scope の値は、クレデンシャルイシュアメタデータの
credential_configurations_supported オブジェクトに、
scope プロパティの値が org.iso.18013.5.1.mDL
であるクレデンシャル設定が少なくとも一つ含まれていることを想定しています。
request_uri
パラメーターの値が発行されたリクエスト URI です。
この値は次のステップで使用します。
4.2.3. 認可コード
ウェブブラウザを使い、認可エンドポイントに認可リクエストを送ります。URL 内の$REQUEST_URI
を先ほどのステップで PAR エンドポイントから受け取った実際のリクエスト URI で置き換えることを忘れないでください。
inga, inga
と入力し、Authorize ボタンを押してください。


4.2.4. アクセストークン
トークンエンドポイントにアクセスするための DPoP proof JWT を生成します。generate-dpop-proof スクリプトの -u オプションに渡す引数が $TOKEN_ENDPOINT
であること ($PAR_ENDPOINT ではないこと) に注意してください。
htu クレームの値はトークンエンドポイントの URL になっています。
AUTHORIZATION_CODE に設定することを忘れないでください。
access_token パラメーターが含まれています。
次のステップで使うので、このパラメーターの値をシェル変数 ACCESS_TOKEN に設定してください。
4.2.5. mdoc
クレデンシャルエンドポイントにアクセスするための DPoP proof JWT を生成します。generate-dpop-proof スクリプトの -u オプションに渡す引数が $CREDENTIAL_ENDPOINT であること、
DPoP proof JWT に ath クレームを埋め込むために -a オプションを渡す必要があることに注意してください。
ath クレームが含まれています。
credential パラメーターの値が発行された mdoc です。
ウェブサイト CBOR Zone (https://cbor.zone/) を使い、mdoc をデコードすることができます。
credential パラメーターの値をコピーし、CBOR Zone の Input セクションのテキストエリアに貼り付け、
base64url ラジオボタンを選択し、Generate ボタンを押してください。mdoc の内容が CBOR
診断記法 (RFC 8949, 8. Diagnostic Notation,
RFC 8610, Appendix G. Extended Diagnostic Notation) で表示されます。

4.3. POTENTIAL 相互運用性イベント / トラック 1 / Light プロファイル
POTENTIAL はヨーロッパのデジタルアイデンティティに特化したヨーロッパの組織です。 この組織は 2024 年春から相互運用性イベントを開催しています。このイベントは 6 つのトラックに分かれています。 トラック 1 と 2 は、クレデンシャルイシュアの相互運用性をテストするためのトラックです。 トラック 1 では VC の形式として mdoc が使用され、トラック 2 では SD-JWT VC が使用されます。 トラック 1 では 2 つのプロファイルが定義されています。 1 つは Light プロファイルと呼ばれ、もう 1 つは Full プロファイルと呼ばれます。 このセクションでは Light プロファイルの手順を説明します。4.3.1. 設定
4.3.1.1. 認可サーバの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| 認可エンドポイント | https://trial.authlete.net/api/authorization |
| トークンエンドポイント | https://trial.authlete.net/api/token |
| ディスカバリエンドポイント | [https://trial.authlete.net/.well-known/openid-configuration](https://trial.authlete.net/.well-known/openid-configuration) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.3.1.2. クレデンシャルイシュアの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| クレデンシャルエンドポイント | https://trial.authlete.net/api/credential |
| メタデータエンドポイント | [https://trial.authlete.net/.well-known/openid-credential-issuer](https://trial.authlete.net/.well-known/openid-credential-issuer) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.3.1.3. クライアントの設定
| パラメータ | 値 |
|---|---|
| クライアント識別子 | track1_light |
| クライアントタイプ | パブリック (= クライアント認証は要求されない) |
| リダイレクト URI | https://nextdev-api.authlete.net/api/mock/redirection または eudi-openid4ci://authorize/ |
Authlete メンバーへ: 新しいクライアントは
“Trial” (組織 = 283415) /
“NextDev” (サーバ = 2704222) /
“Authlete Trial” (サービス = 986126671)
に登録してください。
4.3.2. デモ手順
4.3.2.1. 手順 1 : クレデンシャルオファー
クレデンシャルイシュアのサンプル実装は、開発者がテスト用に任意のクレデンシャルオファーを生成できるウェブページを提供しています。 ページの URL は https://trial.authlete.net/api/offer/issue です。 このウェブページにアクセスすると、クレデンシャルオファーの内容を設定するフォームが表示されます。 以下の指示に従ってフォームを編集してください。- Login ID フィールドと Password フィールドに、
inga、ingaを入力する。 - Credential Configuration IDs を編集する。値は、文字列
potential.light.profileを含む JSON 配列とする。 - Authorization Code Grant の横にある “include?” チェックボックスをチェックする。
- Pre-Authorized Code Grant の横にある “include?” チェックボックスのチェックを外す。


issuer_state プロパティの値は発行されたイシュアステートです。
上の例では、イシュアステートの値は
tXkAkhSu5N9ORSNES9T64Bd9PAiKn9OmEOT5qDL0lkA
です。
イシュアステートは、後ほど実行する認可リクエストに含めることになります。
4.3.2.2. 手順 2 : コードベリファイアとコードチャレンジ
pkce コマンドを用いて、コードベリファイアを生成し、また、対応するコードチャレンジを計算します
(RFC 7636 参照)。
pkce コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。
4.3.2.3. 手順 3 : 認可リクエスト
認可コードフロー (RFC 6749, 4.1 参照) を用いて認可リクエストを実行します。 次の URL をお使いのウェブブラウザのアドレスバーに入力してください。URL 内の${ISSUER_STATE} と
${CODE_CHALLENGE} は、これまでの手順で生成したイシュアステートとコードチャレンジの実際の値で置き換えてください。
inga、inga と入力し、Authorize ボタンを押してください。


code パラメータの値が発行された認可コードです。
この例では、認可コードの値は
gR43MQf2olvhMt6KekVDkUOdQPrVYgBiKXMwu_UFnB8
です。
認可コードは次のセクションのトークンリクエストで使います。
認可コードは 10 分で期限切れとなるため、すみやかにトークンリクエスト実行しなければならないことに注意してください。
4.3.2.4. 手順 4 : トークンリクエスト
認可コードフローを用いてトークンリクエストを実行します。下記のcurl コマンド内の
${AUTHORIZATION_CODE} と ${CODE_VERIFIER} は、これまでの手順で取得した認可コードとコードベリファイアの実際の値で置き換えてください。
access_token プロパティの値は発行されたアクセストークンです。
これは、クレデンシャルリクエストを実行する際に提示する必要があります。
c_nonce プロパティの値は鍵証明に含めなければならないノンス値です。
4.3.2.5. 手順 5 : CWT 鍵証明
authlete/cbor ライブラリには、CWT 鍵証明を生成するためのユーティリティクラスCWTKeyProofBuilder が含まれています。当ライブラリのレポジトリに含まれるシェルスクリプト
bin/generate-cwt-key-proof は、このユーティリティクラスをコマンドラインから起動するためのラッパーです。
次に示すように CWT 鍵証明を生成することができます。コマンドライン内の ${NONCE} を、
先の手順でトークンエンドポイントから発行された c_nonce の値で置き換えてください。
また、${PRIVATE_KEY_FILE} を、JWK フォーマット (RFC 7517 参照)
で秘密鍵を含むファイルの実際のパスで置き換えてください。
authlete/oid4vci-demo レポジトリ内の holder.jwk
ファイルをこの用途で使うことができます。
generate-cwt-key-proof スクリプトは次のように CWT 鍵証明を表示します。
COSE_Key の値は CBOR byte string で、COSE 鍵を内包しています。
この byte string をデコードすると、次の COSE 鍵が得られます。
4.3.2.6. 手順 6 : クレデンシャルリクエスト
アクセストークンと CWT 鍵証明を使い、クレデンシャルリクエストを実行します。 次のコマンドライン内の${ACCESS_TOKEN} と ${CWT_KEY_PROOF}
は実際の値で置き換えてください。
credential プロパティの値が発行された Verifiable Credential (VC) です。
4.3.3. VC フォーマット
前のセクションの VC を CBOR 診断記法で表すと次のようになります。IssuerSigned 構造を表しています。この構造は、
ISO/IEC 18013-5:2021 のセクション
“8.3.2.1.2.2 Device retrieval mdoc response” で次のように定義されています。
意外ですが、フォーマットが
mso_mdoc のときに credential
プロパティがどの CBOR 構造を表すかについて、OID4VCI 仕様は指定していません。
これは意図的とは考えにくく、単なる仕様の不備です。この曖昧さのため、Authlete の以前の実装では IssuerSigned 構造ではなく
Document 構造が使われていました。興味深いことに、EUDI Wallet の実装は
IssuerSigned 構造も Document 構造も想定していないようです。
代わりに DeviceResponse 構造を想定しているようです。Authlete の実装を IssuerSigned 構造を用いるように変更した理由は、
POTENTIAL Interop Event Track 1 のドキュメントが IssuerSigned
構造を使うべきだと明示的に述べているからです。IssuerAuth 構造および関連する構造は次のように定義されています。
IssuerAuth と MobileSecurityObjectBytes
の定義は、(CBOR タグで始まる) MobileSecurityObjectBytes が
COSE_Sign1 のペイロードとして直接使われる印象を与えます。しかし、
MobileSecurityObjectBytes をさらに byte string
に変換する必要があります。
ですので、h'd81859 で始まる、"issuerAuth" 配列の三番目の要素は、
MobileSecurityObjectBytes を含む byte string を表しています。
その byte string をデコードすることで、次の CBOR 構造を見ることができます。
deviceKey の値として VC 内に現れることです。
CWT 鍵証明内の COSE_Key の値と VC 内の deviceKey の値が同一であることを確認してください。
双方とも次の COSE Key を保持しています。
4.4. POTENTIAL 相互運用性イベント / トラック 2 / Light プロファイル
POTENTIAL はヨーロッパのデジタルアイデンティティに特化したヨーロッパの組織です。 この組織は 2024 年春から相互運用性イベントを開催しています。このイベントは 6 つのトラックに分かれています。 トラック 1 と 2 は、クレデンシャルイシュアの相互運用性をテストするためのトラックです。 トラック 1 では VC の形式として mdoc が使用され、トラック 2 では SD-JWT VC が使用されます。 トラック 2 では 2 つのプロファイルが定義されています。 1 つは Light プロファイルと呼ばれ、もう 1 つは Full プロファイルと呼ばれます。 このセクションでは Light プロファイルの手順を説明します。4.4.1. 設定
4.4.1.1. 認可サーバの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| 認可エンドポイント | https://trial.authlete.net/api/authorization |
| トークンエンドポイント | https://trial.authlete.net/api/token |
| ディスカバリエンドポイント | [https://trial.authlete.net/.well-known/openid-configuration](https://trial.authlete.net/.well-known/openid-configuration) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.4.1.2. クレデンシャルイシュアの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| クレデンシャルエンドポイント | https://trial.authlete.net/api/credential |
| メタデータエンドポイント | [https://trial.authlete.net/.well-known/openid-credential-issuer](https://trial.authlete.net/.well-known/openid-credential-issuer) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.4.1.3. クライアントの設定
| パラメータ | 値 |
|---|---|
| クライアント識別子 | track2_light |
| クライアントタイプ | パブリック (= クライアント認証は要求されない) |
| リダイレクト URI | https://nextdev-api.authlete.net/api/mock/redirection または eudi-openid4ci://authorize/ |
Authlete メンバーへ: 新しいクライアントは
“Trial” (組織 = 283415) /
“NextDev” (サーバ = 2704222) /
“Authlete Trial” (サービス = 986126671)
に登録してください。
4.4.2. デモ手順
4.4.2.1. 手順 1 : コードベリファイアとコードチャレンジ
pkce コマンドを用いて、コードベリファイアを生成し、また、対応するコードチャレンジを計算します
(RFC 7636 参照)。
pkce コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。
4.4.2.2. 手順 2 : 認可リクエスト
認可コードフロー (RFC 6749, 4.1 参照) を用いて認可リクエストを実行します。 次の URL をお使いのウェブブラウザのアドレスバーに入力してください。URL 内の${CODE_CHALLENGE}
は、先の手順で生成したコードチャレンジの実際の値で置き換えてください。
inga、inga と入力し、Authorize ボタンを押してください。


code パラメータの値が発行された認可コードです。
この例では、認可コードの値は
gR43MQf2olvhMt6KekVDkUOdQPrVYgBiKXMwu_UFnB8
です。
認可コードは次のセクションのトークンリクエストで使います。
認可コードは 10 分で期限切れとなるため、すみやかにトークンリクエスト実行しなければならないことに注意してください。
4.4.2.3. 手順 3 : トークンリクエスト
認可コードフローを用いてトークンリクエストを実行します。下記のcurl コマンド内の
${AUTHORIZATION_CODE} と ${CODE_VERIFIER} は、これまでの手順で取得した認可コードとコードベリファイアの実際の値で置き換えてください。
access_token プロパティの値は発行されたアクセストークンです。
これは、クレデンシャルリクエストを実行する際に提示する必要があります。
c_nonce プロパティの値は鍵証明に含めなければならないノンス値です。
4.4.2.4. 手順 4 : JWT 鍵証明
保有者の鍵holder.jwk と generate-key-proof スクリプトを用いて、JWT 形式の『鍵証明』を生成します。
この JWK ファイルとスクリプトは oid4vci-demo レポジトリに含まれています。
次のコマンドライン内の $C_NONCE は、先の手順で受け取ったトークンレスポンスに含まれる c_nonce
プロパティの実際の値で置き換えてください。
generate-key-proof スクリプトは次のような鍵証明を生成します。
generate-key-proof スクリプトの実行結果は、次のようにすることで直接シェル変数
JWT_KEY_PROOF に設定することができます。
4.4.2.5. 手順 5 : クレデンシャルリクエスト
アクセストークンと JWT 鍵証明を使い、クレデンシャルリクエストを実行します。 次のコマンドライン内の${ACCESS_TOKEN} と ${JWT_KEY_PROOF}
は実際の値で置き換えてください。
credential プロパティの値が発行された Verifiable Credential (VC) です。
4.4.3. VC フォーマット
レスポンス内のcredential パラメーターの値が発行された SD-JWT VC です。
この SD-JWT VC がシェル変数 SD_JWT に設定されている場合、decode-sd-jwt
スクリプトを次のように起動することで、SD-JWT VC の内容をデコードすることができます。
4.5. POTENTIAL 相互運用性イベント / トラック 2 / Full プロファイル
POTENTIAL はヨーロッパのデジタルアイデンティティに特化したヨーロッパの組織です。 この組織は 2024 年春から相互運用性イベントを開催しています。このイベントは 6 つのトラックに分かれています。 トラック 1 と 2 は、クレデンシャルイシュアの相互運用性をテストするためのトラックです。 トラック 1 では VC の形式として mdoc が使用され、トラック 2 では SD-JWT VC が使用されます。 トラック 2 では 2 つのプロファイルが定義されています。 1 つは Light プロファイルと呼ばれ、もう 1 つは Full プロファイルと呼ばれます。 このセクションでは Full プロファイルの手順を説明します。4.5.1. 設定
4.5.1.1. 認可サーバの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| 認可エンドポイント | https://trial.authlete.net/api/authorization |
| トークンエンドポイント | https://trial.authlete.net/api/token |
| PAR エンドポイント | https://trial.authlete.net/api/par |
| ディスカバリエンドポイント | [https://trial.authlete.net/.well-known/openid-configuration](https://trial.authlete.net/.well-known/openid-configuration) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.5.1.2. クレデンシャルイシュアの設定
| パラメータ | 値 |
|---|---|
| 発行者識別子 | https://trial.authlete.net |
| クレデンシャルエンドポイント | https://trial.authlete.net/api/credential |
| メタデータエンドポイント | [https://trial.authlete.net/.well-known/openid-credential-issuer](https://trial.authlete.net/.well-known/openid-credential-issuer) |
| エンティティ設定 | [https://trial.authlete.net/.well-known/openid-federation](https://trial.authlete.net/.well-known/openid-federation) |
4.5.1.3. クライアントの設定
| パラメータ | 値 |
|---|---|
| クライアント識別子 | track2_full |
| クライアントタイプ | コンフィデンシャル |
| クライアント認証方式 | attest_jwt_client_auth |
| リダイレクト URI | https://nextdev-api.authlete.net/api/mock/redirection または eudi-openid4ci://authorize/ |
Authlete メンバーへ: 新しいクライアントは
“Trial” (組織 = 283415) /
“NextDev” (サーバ = 2704222) /
“Authlete Trial” (サービス = 986126671)
に登録してください。
4.5.2. デモ手順
4.5.2.1. 手順 1 : コードベリファイアとコードチャレンジ
pkce コマンドを用いて、コードベリファイアを生成し、また、対応するコードチャレンジを計算します
(RFC 7636 参照)。
pkce コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。
4.5.2.2. 手順 2 : クライアントアテステーションとクライアントアテステーション PoP
POTENTIAL の Track 2 Full プロファイルでは OAuth 2.0 Attestation-Based Client Authentication と呼ばれる新しいクライアント認証方式を用います。この方式のため、JWT を二つ用意しなければなりません。 それらの JWT はそれぞれ、クライアントアテステーション (Client Attestation)、 クライアントアテステーション PoP (Client Attestation PoP) と呼ばれます。 これらの JWT を生成するため、oid4vci-demo レポジトリにはgenerate-client-attestation と
generate-client-attestation-pop
という二つのスクリプトが含まれています。使い方は次の通りです。
attester.jwk) とクライアントアプリケーションの秘密鍵 (client.jwk) が含まれています。
これらの鍵を用い、クライアントアテステーションを次のように生成することができます。
仮に秘密鍵が与えられたとしても、
generate-client-attestation
スクリプトは指定されたクライアント鍵の公開部分しか使いません。
そのため、クライアントの秘密鍵を含むファイルを --client-key
オプションに直接渡すことができます。上記の例ではクライアントアテステーション発行者の識別子として
https://attester.example.com を用いています。Authlete
の現在の実装は値について気にしないので、どんな値でも動きます。OAuth 2.0 Attestation-Based Client Authentication の現在の仕様 (この記事を執筆している時点では
draft 03) ではクライアントアテステーションの署名を検証するための公開鍵をどのように取得するかが決められていないことに注意してください。
この点に関して、仕様は各エコシステムが独自ルールを定めることを期待しているように見受けられます。そのため、現在の Authlete の実装はクライアントアテステーションの署名を検証しません。
クライアントアテステーション発行者の識別子の値も気にしません。
クライアントアテステーションの署名の検証は、あなたの認可サーバの実装で実施しなければなりません。将来、この検証処理を補助する仕組みを Authlete は提供するかもしれません。generate-client-attestation スクリプトは次のような JWT
フォーマットのクライアントアテステーションを生成します。
iss クレームの値として使われていること、
クライアントの公開鍵が cnf.jwk プロパティの値として埋め込まれていることを確認できます。
client.jwk) を使い、
クライアントアテステーション PoP を次のように生成することができます。
generate-client-attestation-pop スクリプトは次のような JWT
フォーマットのクライアントアテステーション PoP を生成します。
iss クレームの値として使われていること、認可サーバの識別子が
aud クレームの値として指定されていることを確認できます。
4.5.2.3. 手順 3 : PAR リクエスト用 DPoP Proof JWT
DPoP Proof JWT を生成するため、oid4vci-demo レポジトリ内のgenerate-dpop-proof スクリプトを使うことができます。
oid4vci-demo レポジトリにある DPoP デモ用の鍵 (dpop.jwk) を使い、次のようにスクリプトを起動できます。
generate-dpop-proof スクリプトの -u オプション
(--htu オプションの短縮版) で DPoP Proof JWT の htu
クレームの値を指定します。ここで生成する DPoP Proof JWT は PAR リクエストのためのものなので、-u
オプションの値として PAR エンドポイントの URL
(https://trial.authlete.net/api/par)
を指定しています。generate-dpop-proof スクリプトは次のような JWT
フォーマットの DPoP Proof JWT を生成します。
htu クレームが PAR エンドポイントの URL を保持しています。
4.5.2.4. 手順 4 : PAR リクエスト
認可エンドポイントよりも PAR エンドポイントが優れている点の一つは、PAR エンドポイントでクライアント認証を行えることです。 このデモでは、PAR エンドポイントにアクセスする際にアテステーションによるクライアント認証を用います。 当クライアント認証方式では二つの JWT、すなわちクライアントアテステーションとクライアントアテステーション PoP、をOAuth-Client-Attestation HTTP ヘッダと
OAuth-Client-Attestation-PoP HTTP ヘッダで指定します。
手順 2 で生成したクライアントアテステーションとクライアントアテステーション PoP、および手順 4 で生成した
DPoP Proof JWT とともに、次のコマンドを実行することで PAR リクエストを行えます。
コマンドライン内の ${CLIENT_ATTESTATION}、${CLIENT_ATTESTATION_POP}、
${DPOP_PROOF_JWT_FOR_PAR_REQUEST}、${CODE_CHALLENGE}
は、ここまでの手順で取得した実際の値で置き換えてください。
request_uri プロパティが含まれています。
このプロパティの値は、事前登録された認可リクエストを表すリクエスト URI です。
urn:ietf:params:oauth:request_uri:-CYpNdxTlS3S7e0PQKJVehPMnC0iiIk4pqJpD25k0Ws
です。この値は認可リクエストの request_uri パラメーターの値として用いることになります。
4.5.2.5. 手順 5 : 認可リクエスト
次の URL をあなたのウェブブラウザのアドレスバーに入力してください。 これは、認可サーバの認可エンドポイントへの認可リクエストです。 URL 内の${REQUEST_URI} を直前の手順で取得したリクエスト URI
の実際の値で置き換えることを忘れないでください。
inga、inga を入力し、続けて Authorize ボタンを押してください。


code パラメータの値が発行された認可コードです。
この例では、認可コードの値は
yn1W7SLX9OEGqFZ2D986iPowVnoQtIRpPByBEyiIrBk
です。
認可コードはのちほどトークンリクエストで使います。
4.5.2.6. 手順 6 : トークンリクエスト用 DPoP Proof JWT
トークンエンドポイントにアクセスするため、新しい DPoP Proof JWT を作成する必要があります。 PAR リクエスト用に作成した DPoP Proof JWT を再利用することはできません。 次のコマンドにより DPoP Proof JWT を作成します。-u オプションの値が (PAR エンドポイントではなく)
トークンエンドポイントの URL であることに注意してください。
generate-dpop-proof スクリプトは次のような JWT を生成します。
htu クレームがトークンエンドポイントの URL を保持しています。
4.5.2.7. 手順 7 : トークンリクエスト
これまでの手順で次のものを用意しました。- クライアントアテステーション (JWT)
- クライアントアテステーション PoP (JWT)
- トークンリクエスト用 DPoP Proof JWT (JWT)
- 認可コード
- コードベリファイア
access_token プロパティの値は発行されたアクセストークンです。
のちほど実行するクレデンシャルリクエストにこれを含める必要があります。
c_nonce プロパティの値は発行されたノンスです。この値は次の手順で生成する
JWT Key Proof に含める必要があります。
4.5.2.8. 手順 8 : クレデンシャルリクエスト用 JWT Key Proof
POTENTIAL の Track 2 Full プロファイルでは、 “OpenID4VCI PR 293: rework credential and batch credential endpoint” で導入された新しい機能を使います。この新しい機能は、一回のクレデンシャルリクエストで複数の VC を発行することを可能にします。 複数の VC を要求するには、クレデンシャルリクエストに複数の鍵証明を含める必要があります。 そのため、ここでは、異なる保有者鍵を使って二つの JWT Key Proof を作ることにします。 oid4vci-demo レポジトリには、holder.jwk と holder2.jwk
という二つのデモ用保有者鍵が含まれています。これらの鍵と
generate-key-proof スクリプトを用い、次のように JWT Key Proof
を生成することができます。コマンドを実行する前に、コマンドライン内の ${C_NONCE}
を先の手順で取得したトークンレスポンスに含まれる c_nonce プロパティの実際の値で置き換えてください。
トークンレスポンスの
c_nonce プロパティは任意なので、あなたの認可サーバが返すトークンレスポンスはこのプロパティを含んでいないかもしれません。
そのような場合、クレデンシャルイシュアから有効な c_nonce を取得するまでは、
c_nonce を含む有効な鍵証明を生成することはできません。鍵証明に含まれる c_nonce が無効の場合、クレデンシャルイシュアはエラー応答に有効な
c_nonce を含めます。その c_nonce で有効な鍵証明を生成することができます。上記に記述した手順が示唆するのは、もしも認可サーバがトークンレスポンスに c_nonce
を含めないならば、(偽の) c_nonce
を含む鍵証明を伴う最初のクレデンシャルリクエストは必ず失敗するということです。
最初のリクエストが失敗することを知っているとしても、有効な c_nonce
を取得するためだけにそのリクエスト実行しなければなりません。トークンレスポンスの c_nonce プロパティは任意ですから、
認可サーバの実装はそのプロパティをトークンレスポンスに含めたくなければ含めなくてもかまいません。
しかしながら、業界には、認可サーバが c_nonce を発行することを認めるこの機能が気に食わず、
この機能自体を OID4VCI 仕様から削除するよう働きかけている人達がいます。
彼らの試みが成功すると、c_nonce 付きの鍵証明を含む、
世界中の全ての最初のクレデンシャルリクエストは必ず失敗することになります。OID4VCI 仕様が改訂されて c_nonce プロパティをトークンレスポンスに含めることが明示的に禁止でもされない限り、
OID4VCI 仕様の実装者向け草稿第一版との (無害な) 後方互換性のため、Authlete はトークンレスポンスの c_nonce
プロパティをサポートし続けます。しかしながら、そのような禁止事項を導入することは、
トークンレスポンスに任意のレスポンスパラメーターを含めることを許している OAuth 2.0 の中核仕様である
RFC 6749 と衝突することになるでしょう。holder.jwk を用いた JWT Key Proof の例です。ヘッダ内の jwk クレームが
holder.jwk 内の秘密鍵に対応する公開鍵を保持していることに注目してください。
holder2.jwk を用いた JWT Key Proof の例です。ヘッダ内の jwk クレームが
holder2.jwk 内の秘密鍵に対応する公開鍵を保持しています。
4.5.2.9. 手順 9 : クレデンシャルリクエスト用 DPoP Proof JWT
クレデンシャルエンドポイントにアクセスするため、再度 DPoP Proof JWT を生成する必要があります。-u オプションの値としてクレデンシャルエンドポイントの URL を指定することに加え、今回はアクセストークンの値を
-a オプション (--at オプションの短縮版) で指定する必要があります。このオプションは DPoP Key Proof に
ath クレームを含めるために必要です。
ath クレームが含まれることに注目してください。
このクレームは、アクセストークンのハッシュ値を表しています。
4.5.2.10. 手順 10 : クレデンシャルリクエスト
ここまでの手順で次のものが用意できました。- アクセストークン
- クレデンシャルリクエスト用 DPoP Proof JWT (JWT)
- JWT Key Proof 1 (JWT)
- JWT Key Proof 2 (JWT)
proof プロパティではなく
proofs プロパティを含んでいることです。この proofs プロパティは
OpenID4VCI PR 293 により新たに導入されたものであり、複数の鍵証明を含めることを可能にします。
クレデンシャルエンドポイントは次のような応答を返します。
credential プロパティではなく credentials プロパティが含まれます。
credentials 配列内の要素は発行された VC です。この例では、クレデンシャルリクエストが
2 つの鍵証明を含んでいたので、credentials 配列は二つの VC を含んでいます。
VC のフォーマットは SD-JWT です。oid4vci-demo レポジトリにある
decode-sd-jwt スクリプトを用いて、これらの VC をデコードすることができます。
一番目の VC をデコードすると次のようになります。
cnf.jwk プロパティの値が一番目の鍵証明に埋め込まれている公開鍵と合致することです。
cnf.jwk プロパティが二番目の鍵証明に埋め込まれた公開鍵に合致することを確認できます。