> ## Documentation Index
> Fetch the complete documentation index at: https://developers.authlete.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenID for Verifiable Credential Issuance

> OpenID for Verifiable Credential Issuance 仕様と、Authlete が当仕様をどのようにサポートするかを説明する文書

<Info>
  For **Authlete 2.x** documentation, see [2.x version](/v2/protocols-and-flows/verifiable-credentials/oid4vci).
</Info>

## 1. はじめに

この文書は、『**[OpenID for Verifiable Credential Issuance][OID4VCI]**』(**OID4VCI**) 仕様、および <ruby>Authlete <rp>(</rp><rt>オースリート</rt><rp>)</rp></ruby> が当仕様をどのようにサポートするかを解説します。

優に百枚を超える図を用いて様々な概念の概要と詳細を丁寧に説明します。読者が文書内を行ったり来たりする必要に迫られることなく内容を理解できるよう、説明前の概念を前提知識として使うことを注意深く避けています。また、読者が途中で迷子にならないよう、全体像を説明している途中で詳細説明に入らないようにしています。これらの配慮により、この文書は仕様本体よりも格段に読みやすくなっています。そのため、事前にこの文書を読んでおけば仕様を読む際に大きな助けとなるでしょう。

**変更履歴**

| 日付               | 変更内容                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 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](https://datatracker.ietf.org/doc/draft-ietf-oauth-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](https://github.com/authlete/cbor/pull/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

『**<ruby>Verifiable Credential <rp>(</rp><rt>ベリファイアブル クレデンシャル</rt><rp>)</rp></ruby>**』(**検証可能な資格証明**) は、OID4VCI 仕様の中心となる技術用語です。以降、本文書では VC と呼ぶことにします。

用語内の『Credential』(資格証明) は、一人のユーザまたは複数のユーザ (または特定可能な任意の実体) に関するデータ集合を表しています。氏名や生年月日といった情報はユーザに関するデータの例です。

用語内の『Verifiable』(検証可能な) は、データ集合が改竄されていないことを検証可能であることを示しています。技術的には、データ集合が電子的に署名されていることを意味します。

<img src="https://mintcdn.com/authlete/UdhsyS8JFpC2EXja/protocols-and-flows/compliance-profiles/verifiable_credential.png?fit=max&auto=format&n=UdhsyS8JFpC2EXja&q=85&s=252e9c65a2aef38c656407bd81ceaaa2" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/verifiable_credential.png" />

携帯端末上の電子的な運転免許証や健康保険証などが VC の例です。

#### 2.1.2. Credential Issuer

VC は『**<ruby>Credential Issuer <rp>(</rp><rt>クレデンシャル イシュア</rt><rp>)</rp></ruby>**』(**資格証明発行者**) により発行されます。クレデンシャルイシュアも技術用語です。仕様はクレデンシャルイシュアの動作を記述しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/core_terms_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=95a1e1ecabf797e9f526b005ad7cc615" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/core_terms_1.png" />

#### 2.1.3. Access Token

VC をクレデンシャルイシュアから取得するためには、発行を要求する際にクレデンシャルイシュアに対して『**<ruby>Access Token <rp>(</rp><rt>アクセス トークン</rt><rp>)</rp></ruby>**』(**アクセストークン**) を提示しなければなりません。このアクセストークンとは、**OAuth 2.0** の中心となる仕様である [RFC 6749][RFC_6749] で定義されているアクセストークンを指します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/core_terms_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=b9e8325365ed5153dba9ed2f96bf132a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/core_terms_2.png" />

#### 2.1.4. Authorization Server

アクセストークンは『**<ruby>Authorization Server <rp>(</rp><rt>オーソリゼーション サーバ</rt><rp>)</rp></ruby>**』(**認可サーバ**) により発行されます。認可サーバの基本的な動作は [RFC 6749][RFC_6749] で定義されており、また、その RFC 6749 を中心として、認可サーバの追加機能を定義する数多くの標準仕様が存在します。OID4VCI 仕様も同様に、VC 発行に使えるアクセストークンを認可サーバが発行できるようにするため、認可サーバに対する追加仕様を定めています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/core_terms_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=9c133f445758bc5e4f3146b209e692dd" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/core_terms_3.png" />

#### 2.1.5. Wallet

OID4VCI 仕様では、VC を取得するために認可サーバやクレデンシャルイシュアとやりとりするソフトウェアアプリケーションを『**<ruby>Wallet <rp>(</rp><rt>ウォレット</rt><rp>)</rp></ruby>**』(**ウォレット**) と呼びます。技術的には、VC 発行の文脈ではウォレットは OAuth 2.0 の**クライアントアプリケーション**として動作します。そのため、OID4VCI 仕様の文脈では、技術的な観点からは、ウォレットという用語とクライアントアプリケーションという用語は相互に交換可能です。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/core_terms_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=a279d72389e324e9334040b1dc4561a3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/core_terms_4.png" />

<Note>
  ただし、本文書では説明しない『OpenID for Verifiable Presentations』の文脈では、ウォレットはクライアントアプリケーションではなくサーバとして動作するので注意してください。
</Note>

#### 2.1.6. 関係性

次の図は中心となる技術用語間の関係を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/core_terms.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ee9082aec64002fb0272c4e0e920632f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/core_terms.png" />

### 2.2. アクセストークン発行の概要

#### 2.2.1. 事前認可コードフロー

仕様では、VC 発行に使えるアクセストークンを発行するための方法を幾つか定義しています。

それらのうちの一つは完全に新しいもので、『**<ruby>Pre-Authorized Code Flow <rp>(</rp><rt>プリオーソライズド コード フロー</rt><rp>)</rp></ruby>**』(**事前認可コードフロー**) と呼ばれます。このフローでは、最初の手順として、ウォレットはクレデンシャルイシュアから『**<ruby>pre-authorized code<rp>(</rp><rt>プリオーソライズド コード</rt><rp>)</rp></ruby>**』(**事前認可コード**) を取得します。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/pre-authorized_code_flow_1.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=f3a2e6046177b95fd3b848ee8ecc04fb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow_1.png" />

そして、ウォレットは事前認可コードを認可サーバの『**<ruby>Token Endpoint <rp>(</rp><rt>トークン エンドポイント</rt><rp>)</rp></ruby>**』(**トークンエンドポイント**) ([RFC 6749][RFC_6749], [3.2. Token Endpoint][RFC_6749_3_2]) に提示します。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/pre-authorized_code_flow_2.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=1402d67f2a00fcabfab2fa5bae5f326f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow_2.png" />

引き換えに、ウォレットはアクセストークンを受け取ります。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/pre-authorized_code_flow_3.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=5410a53bd3673deff1f0c33874692178" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow_3.png" />

先ほど説明したように、ウォレットはそのアクセストークンをクレデンシャルイシュアに提示します。具体的には、ウォレットはアクセストークンをクレデンシャルイシュアの『**<ruby>Credential Endpoint <rp>(</rp><rt>クレデンシャル エンドポイント</rt><rp>)</rp></ruby>**』(**クレデンシャルエンドポイント**) に提示します。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/pre-authorized_code_flow_4.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=bb0d62680a9b5d125e6eb2573a664e4a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow_4.png" />

引き換えに、ウォレットは VC を受け取ります。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/pre-authorized_code_flow_5.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=d8f713ea5fd8bdf92b1415f2c52115ca" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow_5.png" />

次の図は事前認可コードフローの概要を示しています。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/pre-authorized_code_flow.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=b55ebef538cf72f77c9754585c491594" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/pre-authorized_code_flow.png" />

#### 2.2.2. 認可コードフロー

事前認可コードフロー以外の方法は、伝統的な『**<ruby>Authorization Code Flow <rp>(</rp><rt>オーソリゼーション コード フロー</rt><rp>)</rp></ruby>**』(**認可コードフロー**) ([RFC 6749][RFC_6749], [4.1. Authorization Code Grant][RFC_6749_4_1]) の拡張です。

認可コードフローを復習しましょう。

認可コードフローでは、最初の手順として、クライアントアプリケーション (OID4VCI の文脈ではウォレット) はウェブブラウザを介して認可サーバの『**<ruby>Authorization Endpoint <rp>(</rp><rt>オーソリゼーション エンドポイント</rt><rp>)</rp></ruby>**』(**認可エンドポイント**) ([RFC 6749][RFC_6749], [3.1. Authorization Endpoint][RFC_6749_3_1]) に『**<ruby>Authorization Request <rp>(</rp><rt>オーソリゼーション リクエスト</rt><rp>)</rp></ruby>**』(**認可リクエスト**) を送ります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=11ce2f4aeae6e397f685dfa8c0549cd5" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_1.png" />

認可リクエストを受け取ると、認可サーバはウェブブラウザを介してユーザとやり取りを始めます。そしてユーザから同意を得た後、認可サーバはクライアントアプリケーションに『**<ruby>Authorization Code <rp>(</rp><rt>オーソリゼーション コード</rt><rp>)</rp></ruby>**』(**認可コード**) を発行します。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=4e14a502510a8f779d62ddc9d3496d9f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_2.png" />

その後、クライアントアプリケーションはその認可コードを含む『**<ruby>Token Request <rp>(</rp><rt>トークン リクエスト</rt><rp>)</rp></ruby>**』(**トークンリクエスト**) を認可サーバのトークンエンドポイントに送ります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_3.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=d74a0d40fe0f4c575144ddd97cdf0998" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_3.png" />

引き換えに、クライアントアプリケーションはアクセストークンを受け取ります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_4.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=9577b9e5a49c20815239b32be1ef8ad6" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_4.png" />

アクセストークンを取得した後の処理は事前認可コードフローのものと同じです。クライアントアプリケーションはクレデンシャルイシュアのクレデンシャルエンドポイントにアクセストークンを提示します。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_5.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=36155eb2df1b1b9b2410d75d8f608335" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_5.png" />

引き換えに、クライアントアプリケーションは VC を受け取ります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow_6.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=1ffacd114b77d33bbe4d0d178c2a32f4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow_6.png" />

次の図は、認可コードフローと、それに続く VC 発行を示しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=58477031e2c562e3dd9c02c5669eb6c3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow.png" />

OID4VCI 仕様は認可コードフロー中の認可リクエストを拡張します。具体的には、次に挙げる認可リクエストパラメーター群を利用します。

1. `issuer_state` リクエストパラメーター
2. `authorization_details` リクエストパラメーター
3. `scope` リクエストパラメーター

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_request_parameters.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=0f7e5b2e6cecb58eeaaffdf58bb2a555" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_request_parameters.png" />

`issuer_state` リクエストパラメーターは OID4VCI 仕様で定義される新しいパラメーターです。

`authorization_details` リクエストパラメーターは [RFC 9396 OAuth 2.0 Rich Authorization Requests][RFC_9396] で定義されています。この仕様は **<ruby>RAR <rp>(</rp><rt>ラー</rt><rp>)</rp></ruby>** と略して呼ばれることがあります。

`scope` リクエストパラメーターは [RFC 6749 The OAuth 2.0 Authorization Framework][RFC_6749] で定義されているパラメーターです。

<Note>
  この文書を書いている時点では、上記のパラメーター群が組み合わされて使われた場合について仕様は何も言及していません。これらの仕組みが相互排他の関係にあるのか、それとも共存可能なのか明確ではありません。

  Authlete の現在の実装は、これらの仕組みを全て考慮に入れ、リクエストパラメーターを介して指定された全ての VC の発行に使えるアクセストークンを生成します。
</Note>

#### 2.2.3. 認可コードフロー + issuer\_state

`issuer_state` リクエストパラメーターは OID4VCI 仕様で定義されています。このリクエストパラメーターを使うためには、認可リクエストをおこなう前に、ウォレットはクレデンシャルイシュアから『**<ruby>Issuer State <rp>(</rp><rt>イシュア ステート</rt><rp>)</rp></ruby>**』(**イシュアステート**) を取得しておく必要があります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=724935349a4f789ae2dc0023b1849b84" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_1.png" />

その後ウォレットは、そのイシュアステートを `issuer_state` リクエストパラメーターの値として含む認可リクエストをおこないます。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=358aa35c8dc720dcca71d6394dc5be9c" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_2.png" />

認可リクエストの残りの部分は、通常の認可コードフローと同じです。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_3.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=bb3e93a35294dff3155aff24a43c598a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state_3.png" />

次の図はイシュアステートを用いる認可コードフローを示しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=104c8d418943deb4761119a4fd289cca" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+issuer_state.png" />

#### 2.2.4. 認可コードフロー + authorization\_details

RAR 仕様 ([RFC 9396][RFC_9396]) は、認可に関する詳細情報を伝えるための汎用的なパラメーターとして `authorization_details` を定義しています。このパラメーターをどのように使うかは、それぞれの運用に任されています。

このパラメーターの値は JSON 配列であり、配列の各要素は JSON オブジェクトです。このオブジェクトは『**RAR オブジェクト**』と呼ばれます。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+authorization_details_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=641f7d799059d7ea2375ce60fc502c23" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+authorization_details_1.png" />

RAR オブジェクトは柔軟です。任意のプロパティをオブジェクト内に置くことができます。しかし、想定される用途で共通して使われるであろうプロパティがあるため、RAR 仕様は幾つかのプロパティを事前に定義しています。

そのような事前定義されたプロパティ群のうち、`"type"` プロパティだけは必須です。このプロパティは RAR オブジェクトが何を表しているのかを示します。

そして OID4VCI 仕様は、ウォレットが欲しい VC に関する情報を含む RAR オブジェクトであることを示すための特別な `"type"` 値として `"openid_credential"` を定義しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+authorization_details_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=fc877b38e86458043233939c092e3b61" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+authorization_details_2.png" />

#### 2.2.5. 認可コードフロー + scope

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

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+scope_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=633634be8bc5e9ff59a46135cc52c93f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+scope_1.png" />

歴史的に `scope` リクエストパラメーターは元々意図していた用途外でも利用されてきました。そして、OID4VCI 仕様も同様に `scope` リクエストパラメーターの使い方を拡張します。

クレデンシャルイシュアは、自身が発行可能な VC を『**<ruby>Credential Configuration <rp>(</rp><rt>クレデンシャル コンフィギュレーション</rt><rp>)</rp></ruby>**』(**クレデンシャル設定**) として管理しており、そのリストをある場所で公開しています。各クレデンシャル設定は `"scope"` プロパティを持つことがあります。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+scope_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=5b6ae1df5aec9a9e241c428583422791" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+scope_2.png" />

ウォレットは、どの種類の VC が欲しいかを示すために、`"scope"` プロパティの値を `scope` リクエストパラメーターに含めることができます。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authorization_code_flow+scope_3.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=980ae5b5dfa4932074ee49ad02010d51" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authorization_code_flow+scope_3.png" />

複数のクレデンシャル設定が同じ値を `"scope"` プロパティに持つ場合もあります。

<Note>
  OAuth 2.0 の中心仕様 ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749.html))
  が未知の `scope` 値を無視するように認可サーバに要求しているため、クレデンシャル設定の
  `"scope"` プロパティの値をサポートするスコープ値として認可サーバに明示的に登録する必要がある可能性が高いです。

  加えて、[OpenID Federation](https://openid.net/specs/openid-federation-1_0.html)
  を利用している場合、VC 発行のための `scope` 値をメタデータポリシーが意図せずに削除することがないよう、注意が必要です。
</Note>

### 2.3. クレデンシャル発行の概要

認可サーバからアクセストークンを取得すれば、ウォレットはアクセストークンを提示することにより、クレデンシャルイシュアに VC の発行を要求することができます。

基本的な手順では、ウォレットはクレデンシャルイシュアのクレデンシャルエンドポイントにアクセストークンを含むクレデンシャルリクエストを送ります。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/deferred_issuance_1.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=2a666fd53783d9895c9930e96862b112" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/deferred_issuance_1.png" />

クレデンシャルイシュアは応答として要求された VC を発行します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/deferred_issuance_2.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=8c9df9504358a865a529fba5e486e3cb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/deferred_issuance_2.png" />

#### 2.3.1. 遅延クレデンシャル発行

しかし、要求された時点で VC が用意できていないこともありえます。たとえば、裏で時間のかかるオフライン処理が走っているかもしれません。

このような場合、クレデンシャルイシュアは代わりに『<ruby>Transaction ID <rp>(</rp><rt>トランザクション アイディー</rt><rp>)</rp></ruby>』(**トランザクション ID**) を発行します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/deferred_issuance_3.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=28bf72056c7984a40d31aca0028cce5b" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/deferred_issuance_3.png" />

ウォレットは VC 発行の準備が整うまで待機します。その後、受信済みのトランザクション ID とアクセストークンを『**<ruby>Deferred Credential Endpoint <rp>(</rp><rt>ディファード クレデンシャル エンドポイント</rt><rp>)</rp></ruby>**』(**遅延クレデンシャルエンドポイント**) に提示します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/deferred_issuance_4.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=ee4ecda7040f4ba853e1fe89cee5d091" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/deferred_issuance_4.png" />

クレデンシャルイシュアは応答として要求された VC を発行します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/deferred_issuance_5.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=27d108e5025796365d1c6540958eedb3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/deferred_issuance_5.png" />

VC が依然として用意できていない場合、遅延クレデンシャルエンドポイントはその旨を示すエラー (たとえば `"error":"issuance_pending"`) を返すでしょう。このような場合、ウォレットは後ほど再び『**<ruby>Deferred Credential Request <rp>(</rp><rt>ディファード クレデンシャル リクエスト</rt><rp>)</rp></ruby>**』(**遅延クレデンシャルリクエスト**) を実行します。

#### 2.3.2. 一括クレデンシャル発行

ウォレットは一度に複数の VC を入手したいことがあるかもしれません。そのような場合のために『**<ruby>Batch Credential Endpoint <rp>(</rp><rt>バッチ クレデンシャル エンドポイント</rt><rp>)</rp></ruby>**』(**一括クレデンシャルエンドポイント**) があります。

ウォレットはアクセストークンを含む『**<ruby>Batch Credential Request <rp>(</rp><rt>バッチ クレデンシャル リクエスト</rt><rp>)</rp></ruby>**』(**一括クレデンシャルリクエスト**) を一括クレデンシャルエンドポイントに送信します。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_issuance_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=3b9585df011a7c5d1382f780a3cf8032" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_issuance_1.png" />

エンドポイントは、複数の VC またはトランザクション ID を返却します。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_issuance_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=ee0bb9d849179e315c5ab613689eb931" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_issuance_2.png" />

各トランザクション ID は、遅延クレデンシャルエンドポイントから VC を取得するために使うことができます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/batch_issuance_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=b61836d8d07bd7327cd61e845244de6b" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_issuance_3.png" />

### 2.4. アクセストークン発行の詳細

ここまでの説明で、アクセストークン発行とクレデンシャル発行の概要を見てきました。この節ではアクセストークン発行の詳細について見ていこうと思います。

#### 2.4.1. クレデンシャルオファー

クレデンシャルイシュアが事前認可コードを発行する際、それを直接発行する代わりに、それを内包する『**<ruby>Credential Offer <rp>(</rp><rt>クレデンシャル オファー</rt><rp>)</rp></ruby>**』(**クレデンシャルオファー**) を発行します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_01.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ee9bcc29a895e860dbe21cc71511413e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_01.png" />

同様に、イシュアステートもクレデンシャルオファーの一部として含まれます。クレデンシャルオファーは、事前認可コードもしくはイシュアステート、または両方を含むことがあります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_02.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=6e53a5bb44d27ec7fad8cf202577741f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_02.png" />

クレデンシャルオファーは他の情報も含んでいます。クレデンシャルイシュアの識別子は常に含まれます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_03.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=1f402b4f5c8311f0c406407b72ba0231" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_03.png" />

また、クレデンシャルオファーは、クレデンシャルイシュアが提供する VC に関する情報を含んでいます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_04.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=611b320e8eae1083a9bbab7466921dd0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_04.png" />

##### 2.4.1.1. 値によるクレデンシャルオファー発行

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_05.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=b00f103ff81ed27a8128f8ee18fef47c" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_05.png" />

その URL が何らかの方法でアクセスされ、そのアクセスをウォレットが処理することができれば、ウォレットはクレデンシャルオファーを受け取ることができます。

しかし、ここで問題なのは、どのようにそのアクセスを引き起こすかです。OID4VCI 仕様ではクレデンシャルイシュアによる HTTP GET リクエストや HTTP リダイレクションの始動を想定していますが、アクセスの引き起こし方についてクレデンシャルイシュアとウォレットがどのように合意するかは定めていません。

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_06.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=35c3e50c1f654e5c28fbbd6b922a49b4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_06.png" />

<Note>
  上記のような理由から、クレデンシャルイシュアはクレデンシャルオファーの生成と転送をそれぞれ独自の方法で実装するでしょう。そのため、相互運用性はあまり期待できません。
</Note>

##### 2.4.1.2. 参照によるクレデンシャルオファー発行

クレデンシャルオファーは参照によってウォレットに渡されるかもしれません。具体的には、URL は発行されたクレデンシャルオファーの内容ではなく、その配置場所に関する情報を含んでいるかもしれません。この場合、その場所を示すために `credential_offer_uri` クエリパラメーターが用いられます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_07.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=79b91ac996bbc721d5ce3b5f9af76953" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_07.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_08.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=d8efb2bd2b03811f115e7ac01bab1578" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_08.png" />

その URI にアクセスすることにより、

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_09.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ed612840f1644363378910ef0907dba2" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_09.png" />

ウォレットは発行されたクレデンシャルオファーの内容を取得することができます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_10.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=9ac332d8ad2f7f348ebfa6efe6418479" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_10.png" />

##### 2.4.1.3. クレデンシャルオファーの内容

クレデンシャルオファーの実際の内容は JSON オブジェクトです。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=4ce204bae873bd1d49b3a04e0335f26d" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_1.png" />

クレデンシャルイシュアの識別子が、`"credential_issuer"` プロパティの値として置かれます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f96d739a68eeb8d2c6a79d176115d6d7" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_2.png" />

クレデンシャルイシュアが提供する VC に関する情報は `"credential_configuration_ids"`
配列に置かれます。配列要素の詳細については後ほど紹介します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ad5d513d56c702ceb098152ccaf47812" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_3.png" />

イシュアステートが発行される場合は、幾分ネストした場所に置かれます。

クレデンシャルオファーには、トップレベルのプロパティとして `"grants"` プロパティがあります。`"grants"` プロパティの値は JSON オブジェクトです。その `"grants"` JSON オブジェクト内のキーは、`authorization_code` のようなグラントタイプ (認可種別) の識別子です。

`"grants"` JSON オブジェクト内の各エントリの値もまた JSON オブジェクトで、それぞれ、キーが示すグラントタイプに関連するプロパティ群を含んでいます。

イシュアステートの場合は、その値は `"grants"` JSON オブジェクト内の `"authorization_code"` JSON オブジェクト内の `"issuer_state"` プロパティの値として置かれます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=0d5217d45dc263431eb5612339a7dcbe" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_4.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_5.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=20e18e63b83d6d4c7ff6be565f920c32" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_5.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content_6.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=8c9f000f2a4765ee757bb6521187d10c" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content_6.png" />

次の図はクレデンシャルオファーの内容の構造を示した概要図です。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_content.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=8b283679fa88badabd848771d884a0b4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_content.png" />

##### 2.4.1.4. クレデンシャルオファー内の "credential\_configuration\_ids"

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

要素の値はクレデンシャル設定の識別子を表しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_credential_configuration_ids.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=2b3ef76769b18711c8a31131046da926" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_credential_configuration_ids.png" />

#### 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` パラメーターは必須になります。
この場合、何らかの方法でトランザクションコードがユーザに届けられるものと想定されます。

```json theme={null}
{
  "credential_issuer": "...",
  "credential_configuration_ids": [
    "..."
  ],
  "grants": {
    "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
      "pre-authorized_code": "...",
      "tx_code": {
        "length": 6,
        "input_mode": "numeric",
        "description": "Input the one-time code sent via email"
      }
    }
  }
}
```

ユーザにトランザクションコードの入力を促す UI 部品をウォレットが準備するのを手助けするため、`tx_code`
オブジェクトは次表に挙げるプロパティを含んでいることがあります。

| パラメーター        | 説明                                                    |
| :------------ | :---------------------------------------------------- |
| `length`      | トランザクションコードの長さ。                                       |
| `input_mode`  | トランザクションコードの入力モード。事前定義されている値は `"numeric"` と `"text"`。 |
| `description` | 配送チャネルなど、トランザクションコードに関する情報。                           |

また、クライアント認証に関連するリクエストパラメーターも追加で要求されるかもしれません。例えば `private_key_jwt` クライアント認証が用いられる場合、`client_assertion` リクエストパラメーターと `client_assertion_type` リクエストパラメーターが必要となります。

<Note>
  OID4VCI 仕様の野心的な試みの一つは、認可サーバの設定に依存しますが (具体的には `pre-authorized_grant_anonymous_access_supported`
  サーバメタデータが `true` の場合ですが)、クライアントアプリケーションを特定する情報を何も含まないトークンリクエストが許容される場合があります。
  実際にそのようなトークンリクエストが実行された場合、特定のクライアントアプリケーションに紐付かないアクセストークンが発行されることになります。
</Note>

下記は、OID4VCI 仕様から抜粋したクライアント認証を伴わない事前認可コードフローのトークンリクエストの例です。

```http theme={null}
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code
&pre-authorized_code=SplxlOBeZQQYbYS6WxSbIA
&tx_code=493536
```

いつものように、トークンエンドポイントはアクセストークンを含む応答を返します。下記は仕様書から抜粋したトークンレスポンスの例です。

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ",
  "token_type": "bearer",
  "expires_in": 86400,
  "c_nonce": "tZignsnFbp",
  "c_nonce_expires_in": 86400
}
```

上記の例が示すように、発行されたアクセストークンが VC 発行に使用可能な場合、トークンレスポンスは
OAuth 2.0 の中心仕様 ([RFC 6749][RFC_6749]) で定義されている昔ながらのレスポンスパラメーター群
(`access_token`, `token_type`, `expires_in`) に加えて、`c_nonce` レスポンスパラメーターと
`c_nonce_expires_in` レスポンスパラメーターを含む場合があります。
これらのレスポンスパラメーター群の詳細は後ほど説明します。

#### 2.4.3. 発行可能クレデンシャル

VC 用アクセストークンを発行する手段が幾つか用意されているものの、アクセストークンの実装の観点から言えば、全て一つの共通の目標に収束します。それは、発行可能な VC 種別に関する情報をアクセストークンに紐付けることです。

この文書では、その情報を『**<ruby>Issuable Credential <rp>(</rp><rt>イシュアブル クレデンシャル</rt><rp>)</rp></ruby>**』(**発行可能クレデンシャル**) と呼びます。ただし、この用語は公式のものではないので、その点はご留意ください。

クレデンシャルオファーの `"credential_configuration_ids"` 配列の要素 JSON 文字列です。
それらは、クレデンシャル設定を参照することにより発行可能クレデンシャルを間接的に指定しています。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_01.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=f474fc57125df20c14d9a73ed5b0635e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_01.png" />

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

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_02.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=e26bde397b291f0563092cca30d0d8f0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_02.png" />

そのため、事前認可コードフローを用いるトークンリクエストは、事前認可コードを含むクレデンシャルオファーで指定される発行可能クレデンシャル群に紐付いたアクセストークンを要求していると言えます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_03.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=cd2b7c56eb1cad3d1e7008d2a9ea0af0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_03.png" />

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

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_04.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=79a36f12fb034f7458c15940b73aa87e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_04.png" />

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

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_05.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=8b6f1d53a146131ae2f51511d1df22cb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_05.png" />

または、代わりに `format` プロパティを使うこともあります。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_06.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=1dc1d4a479074d2a92695819be0737f9" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_06.png" />

<Note>
  `openid_credential` タイプの RAR オブジェクトでは、
  `credential_configuration_id` プロパティと
  `format` プロパティは相互排他の関係にあります。
</Note>

`scope` リクエストパラメーター内の値は、クレデンシャル設定の `"scope"` プロパティを介して一つ以上の発行可能クレデンシャルを間接的に指定するかもしれません。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_07.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=ba8f764ca34cf51eeb0add06b5a43283" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_07.png" />

現在の OID4VCI 仕様のドラフトでは発行可能クレデンシャルを指定するこれらの仕組みが同時に使われた場合について明示的に言及していませんが、我々の解釈と実装では、これらの仕組みで指定された全ての発行可能クレデンシャル群は結合されて一つの集合を形成します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_08.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=49569a314a89d9469f34c72f01b708c5" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_08.png" />

次の図は発行可能クレデンシャルを指定する仕組みの全体像を示しています。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=ae1c61925128f6d11aa1586b2c3b535a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential.png" />

図中の credential info (クレデンシャル情報) と RAR オブジェクトの構造について気になっているかもしれません。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_09.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=e1d0423b22e1b0b7329d7418952fdb4f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_09.png" />

しかし、それらの詳細に立ち入る前に、VC のフォーマットについて見ていく必要があります。

### 2.5. クレデンシャル検証

VC のフォーマットを議論するためには、それらが意図する目的を理解する必要があります。VC の検証処理を一つ一つ見ていくことにしましょう。

まず始めに、クレデンシャルイシュアは VC に含めるデータを用意します。この例では、name (氏名)、birthdate (生年月日)、address (住所) を使います。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_verification_01.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=7fa4c93af19596b8283f9782922b7208" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_01.png" />

データに署名するため、クレデンシャルイシュアは private key (秘密鍵) と public key (公開鍵) の組を用意します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_verification_02.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f1453369eb350b870f645cf08f8ae1d3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_02.png" />

その後、クレデンシャルイシュアは秘密鍵を用いてデータに署名します。結果として、署名が生成されます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_03.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=2ef26b910d0683aed0e29f2dabb5ccc0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_03.png" />

このデータと署名の集合が VC です。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_04.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=fca28601e8810f175dd2f04a644972b1" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_04.png" />

クレデンシャルイシュアは VC をウォレットに渡します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_05.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=11ba047120b8ff9e482c6ab6e57caba7" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_05.png" />

ウォレットが VC の署名を検証したければ、何らかの方法でクレデンシャルイシュアから公開鍵を取得し、それを署名検証に用います。検証が成功すれば、その VC が正当なクレデンシャルイシュアから発行されたこと、及びその内容が改竄されていないことが保証されます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_06.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=507fc61dbc22ca5d96d22aaec66c1ec4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_06.png" />

VC の利用方法と ID トークンの利用方法との重要な違いは、VC の『**<ruby>Holder <rp>(</rp><rt>ホルダー</rt><rp>)</rp></ruby>**』(**保有者**) は VC を他者に提示することがある点です。提示の前に、VC は『**<ruby>Verifiable Presentation <rp>(</rp><rt>ベリファイアブル プレゼンテーション</rt><rp>)</rp></ruby>**』(**検証可能なプレゼンテーション**) に変換されます。本文書では、以降 Verifiable Presentation を VP と呼ぶことにします。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_07.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=c57e6596e5b5176b8d821d41b3e0fdf8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_07.png" />

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

ウォレットは VP を他者に提示します。VP を受け取る部外者は『**<ruby>Verifier <rp>(</rp><rt>ベリファイア</rt><rp>)</rp></ruby>**』(**検証者**) と呼ばれます。というのは、ホルダーに対してサービスを提供する前にベリファイアは VP の検証をおこなうものと想定されているからです。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_08.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=68f51b479075f5d42ef461025106a813" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_08.png" />

ベリファイアが VP の署名を検証したければ、何らかの方法でクレデンシャルイシュアから公開鍵を取得し、それを署名検証に用います。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_09.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=4e3e73113a4010bb7ffcb6415ec8ec46" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_09.png" />

#### 2.5.1. キーバインディング

ところで、ベリファイアは次の事項をどうすれば確認できるでしょうか？

1. VP が当ホルダーによって提示されたこと
2. VP の元となった VC はクレデンシャルイシュアが当ホルダーに対して発行したものであること

一点目については、ホルダーに秘密鍵と公開鍵の組を提供してもらい、

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_10.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=3011069cc591b92ac8b9c5ab2a23acdb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_10.png" />

そのホルダーの秘密鍵を用いて作成した署名を VP に含めることで実現できるでしょう。署名対象のデータは、署名と共に提示される限り、任意のデータでかまいません。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_11.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=cb04a61be95fb4dbe07a93f893affa52" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_11.png" />

二点目については、ホルダーの公開鍵を VC のデータに含め、クレデンシャルイシュアにデータ全体に対して署名してもらうことで実現できます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_12.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=13690213308f6c221c11e1b8c349b76a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_12.png" />

VC とホルダー間のこのような暗号的関連付けは『**<ruby>Key Binding <rp>(</rp><rt>キー バインディング</rt><rp>)</rp></ruby>**』(**キーバインディング**) と呼ばれます。

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

ウォレットが暗号的キーバインディング付きの VC を要求する場合、クレデンシャルリクエストに公開鍵を含めます。しかし、クレデンシャルイシュアは提示された公開鍵を無条件に受け入れるわけにはいきません。というのは、悪意のあるウォレットが無関係な公開鍵を提示するかもしれないからです。

そのため、ウォレットは自身が公開鍵の正当な所有者であることを示さなければなりません。これを実現するため、ウォレットは対応する秘密鍵を用いて署名を生成し、公開鍵と併せて提示します。この署名と公開鍵の組みは一般的に『**<ruby>Key Proof <rp>(</rp><rt>キー プルーフ</rt><rp>)</rp></ruby>**』(**鍵証明**) と呼ばれます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_13.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=65db308817fdbbc5b1548331aa8e9a81" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_13.png" />

提示された公開鍵の有効性を確認できれば、クレデンシャルイシュアはキーバインディング付きの VC を生成することができます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_14.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=00db2fc6e8f05dee14004e7896be06c3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_14.png" />

その VC はウォレットに渡され、

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_15.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=2f612c5d06d6cbbaff30d83c8b2ce456" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_15.png" />

ウォレットはその VC を元に VP を生成します。ウォレットは秘密鍵を用いて作成した署名を VP に含めます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_16.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=3f681d0d15504358f65469511b5b71b2" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_16.png" />

そして VP がベリファイアに渡されます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_17.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=3ec30e4ee6d812555b495cfc17719f6f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_17.png" />

ベリファイアは、VP に埋め込まれている公開鍵を用いてウォレットが追加した署名を検証することができます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_18.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=e02944fe22d2a43748cd8c2ae9cb6bd8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_18.png" />

次の図は、これまでに説明したクレデンシャル検証処理の全体像を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_verification.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f29f85df7c0ab59f4f19d69ab71caa5a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification.png" />

### 2.6. 選択的開示

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

このように情報を選んで開示することを『**<ruby>Selective Disclosure <rp>(</rp><rt>セレクティブ ディスクロージャ</rt><rp>)</rp></ruby>**』(**選択的開示**) と言います。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/selective_disclosure_1.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=121aafa0fd894b1f2a8ff204cc88e939" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/selective_disclosure_1.png" />

しかし、特別な考慮をせずに情報を省略すると、署名検証が失敗してしまいます。なぜなら、署名が対象としたデータ集合とベリファイアが受け取ったデータ集合が異なるからです。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/selective_disclosure_2.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=6b7b97a0490fb9c8b6e08d61ea5b2a6d" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/selective_disclosure_2.png" />

署名を無効化することなく選択的開示を実現する手法が幾つかあります。BBS+ (Boneh-Lynn-Shacham signature plus) や CL Signatures (Camenisch-Lysyanskaya Signatures) はそのような例で、有望のように思われます。しかしながら、現実世界では、特定の手法が採用されるかどうかは下記に挙げるように様々な要因に依存しており、必ずしも学術的に美しい理論に基づく解決策が普及するとは限りません。

1. 理論の複雑さ
2. 実装の容易さ
3. ライセンス費用
4. 使用する際の法的制限
5. ハードウェアセキュリティモジュール製品によるサポート
6. アルゴリズムの頑健性/安全性を業界がどの程度信じているか

徹底的な[クレデンシャルプロファイル比較][CREDENTIAL_PROFILE_COMPARISON]とハッカソンの後、業界は『**[Selective Disclosure for JWTs (SD-JWT)][SD_JWT]**』と呼ばれる新しいフォーマットを作成することに決めました。

#### 2.6.1. SD-JWT

SD-JWT は JWT ([RFC 7519 JSON Web Token (JWT)][RFC_7519]) を利用して選択的開示を実現するフォーマットです。

通常の JWT のペイロード部には、クレーム名とクレーム値の組が含まれています。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_01.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=c4750ab694d2c8a4692e7fdbded803cd" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_01.png" />

このようなクレームを SD-JWT フォーマットを用いて選択的開示可能とするには、まず、クレームを取り出します。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_02.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=e4201cd2e70eb49dd0cf78f1665274be" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_02.png" />

そして、任意のソルト (salt) を追加し、

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_03.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=4a7cee5fd9be6084549fc3d48bb4e886" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_03.png" />

そのソルトとクレーム名およびクレーム値を含む JSON 配列を作ります。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_04.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=722ad25487e55232eeecf9586805d4b8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_04.png" />

次に、その JSON 配列を base64url でエンコードします。SD-JWT 仕様では、この結果得られる文字列を『**<ruby>Disclosure <rp>(</rp><rt>ディスクロージャ</rt><rp>)</rp></ruby>**』(**ディスクロージャ**) と呼びます。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_05.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=46a97511bd74550061985ae9182d8d4c" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_05.png" />

元のクレームはディスクロージャのダイジェスト値で置き換えられます。ダイジェスト値は base64url でエンコードされ、元のクレームが置かれていた場所に挿入された `"_sd"` 配列内に置かれます。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_06.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=10a88ffaa8f942da06a7ad33c9f659b7" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_06.png" />

選択的開示可能にする必要のある他のクレーム群に対して同じ処理を行います。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_07.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=a4f8745542039de4ce54e38d88242312" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_07.png" />

そして、クレデンシャルイシュアが署名した JWT (issuer-signed JWT) とディスクロージャ群をチルダ (`~`) で連結し、一つの文字列を作ります。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_08.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=1c7f0d439136cb39f598ae71e2073816" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_08.png" />

結果として得られた文字列が SD-JWT です。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_09.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=1fe97dafc00d2b03b26afcf663785939" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_09.png" />

次の処理は任意ですが、キーバインディングをおこないたければ、鍵の組を用意してください。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_10.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=b62fd27a5e9131ddde49ed2d5f843a7a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_10.png" />

そして、クレデンシャルイシュアが署名する JWT に公開鍵を埋め込み、

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_11.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=e28f69485cdaf8ad73a1716e7d7f98f3" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_11.png" />

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

仕様で定義される特定のデータ集合に署名し、結果として得られた JWT を先ほど生成した SD-JWT の末尾におきます。この JWT を『**<ruby>Key Binding JWT <rp>(</rp><rt>キー バインディング ジョット</rt><rp>)</rp></ruby>**』(**キーバインディング JWT**) と呼びます。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_12.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=7f81768002a330854b25dce7fd1fd301" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_12.png" />

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

次の図は、これまでに説明した SD-JWT 生成手順を示しています。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=6d8781e55a5c1613c0efd6955b7c00d1" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt.png" />

ここで鍵となるのは、SD-JWT の受信者が全てのディスクロージャを受け取っていない場合、ディスクロージャに対応するクレームしか再構築できないことです。そして重要なのは、そのような場合においてもクレデンシャルイシュアが署名した JWT の署名は有効のままという点です。

<img src="https://mintcdn.com/authlete/pc0lPZhy9Zo_eIBR/protocols-and-flows/compliance-profiles/sd-jwt_13.png?fit=max&auto=format&n=pc0lPZhy9Zo_eIBR&q=85&s=a0b039a7c648b6538151abc272f3ad9e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/sd-jwt_13.png" />

より詳細な情報は [SD-JWT 仕様][SD_JWT]を参照してください。また、Java 言語用に書かれたオープンソースの SD-JWT ライブラリである [authlete/sd-jwt][AUTHLETE_SD_JWT] の README にも有益な情報があります。

### 2.7. VC フォーマット

#### 2.7.1. VC フォーマットをめぐる混乱

VC フォーマットをめぐる混乱は、複数の競合する仕様が存在し、それぞれが課題を抱え、依然として開発中であることから来ています。また、様々な国家、地域、業界の組織が異なるフォーマットを推進していることも状況を複雑にしています。

VC となると、多くの人が **[W3C Verifiable Credentials Data Model][W3C_VCDM]** (**W3C VCDM**) を思い浮かべます。これは主に、当文書が『イシュア・ホルダー・ベリファイア』の三者間モデルを定義している一次情報源とみなされることが多いからです。しかし、W3C VCDM 自体も完全無欠というわけではなく、実際に議論は続いています。[バージョン 1.1][W3C_VCDM_1_1] は 2022 年 3 月 3 日にリリースされましたが、現在[バージョン 2.0][W3C_VCDM_2_0] の議論が進んでいます。

外部から観察したときに、さらに状況を複雑にしているのは、**[Securing Verifiable Credentials using JOSE and COSE][W3C_JOSE_COSE]** (**[w3c/vc-jose-cose][W3C_JOSE_COSE_REPO]**) という名前の仕様です。その仕様は 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][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][RFC_8949]) や **CBOR Object Signing and Encryption** (**COSE**) ([RFC 9052][RFC_9052], [RFC 9053][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]** (**SD-JWT VC**)
という仕様内で提案されました。しかし、パス名が汎用的過ぎ、JWT
発行関連の他の仕様群と簡単に衝突する恐れがあるので、後日パス名は
`/.well-known/jwt-vc-issuer` に変更されました。
それでも依然として、このパス名は、VC のフォーマットが JWT
ベースであることを不必要に想定しているという問題を抱えています。
そのため、この解決方法を好まない人々もいます。
実際に [OpenID Federation][OIDFED] を活用しているイタリアのエコシステムは
`/.well-known/jwt-vc-issuer` を使わないことを決めました。
彼らは代わりに `openid_credential_issuer`
という新しいエンティティタイプ識別子を定義し、エンティティコンフィギュレーションの
`"metadata"."openid_credential_issuer"` オブジェクトに
VC 検証用の公開鍵を埋め込むことにしました。

関連する議題として、**[OAuth 2.0 Attestation-Based Client Authentication][ATTESTATION_BASED_CLIENT_AUTH]**
と呼ばれる新しい[クライアント認証][CLIENT_AUTHENTICATION]方式が現在開発中です。
この方式のため、ウォレットはあらかじめ『**<ruby>Attester <rp>(</rp><rt>アテスタ</rt><rp>)</rp></ruby>**』(**証人**)
から『**<ruby>Wallet Attestation <rp>(</rp><rt>ウォレット アテステーション</rt><rp>)</rp></ruby>**』を取得しておく必要があります。
というのは、クライアント認証を実行するときにそれが必要になるからです。
アテステーションの受け手 (例えば認可サーバ) は、アテステーションの署名を検証するための公開鍵をアテスタから取得しなければなりません。
ここで、アテステーション用の公開鍵配布は、先に述べた VC と似たような問題となります。
そして、`/.well-known/jwt-vc-issuer` がここでも選択肢の一つとして提案されています。
これはまさに予想された通りの懸念事項です。つまり、アテスタとクレデンシャルイシュアを同じサーバ上で動かすことが技術的に不可能になるのです
(それら二つを同じサーバ上で動かすことが概念的に適切かどうかは別問題です)。
加えて、アテステーションのフォーマットが JWT かどうかは本質ではないのです。

しかし、アテステーションベースのクライアント認証に関してより深刻な問題は、
基本的な概念について完全な合意にまだ達していないことです (参照:
[ISSUE 61](https://github.com/vcstuff/draft-ietf-oauth-attestation-based-client-auth/issues/61))。

#### 2.7.2. VC フォーマットの本質的機能

前節で述べたように、VC フォーマットに関する多くの課題があります。しかし、VC フォーマットに期待される本質的機能は次のものに要約できると我々は考えています。

1. **検証可能性**
2. **キーバインディング**
3. **選択的開示**

次の節では、これらの要求事項を満たすことのできる SD-JWT に基づく VC フォーマットについて説明します。

#### 2.7.3. SD-JWT VC

SD-JWT は汎用的なデータフォーマットで、それ自体は VC フォーマットではありません。しかし、特定の要求事項を追加することにより、SD-JWT に基づく VC フォーマット定義することは可能です。**[SD-JWT-based Verifiable Credentials][SD_JWT_VC]** (**SD-JWT VC**) はそのような目的で作られた仕様です。

SD-JWT の概要については既に見てきたので、ここでは SD-JWT VC のポイントを下表に簡潔に紹介するにとどめます。詳細については SD-JWT VC 仕様を参照してください。

\| メディアタイプ | application/vc+sd-jwt |
\| クレデンシャルイシュアが署名する JWT | 場所 | 名前 | 要否 | 説明 |
\| ヘッダ | alg | 必須 | JWT 仕様 ([RFC 7519](https://www.rfc-editor.org/rfc/rfc7519.html)) で要求されている通り。 |
\| typ | 必須 | vc+sd-jwt |
\| ペイロード | iss | 必須 | クレデンシャルイシュアの識別子。 |
\| iat | 必須 | 発行日時 |
\| nbf | 任意 | VC 無効期間終了日時 (VC 有効期間開始日時) |
\| exp | 任意 | 有効期限終了日時 |
\| cnf | 条件により必須 | 暗号的キーバインディングが要請されていれば必須。
公開鍵を表す "jwk" プロパティを含むべき。
(参照: [RFC 7800](https://www.rfc-editor.org/rfc/rfc7800.html)) |
\| vct | 必須 | VC 種別を示す識別子。 |
\| status | 任意 | VC の状態確認方法に関する情報。 |
\| sub | 任意 | VC のサブジェクトの識別子。 |
\| キーバインディング JWT | 場所 | 名前 | 要否 | 説明 |
\| ヘッダ | alg | 必須 | JWT 仕様 ([RFC 7519](https://www.rfc-editor.org/rfc/rfc7519.html)) で要求されている通り。 |
\| 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 フォーマットについて見てきたので、アクセストークン用のクレデンシャル情報の議題に戻ることができます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_8.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=91343ecb228f02814c8444a84e4e11f2" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_8.png" />

#### 2.8.1. RAR オブジェクト内のクレデンシャル情報

RAR オブジェクトのタイプが `openid_credential` の場合、その RAR
オブジェクトは発行可能クレデンシャルに関する情報を含んでいます。

そのような RAR オブジェクトは必ず `credential_configuration_id`
プロパティまたは `format` プロパティを含んでいなければなりません。
この二つのプロパティは相互排他の関係にあります。

##### 2.8.1.1. `credential_configuration_id` プロパティを含む RAR オブジェクト

`credential_configuration_id`
プロパティの値は、クレデンシャルイシュアメタデータ内のクレデンシャル設定を参照します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/issuable_credential_05.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=8b6f1d53a146131ae2f51511d1df22cb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/issuable_credential_05.png" />

仕様書では明示的に説明されていないものの、仕様書内の例から、
`credential_configuration_id` プロパティが参照するクレデンシャル設定は、
発行可能クレデンシャルを構築するためのベースとしてのみ使われるということが推察されます。
別の言い方をすると、クレデンシャルオファー内で参照されるクレデンシャル設定とは異なり、RAR
オブジェクト内で参照されるクレデンシャル設定は、クレデンシャルフォーマット (及び他の必須プロパティ;
`vc+sd-jwt` フォーマットの場合における `vct` や `mso_mdoc` フォーマットの場合における `doctype` など)
の情報を取得するためだけに利用されるということです。結果として、RAR
オブジェクトにはウォレットが入手したいクレーム群が列挙されることが想定されます。

クレーム群を列挙する方法は、クレデンシャルのフォーマットによって異なります。例えば、仕様書内の例によれば、
`jwt_vc_json` フォーマットではクレーム群を列挙するのに `credential_definition`
プロパティを用います。

```json theme={null}
{
  "type": "openid_credential",
  "credential_configuration_id": "UniversityDegreeCredential",
  "credential_definition": {
    "credentialSubject": {
      "given_name": {},
      "family_name": {},
      "degree": {}
    }
  }
}
```

一方、`mso_mdoc` フォーマットは `claims` プロパティを用います。

```json theme={null}
{
  "type": "openid_credential",
  "credential_configuration_id": "org.iso.18013.5.1.mDL",
  "claims": {
    "org.iso.18013.5.1": {
      "given_name": {},
      "family_name": {},
      "birth_date": {}
    },
    "org.iso.18013.5.1.aamva": {
      "organ_donor": {}
    }
  }
}
```

##### 2.8.1.2. `format` プロパティを含む RAR オブジェクト

`credential_configuration_id` プロパティの代わりに `format` プロパティを使う場合、
RAR オブジェクトは発行可能クレデンシャルに関する完全な情報を含まなければなりません。

下記の例では VC フォーマットとして `mso_mdoc` が指定されています。このフォーマットでは
`doctype` プロパティが必須なので、結果として `doctype` プロパティも含まれています。

```json theme={null}
{
  "type": "openid_credential",
  "format": "mso_mdoc",
  "doctype": "org.iso.18013.5.1.mDL",
  "claims": {
    "org.iso.18013.5.1": {
      "given_name": {},
      "family_name": {},
      "birth_date": {}
    },
    "org.iso.18013.5.1.aamva": {
      "organ_donor": {}
    }
  }
}
```

#### 2.8.2. クレデンシャル設定内のクレデンシャル情報

クレデンシャル設定の情報は『**<ruby>Credential Issuer Metadata <rp>(</rp><rt>クレデンシャル イシュア メタデータ</rt><rp>)</rp></ruby>**』(**クレデンシャルイシュアメタデータ**) の一部として記述されます。

メタデータは JSON オブジェクトで、`credentials_configurations_supported`
JSON オブジェクトを含んでいます。そのオブジェクト内のエントリは、クレデンシャルイシュアがサポートする
VC のクレデンシャル設定を表しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_configuration.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f8374d1ad8d5eadcc6d58b83188c4bb8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_configuration.png" />

クレデンシャル設定オブジェクト内のプロパティ群は、
(1) 全てのクレデンシャル設定オブジェクトに共通して現れるものと
(2) それぞれのフォーマットに固有のものとに分かれます。
例えば、`format` プロパティは全ての対応クレデンシャルオブジェクトに含まれていますが、`claims`
プロパティは幾つかのフォーマットの場合のみ存在します。

### 2.9. クレデンシャル発行の詳細

これまでの説明でアクセストークン発行の詳細を見てきました。次はクレデンシャル発行の詳細について見ていきます。

#### 2.9.1. 鍵証明

『クレデンシャル検証』の節で説明したとおり、キーバインディング可能な VC を取得したいのであれば、ウォレットは鍵証明を提供することになります。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/credential_verification_13.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=65db308817fdbbc5b1548331aa8e9a81" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_verification_13.png" />

OID4VCI 仕様では、鍵証明のために三つの具体的なフォーマットが定義されています。
それらのフォーマットはそれぞれ、JWT ([RFC 7519][RFC_7519])、CWT ([RFC 8392][RFC_8392])
及び Data Integrity ([Data Integrity][W3C_DATA_INTEGRITY]) に基づいています。
将来必要になった際には、鍵証明フォーマットが追加されることもありえます。

##### 2.9.1.1. 鍵証明 JWT

定義により、鍵証明は公開鍵またはその鍵への参照を含んでいます。JWT に基づく鍵証明の場合、鍵情報を含めるために次に挙げる複数の方法を利用できます。鍵証明 JWT は、これらのうちの一つだけを使わなければなりません。

1. `jwk` ヘッダパラメーター ([RFC 7515, 4.1.3][RFC_7515_4_1_3])
2. `x5c` ヘッダパラメーター ([RFC 7515, 4.1.6][RFC_7515_4_1_6])
3. `kid` ヘッダパラメーター ([RFC 7515, 4.1.4][RFC_7515_4_1_4])

<Note>
  OID4VCI 仕様の現在のドラフトは、`kid` ヘッダパラメーターと `trust_chain` ヘッダパラメーターを組み合わせてキーバインディング用の公開鍵を指定できるかのような印象を与えるかもしれません。しかし、補助的な規則や仕組みが導入されない限り、その組み合わせは機能しません。
</Note>

これらの方法はいずれも、鍵証明 JWT のヘッダに鍵情報を埋め込みます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_1.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=10f9b5c4246fa2230d22e86e8ad7e4d8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_1.png" />

`jwk` ヘッダパラメーターを使用する場合、公開鍵は **JWK** ([RFC 7517 JSON Web Key (JWK)][RFC_7517]) 形式で埋め込まれます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_2.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=a7559cd8c889a5a2e91a64260848172e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_2.png" />

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

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_3.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=3910e54486fe0d97bd9f8f3720eb32ed" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_3.png" />

鍵証明 JWT 自身は、その公開鍵に対応する秘密鍵で署名されなければなりません。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_4.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=745edc5d447d8fa87ae210f403d80e9a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_4.png" />

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

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_5.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=b79b440fe9250bebbd850842312834e1" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_5.png" />

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

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_6.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=87c3eae02f3c4bb21afc84eb9e9b29de" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_6.png" />

次に、鍵証明 JWT のペイロード部を見ていきましょう。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_7.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=96da2e777cddeb7a27be9bdef8bc00b9" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_7.png" />

次の表は鍵証明 JWT のペイロード部のクレーム群を列挙しています。

\| 名前 | 要否 | 説明 |
\| iss | 条件により必須 | クライアントアプリケーション (ウォレット) の識別子。 |
\| aud | 必須 | クレデンシャルイシュアの識別子。 |
\| iat | 必須 | 発行日時 |
\| nonce | 条件により必須 | サーバが提供した c\_nonce。 |

* `iss` クレームはクライアントアプリケーション (ウォレット) の識別子を表しており、ほとんどの場合は必須です。唯一の例外は、アクセストークンが事前認可コードフローで発行され、そのアクセストークン用のトークンリクエストがクライアントアプリケーションを特定する情報を含んでいない場合です。そのようなトークンリクエストは、サーバが事前認可コードフローにおいて匿名アクセスを許可している場合に受け入れられます。この機能を認可サーバがサポートしているかどうかは、真偽値サーバメタデータである `pre-authorized_grant_anonymous_access_supported` により示されます。

* `aud` クレームはクレデンシャルイシュアの識別子を表しており、常に必須です。

* `iat` クレームは鍵証明 JWT の発行日時を表しており、詳細な定義は [RFC 7519, 4.1.6. "iat" (Issued At) Claim][RFC_7519_4_1_6] にあります。

* `nonce` クレームは、トークンレスポンスまたはクレデンシャルレスポンスに含まれる `c_nonce` に対応します。トークンレスポンスが `c_nonce` パラメーターを含んでいる場合、`nonce` クレームは必須です。また、トークンレスポンスが `c_nonce` パラメーターを含んでいない場合でも、クレデンシャルイシュアは `nonce` クレームを要求するかもしれません。`c_nonce` の詳細は後ほど説明します。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_proof_jwt_8.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=138017c84a416842a7971b16177ac171" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_proof_jwt_8.png" />

次の表は鍵証明 JWT に対する要求事項の要約です。

\| 鍵証明 JWT | 場所 | 名前 | 要否 | 説明 |
\| ヘッダ | alg | 必須 | JWT 仕様 ([RFC 7519](https://www.rfc-editor.org/rfc/rfc7519.html)) で要求されている通り。 |
\| typ | 必須 | openid4vci-proof+jwt |
\| jwk | 条件により必須 | これらのヘッダパラメーター群のどれか一つを含めなければなりません。
公開鍵、または公開鍵への参照を表しています。 |
\| x5c |
\| kid |
\| ペイロード | iss | 条件により必須 | クライアントアプリケーション (ウォレット) の識別子。 |
\| aud | 必須 | クレデンシャルイシュアの識別子。 |
\| iat | 必須 | 発行日時 |
\| nonce | 条件により必須 | サーバが提供した c\_nonce。 |

下記は鍵証明 JWT の例です。

```text theme={null}

eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJraWQiOiJHVURvZFB1SURJYllocmdmMHZsT3RNd1otczNiaVpFT3hWMFRTRjBKN3R3IiwieCI6InJjdU1FT1BYbVBJRlotc0Jvbkxyb1VvaTVYdGZ4NktWeFlFR09YMi1UbGsiLCJ5IjoiNUw1SUZrUFpNT0doTVpsNHRaSk9ISjdtckZQbnJSeV9RSURUOXRWZF9obyIsImFsZyI6IkVTMjU2In19.eyJpc3MiOiJodHRwczovL3dhbGxldC5leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHBzOi8vaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNjk3MjM0NzcwLCJub25jZSI6IjZhMzA3YjU1LWM4ZTEtNDg4YS05NjFlLTI1MzQ4ZmYzZTlkYSJ9.Vvo_X_fZyanUZ-y5X0yYtY7d70bbjMKUKqAoDiCBmP3NT4xNfTEpuYl9eu7vxc2fLf67ZdbSfw4rwEp8qvvWpA
```

鍵証明 JWT の例のヘッダとペイロードをデコードすると、それぞれ次の JSON になります。

```json theme={null}
{
  "alg": "ES256",
  "typ": "openid4vci-proof+jwt",
  "jwk": {
    "kty": "EC",
    "alg": "ES256",
    "crv": "P-256",
    "x":   "rcuMEOPXmPIFZ-sBonLroUoi5Xtfx6KVxYEGOX2-Tlk",
    "y":   "5L5IFkPZMOGhMZl4tZJOHJ7mrFPnrRy_QIDT9tVd_ho",
    "kid": "GUDodPuIDIbYhrgf0vlOtMwZ-s3biZEOxV0TSF0J7tw"
  }
}
```

```json theme={null}
{
  "iss": "https://wallet.example.com",
  "aud": "https://issuer.example.com",
  "iat": 1697234770,
  "nonce": "6a307b55-c8e1-488a-961e-25348ff3e9da"
}
```

##### 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` の有効期間の秒数を表しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=02fce492842eed4329d62752d860178f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce_1.png" />

ウォレットは、その `c_nonce` レスポンスパラメーターの値を鍵証明 JWT の `nonce` の値として使用します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=299ae14b16d33e75905ba22280397416" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce_2.png" />

ウォレットはその鍵証明 JWT をクレデンシャルリクエストに含めます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=b881a55202290d2847f45a7aca6c6b90" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce_3.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=730b92a1136dcdccd74983823a3ddcc9" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce_4.png" />

必要に応じ、ウォレットはクレデンシャルエンドポイントから提供された `c_nonce` を用いて新しい鍵証明を再生成し、その新しい鍵証明を添えて再度クレデンシャルリクエストを実行できます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce_5.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=62c1443c856ba0f3a1cc9cbed625636f" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce_5.png" />

次の図は `c_nonce` の概要を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/c_nonce.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=784665d3c1fd454c577fb70ea3b70945" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/c_nonce.png" />

#### 2.9.3. クレデンシャルリクエスト

クレデンシャルリクエストは、アクセストークンと JSON 形式のペイロードを含む HTTP POST リクエストです。ペイロードにはクレデンシャル情報および任意の鍵証明が含まれます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_request_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=001d9abee26fe1b6145d83ca027c202e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_request_1.png" />

<Note>
  クレデンシャルレスポンスの暗号化のために `credential_response_encryption`
  プロパティが含まれることもありますが、ここでは取り上げません。
</Note>

##### 2.9.3.1. クレデンシャルリクエスト内のクレデンシャル情報

クレデンシャルリクエスト内のクレデンシャル情報は、必須の `"format"` プロパティと、フォーマット固有のプロパティを含んでいます。例えば、`"format"` プロパティの値が `"jwt_vc_json"` であれば、`"credential_definition"` プロパティがあるものと期待されます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_request_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=74c4d16c6bb4c7d44bff6c095b7f2966" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_request_2.png" />

クレデンシャル情報は、ウォレットが入手したい VC について記述したものです。OID4VCI 仕様から抜粋した上記の図内の例で示唆されているように、クレデンシャルリクエスト内のクレデンシャル情報は、アクセストークンに紐付いている発行可能クレデンシャルを指定する以上のことをおこなっています。例えば、クレデンシャルリクエストの例の意図は、`given_name` クレーム、`family_name` クレーム、`degree` クレームのみを含む `jwt_vc_json` フォーマットの VC を要求するというものです。

しかし、幾つかの問題があります。

1. 指定された条件を満たす発行可能クレデンシャルを決めるのは簡単ではない。

2. 複数の発行可能クレデンシャルが条件を満たす可能性がある。

3. 条件のわずかな違いで、異なる発行可能クレデンシャルが選ばれる可能性がある。

4. 提示されたアクセストークンが指定された条件を満たす VC を要求する権限を持っているか確認するのは簡単ではない。

簡単に言うと、この仕様は実装に対する配慮が欠けています。
[Issue 175](https://github.com/openid/OpenID4VCI/issues/175) で報告されている問題は、
この仕様の欠陥により引き起こされる問題の一例です。
ですので、仕様が改善されない限り、「**クレデンシャルイシュアは、 実行時に
（アクセストークンリクエストやクレデンシャルリクエストで） 指定される詳細条件を無視し、構造が固定された
VC を発行する**」というものになる可能性が高いです。

<Note>
  OID4VCI 仕様は最近、`format` パラメーターと相互排他の関係となる
  `credential_identifier` パラメーターを導入しました。
  しかし、そのクレデンシャルインスタンス識別子は (クレデンシャルイシュアがサポートしていれば)
  `openid_credential` タイプの RAR オブジェクトが使われたときのみ利用可能で、
  また、仕様は、クレデンシャルインスタンス識別子は `scope`
  パラメーターが使われたときは利用できないと述べています。`credential_identifier`
  は限定的なユースケースに対して設計された解決法に過ぎず、上述した問題の解にはなりません。
  [Issue 197](https://github.com/openid/OpenID4VCI/issues/197)
  の議論も参照してください。
</Note>

##### 2.9.3.2. クレデンシャルリクエスト内の鍵証明情報

クレデンシャルリクエスト内の鍵証明情報は `"proof"` プロパティにより表されます。プロパティの値は JSON オブジェクトです。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_request_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=5f23deb0c7713b41df821d7299b4ab7e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_request_3.png" />

`"proof"` オブジェクトには、鍵証明のフォーマットを示す `"proof_type"` プロパティが必ず含まれます。

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_request_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=c148acb884a990879940b932290d2042" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_request_4.png" />

次の図はクレデンシャルリクエストの概要を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_request.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=a53868aa44d9c01074866d90a40e65f4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_request.png" />

#### 2.9.4. クレデンシャルレスポンス

クレデンシャルレスポンスは JSON を含む HTTP レスポンスです。

##### 2.9.4.1. VC を含むクレデンシャルレスポンス

VC の発行に成功した場合、VC は `"credential"` プロパティの値として JSON に含まれます。`"credential"` プロパティの値のフォーマットは、VC のフォーマットに依存します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f11c337cec01b5e4e6cb276cbbb25fe8" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_1.png" />

例えば、[SD-JWT VC][SD_JWT_VC] に準拠する SD-JWT ベースの VC であれば、`"credential"` プロパティの値は SD-JWT フォーマットの JSON 文字列です。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=6611b1a587c2138fd1f4e1cb0a2e7e34" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_2.png" />

加えて、先に説明したように、クレデンシャルレスポンスには `c_nonce` レスポンスパラメーターと
`c_nonce_expires_in` レスポンスパラメーターが含まれることがあります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=1cc525c91fc25c52c502706b7291b450" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_3.png" />

ここで SD-JWT ベースの VC の詳細について見ていきましょう。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=cd2d939d4e857bc023ad0d76bea2eef2" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_4.png" />

SD-JWT は、クレデンシャルイシュアが署名した JWT と、0 個以上のディスクロージャ、そして、任意のキーバインディング JWT で構成されます。これらの構成要素は、チルダ (`~`) を区切り文字として連結されています。なお、キーバインディング JWT はウォレットが生成するので、クレデンシャルイシュアが発行したときには VC はキーバインディング JWT を含んでいないので注意してください。

```
<クレデンシャルイシュアが署名したJWT>~<ディスクロージャ1>...<ディスクロージャN>~
```

SD-JWT の最初の構成要素はクレデンシャルイシュアが署名した JWT です。標準 JWT として、クレデンシャルイシュアが署名した JWT のヘッダとペイロードは base64url でデコードできます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_5.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=8fcbe191f7ab4002061cc491b564a330" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_5.png" />

ここで重要な点は次の通りです。

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

SD-JWT ベースの VC の例には、四つのディスクロージャが含まれています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_6.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=6059db1a12a314f043f849a06637f174" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_6.png" />

ディスクロージャを base64url でデコードすることにより、元の JSON 配列が得られます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_7.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=875da5c3c76ef989f43fc191673eed88" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_7.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response_8.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=c78074711867a13cfc71fbbaf8c07ec6" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response_8.png" />

次の図は、SD-JWT ベースの VC を含むクレデンシャルレスポンスの概要を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_response.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=b951432d9c6c52e2aa82c33f14e27224" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_response.png" />

##### 2.9.4.2. トランザクション ID を含むクレデンシャルレスポンス

要求された VC が用意できていない場合、クレデンシャルエンドポイントは VC の代わりにトランザクション ID を返します。トランザクション ID は `"transaction_id"` レスポンスパラメーターの値としてクレデンシャルレスポンスに含まれます。次のものは OID4VCI 仕様から抜粋した例です。

```http theme={null}
HTTP/1.1 202 Accepted
Content-Type: application/json
Cache-Control: no-store

{
  "transaction_id": "8xLOxBtZp8",
  "c_nonce": "wlbQc6pCJp",
  "c_nonce_expires_in": 86400
}
```

トランザクション ID は、後ほどウォレットがクレデンシャルイシュアの遅延クレデンシャルエンドポイントに遅延クレデンシャルリクエストを送る際に使用されます。

##### 2.9.4.3. エラーを含むクレデンシャルレスポンス

クレデンシャルリクエストを成功裡に処理できない場合、クレデンシャルエンドポイントはエラー応答を返します。エラーの種別は `"error"` レスポンスパラメーターで示されます。次のものは仕様から抜粋したエラーの例です。

```http theme={null}
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
   "error": "invalid_request"
}
```

必要な鍵証明が含まれていなかったり、`nonce` クレームの欠落や期限切れなどの理由により鍵証明が正しくない場合、エラーコード `"invalid_proof"` が使われます。そのような場合のエラー応答の例を仕様から転載します。

```http theme={null}
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
  "error": "invalid_proof",
  "error_description":
    "Credential Issuer requires key proof to be bound to a Credential Issuer provided nonce.",
  "c_nonce": "8YE9hCnyV2",
  "c_nonce_expires_in": 86400
}
```

#### 2.9.5. 遅延クレデンシャルリクエスト

ウォレットは、トランザクション ID を使い遅延クレデンシャルエンドポイントにリクエストを送ることができます。このリクエストは JSON を含む HTTP POST リクエストで、その JSON 内の `"transaction_id"` プロパティがトランザクション ID の値を保持しています。

```http theme={null}
POST /deferred_credential HTTP/1.1
Host: issuer.example.com
Content-Type: application/json
Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW

{
   "transaction_id": "8xLOxBtZp8"
}
```

#### 2.9.6. 遅延クレデンシャルレスポンス

遅延クレデンシャルエンドポイントは JSON を含む HTTP レスポンスを返します。
VC が成功裡に発行されていれば、その JSON は `"credential"` プロパティを含みます。
このプロパティの値が発行された VC です。

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "credential": "eyJ......CJd~"
}
```

発行がうまくいかない場合、`"error"` パラメーターを含むエラー応答が返されます。特に、要求された VC がまだ用意できていない場合はエラーコード `"issuance_pending"` が使われます。

```http theme={null}
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
   "error": "issuance_pending"
}
```

#### 2.9.7. 一括クレデンシャルリクエスト

クレデンシャルイシュアの一括クレデンシャルエンドポイントに一括クレデンシャルリクエストを送ることで、ウォレットは一度に複数の VC を要求することができます。

一括クレデンシャルリクエストは JSON を含む HTTP POST リクエストで、`"credential_requests"` JSON 配列を含んでいます。配列は JSON オブジェクトのリストで、一つ一つがクレデンシャルリクエストを表しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_request_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=a7318efc588c18d202c4756dc556ceeb" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_request_1.png" />

各クレデンシャルリクエストはクレデンシャル情報と任意の鍵証明を含んでいます。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_request_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=a1f13dbdb34e5bf9868e3d987d4c9868" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_request_2.png" />

一括クレデンシャルリクエスト内のクレデンシャルリクエスト群が異なるクレデンシャルフォーマット、異なる鍵証明を持つことは許されています。逆もまた真です。クレデンシャルリクエスト群は同じクレデンシャルフォーマット、同じ鍵証明を持っていてもかまいません。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_request_3.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=e827d8e7deb766d7475d04c16a57d7c6" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_request_3.png" />

次の図は一括クレデンシャルリクエストの概要を示しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_request.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=f7f159808ac8e0221cd4cdc6cbac1df4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_request.png" />

#### 2.9.8. 一括クレデンシャルレスポンス

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

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_response_1.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=fbb5cb21659e0b91c8ec839847e6102a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_response_1.png" />

各クレデンシャルレスポンスは VC またはトランザクション ID を含んでいます。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_response_2.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=ffe87287e5e064875ad0addefe291684" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_response_2.png" />

加えて、将来ウォレットが鍵証明付きのクレデンシャルリクエストまたは一括クレデンシャルリクエストを送るときのため、一括クレデンシャルレスポンスは
`c_nonce` と `c_nonce_expires_in` をトップレベルプロパティとして含んでいるかもしれません。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_response_3.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=9ae3bbae106ed3d4f40330be3e1446b1" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_response_3.png" />

次の図は一括クレデンシャルレスポンスの概要を示しています。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/batch_credential_response.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=cb32393c461f4d60e66619fffdbf35fc" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/batch_credential_response.png" />

### 2.10. 公開鍵配布

VC や VP の署名を検証するため、ベリファイアはクレデンシャルイシュアが VC に署名する際に使った秘密鍵に対応する公開鍵を取得する必要があります。

VC の署名を検証するための公開鍵を配布する方法は OIDC4VCI 仕様の範囲外の事項です。しかし、ここで幾つか提案されている手法について見ていきましょう。

#### 2.10.1. X.509 証明書の埋め込み

公開鍵配布の一つの方法として、VC 内に公開鍵用の X.509 証明書を埋め込む方法があります。

JWT ベースの VC の場合、その目的のために `"x5c"` ヘッダパラメーター ([RFC 7515, 4.1.6][RFC_7515_4_1_6]) が使われることになるでしょう。

#### 2.10.2. エンティティコンフィギュレーションに埋め込み

[OpenID Federation][OIDFED] 仕様を活用する方法では、クレデンシャルイシュアのエンティティコンフィギュレーションに公開鍵を埋め込みます。

イタリアのエコシステムでは、クレデンシャルイシュアを表す新しいエンティティタイプ識別子として `openid_credential_issuer` を定義し、その `"jwks"` メタデータをクレデンシャルイシュアの公開鍵を置く場所として使っています。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_distribution_oidfed.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=fd3ee117366f2212e73ec80e87f63ac7" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_distribution_oidfed.png" />

<Note>
  この文書を書いている時点では、`"jwks"`、`"jwks_uri"`、`"signed_jwks_uri"` はまだクレデンシャルイシュアのメタデータとして定義されていません。
</Note>

#### 2.10.3. jwt-vc-issuer

`/.well-known/jwt-vc-issuer` も公開鍵配布方法として提案されています。
このウェルノーンパスは、公開鍵を探す開始点となることを意図しています。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/key_distribution_jwt_vc_issuer.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=3a3cfd4cca9d840402e6d74038fc7db0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/key_distribution_jwt_vc_issuer.png" />

このウェルノーンパスは、JWT VC 発行者のメタデータを含む JSON を返します。
JSON 内の `"jwks_uri"` プロパティが、発行者の JWK Set の場所を示しています。
ベリファイアはその JWK Set 内に目当ての公開鍵を見つけることができるでしょう。

<Note>
  JWT VC 発行者のメタデータは `"jwks_uri"` ではなく `"jwks"` を含んでいるかもしれません。
  何らかの理由により JWT VC 発行者が JWK Set 用の独立したエンドポイントを提供できない場合に、このようなことが起こります。
</Note>

### 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][ISO_IEC_18013_5]) です。
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 はフロントエンドサーバ群の後ろに配置され、エンドユーザからは見えません。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/oid4vci_parties_and_authlete.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=6ed6e65ed7ba9ef08a4efea5240433e5" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/oid4vci_parties_and_authlete.png" />

Authlete のアーキテクチャは必然的に開発者にフロントエンドサーバの作成を要求しますが、その代わりに開発者は以下の利点を得られます。

1. **任意の技術コンポーネントを開発者が選べる**
   * ユーザ認証方法
   * ユーザ管理システム
   * API ゲートウェイ
   * プログラミング言語
   * Web フレームワーク
   * クラウドサービス
2. **ユーザデータに対する完全な制御**
   * ユーザデータを OAuth/OIDC ベンダーのサーバにアップロードする必要はありません。
   * ユーザデータの保護に関するさまざまな規制への対応。
3. **エンドユーザ向けフロントエンドサーバに対する完全な制御**
   * UI/UX のすべての側面にわたる企業ブランドの管理。
4. **システム設計における適切なレイヤ分離の強制**
   * API 認可がユーザ管理・ユーザ認証から分離される。
   * OAuth/OIDC プロトコル処理が API ゲートウェイやフロントエンドサーバから分離される。

<Note>
  企業のアーキテクトは、ビジネスの成功のためにユーザのアイデンティティ管理とサービスの Web API の完全な制御が必要であることを認識するようになり、Authlete が提供する『OAuth/OIDC component as a Service』アプローチがその解決策であることに気付き始めました。EIC 2023 で行われたこのトピックに関するパネルディスカッション『**[Security Offered as Components Empowering Enterprises to Gain Control](https://www.youtube.com/watch?v=hK7ORyfTpvI)**』を是非ご視聴ください。
</Note>

### 3.2. Authlete 設定

#### 3.2.1. Authlete バージョン

OID4VCI 仕様は、2024 年 4 月頃リリース予定の Authlete 3.0 からサポートされます。

それまでの間、お客様とビジネスパートナー向けにトライアルサーバが利用可能です。OID4VCI の試験利用にご興味のある方は[お問い合わせ][CONTACT_US]ください。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authlete_release_history_up_to_3_0.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=45a54eb54b8217c7d123f8d79f6da7a7" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authlete_release_history_up_to_3_0.png" />

#### 3.2.2. Authlete サーバ設定

Authlete サーバで『**Verifiable Credentials**』機能を有効にしておく必要があります。オンプレミス版の
Authlete を利用されている場合は、この機能を有効にするために設定ファイル
(`authlete-server.properties`) 内に次の行が含まれていることを確認してください。

```java-properties theme={null}
feature.verifiable_credentials.enabled=true
```

#### 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](https://authlete.github.io/authlete-java-common/com/authlete/common/types/JWEAlg.html) 列挙型の値です。非対称鍵系アルゴリズムのみ指定可能です。 |
\| credentialResponseEncryptionEncValuesSupported | 文字列の配列 | クレデンシャルレスポンス暗号化においてサポートされる JWE enc アルゴリズム群。
このプロパティは OID4VCI 仕様で定義されている
credential\_response\_encryption.enc\_values\_supported
メタデータに対応します。

有効な値は、"A256GCM" 等、
[JWEEnc](https://authlete.github.io/authlete-java-common/com/authlete/common/types/JWEEnc.html) 列挙型の値です。 |
\| 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 の詳細については以降の節で説明します。

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/compliance-profiles/authlete_apis_for_oid4vci.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=5c768704b66d7db062ad69abe1cde679" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/authlete_apis_for_oid4vci.png" />

#### 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 シークレット       | アクセストークン     |
| ウェブコンソール | サービスオーナーコンソールとデベロッパーコンソール | 単一のコンソール     |

Authlete API のパス部分にも違いがあります。Authlete 3.0 では、ほとんどの Authlete 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` |

<Note>
  他の文書と同様に、この文書では API パスのプレフィックス『`/api/{サービスID}`』を省略します。
</Note>

これらの変更は小さくないですが、差異をライブラリレイヤで吸収することにより、プログラムへの影響は最小化できます。
例えば、Java で書かれたサンプル認可サーバ ([authlete/java-oauth-server][JAVA_OAUTH_SERVER])
を使っていて、Authlete 2.x から Authlete 3.0 へ移行する開発者は、設定ファイル
(`authlete.properties`) の内容を

```java-properties theme={null}
# Authlete 2.x 用
base_url = ...
service.api_key = ..
service.api_secret = ...
```

から

```java-properties theme={null}
# Authlete 3.0 用
api_version = V3
base_url = ...
service.api_key = ...
service.access_token = ...
```

に変更するだけで済みます。

### 3.4. クレデンシャルオファー発行

既に述べたように、クレデンシャルオファー発行処理はクレデンシャルイシュアによって異なります。

例えば、Webブラウザ経由でユーザとやりとりした後、クレデンシャルイシュアは次のような
QR コードを発行するかもしれません。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_qr.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=0f0e0460c353fb787ea251e74f83114d" alt="" width="300" height="300" data-path="protocols-and-flows/compliance-profiles/credential_offer_qr.png" />

この QR コードは "`openid-credential-offer://?credential_offer={CredentialOffer}`"
を表していて、*`{CredentialOffer}`* の部分が下記のクレデンシャルオファーを保持しています。

```json theme={null}
{
  "credential_issuer": "https://trial.authlete.net",
  "credential_configuration_ids": [
    "IdentityCredential",
    "org.iso.18013.5.1.mDL"
  ],
  "grants": {
    "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
      "pre-authorized_code": "NH9udMon5pTuuvbsNsHUNWf8tpU__9wt-gsO9LeYthc"
    }
  }
}
```

代わりにクレデンシャルオファーは次のようなハイパーリンクを表示するかもしれません。

* `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 | クレデンシャルオファーを発行する過程で行われたユーザ認証の認証コンテキストクラス参照。 |

例えば、次のコマンドラインでクレデンシャルオファーが生成されます。

```shell theme={null}
$ BASE_URL=https://nextdev-api.authlete.net
$ SERVICE_ID=986126671
$ ACCESS_TOKEN=YOUR_ACCESS_TOKEN
$ curl -s $BASE_URL/api/$SERVICE_ID/vci/offer/create \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"credentialConfigurationIds":["IdentityCredential"],"preAuthorizedCodeGrantIncluded":true,"txCode":"123456","txCodeInputMode":"numeric","subject":"1001"}'
```

`/vci/offer/create` API は次のような JSON を返します。

```json theme={null}
{
  "type": "credentialOfferCreateResponse",
  "resultCode": "A366001",
  "resultMessage": "[A366001] A credential offer was created successfully.",
  "action": "CREATED",
  "info": {
    "authTime": 0,
    "authorizationCodeGrantIncluded": false,
    "credentialConfigurations": [
      "IdentityCredential"
    ],
    "credentialIssuer": "https://trial.authlete.net",
    "credentialOffer": "{\"credential_issuer\":\"https://trial.authlete.net\",\"credential_configuration_ids\":[\"IdentityCredential\"],\"grants\":{\"urn:ietf:params:oauth:grant-type:pre-authorized_code\":{\"pre-authorized_code\":\"rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk\",\"tx_code\":{\"length\":6,\"input_mode\":\"numeric\"}}}}",
    "expiresAt": 1703929674224,
    "identifier": "9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc",
    "issuerStateIncluded": false,
    "preAuthorizedCode": "rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk",
    "preAuthorizedCodeGrantIncluded": true,
    "subject": "1001",
    "txCode": "123456",
    "txCodeInputMode": "numeric"
  }
}
```

API レスポンス内の `"info"` オブジェクトが生成されたクレデンシャルオファーの情報を含んでいます。
`"info"` オブジェクト内の `"credentialOffer"` プロパティが生成されたクレデンシャルオファーです。
上記例中の `"credentialOffer"` プロパティを読みやすく整形すると次のようになります。

```json theme={null}
{
  "credential_issuer": "https://trial.authlete.net",
  "credential_configuration_ids": [
    "IdentityCredential"
  ],
  "grants": {
    "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
      "pre-authorized_code": "rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk",
      "tx_code": {
        "length": 6,
        "input_mode": "numeric"
      }
    }
  }
}
```

`"credentialOffer"` プロパティの値があれば、次の要素を連結することで
URL を構築できます。

1. クレデンシャルオファーエンドポイント。`openid-credential-offer://` など。
2. `?credential_offer=`
3. URL エンコードした `"credentialOffer"` の値

```text theme={null}

openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Ftrial.authlete.net%22%2C%22credential_configuration_ids%22%3A%5B%22IdentityCredential%22%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk%22%2C%22tx_code%22%3A%7B%22length%22%3A6%2C%22input_mode%22%3A%22numeric%22%7D%7D%7D%7D
```

`/vci/offer/create` API へのリクエストとそのレスポンスは、それぞれ
[authlete-java-common][AUTHLETE_JAVA_COMMON] ライブライ内の
`CredentialOfferCreateRequest` Java クラスと
`CredentialOfferCreateResponse` Java クラスで表現されます。
詳細はライブラリの [JavaDoc][AUTHLETE_JAVA_COMMON_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/{identifier} のようにパスの末尾で指定されます。 |

識別子は `/vci/offer/create` API のレスポンスに含まれます。`"info"` オブジェクト内の
`"identifier"` プロパティの値が識別子です。前節の例では、その値は
`9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc`
となっています。

次のコマンドラインは、前節で作成されたクレデンシャルオファーの情報を問い合わせます。

```shell theme={null}
$ CREDENTIAL_OFFER_IDENTIFIER=9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc
$ curl -s ${BASE_URL}/api/${SERVICE_ID}/vci/offer/info/${CREDENTIAL_OFFER_IDENTIFIER} \
    -H "Authorization: Bearer ${ACCESS_TOKEN}"
```

`/vci/offer/info` API は次のような JSON を返します。
内容は `/vci/offer/create` API が返すものとほぼ同じです。

```json theme={null}
{
  "type": "credentialOfferInfoResponse",
  "resultCode": "A368001",
  "resultMessage": "[A368001] Information about the credential offer was obtained successfully.",
  "action": "OK",
  "info": {
    "authTime": 0,
    "authorizationCodeGrantIncluded": false,
    "credentialConfigurationIds": [
      "IdentityCredential"
    ],
    "credentialIssuer": "https://trial.authlete.net",
    "credentialOffer": "{\"credential_issuer\":\"https://trial.authlete.net\",\"credential_configuration_ids\":[\"IdentityCredential\"],\"grants\":{\"urn:ietf:params:oauth:grant-type:pre-authorized_code\":{\"pre-authorized_code\":\"rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk\",\"tx_code\":{\"length\":6,\"input_mode\":\"numeric\"}}}}",
    "expiresAt": 1703929674000,
    "identifier": "9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc",
    "issuerStateIncluded": false,
    "preAuthorizedCode": "rS8D7asTTL8MaXM5yLjQvaAMmPmierRW6oeK-4JP4Uk",
    "preAuthorizedCodeGrantIncluded": true,
    "subject": "1001",
    "txCode": "123456",
    "txCodeInputMode": "numeric"
  }
}
```

`/vci/offer/info` API の主目的は、ウォレットからの問い合わせに対してクレデンシャルオファーの情報を返すエンドポイントを、開発者がクレデンシャルイシュア上に実装するのを助けることです。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issuance_10.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=9ac332d8ad2f7f348ebfa6efe6418479" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_offer_issuance_10.png" />

そのようなエンドポイントがあれば、次の要素を連結することで URL を構築できます。

1. クレデンシャルオファーエンドポイント。`openid-credential-offer://` など。
2. `?credential_offer_uri=`
3. URL エンコードしたクレデンシャルオファーの識別子を含むエンドポイントの URL。例えば `https://trial.authlete.net/api/offer/9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc` など。

```text theme={null}


openid-credential-offer://?credential_offer_uri=https%3A%2F%2Ftrial.authlete.net%2Fapi%2Foffer%2F9gjVvas8Q5BkkrkSfZv-DbsBYJvlw6ZPMK-TeCkQDEc
```

#### 3.4.3. クレデンシャルオファー発行の例

Java で書かれたサンプル認可サーバの実装である [authlete/java-oauth-server][JAVA_OAUTH_SERVER]
はクレデンシャルイシュアとしても機能します。開発者が任意のクレデンシャルオファーを生成するための
HTML ページが `/api/offer/issue` エンドポイントにより提供されます。Authlete 3.0 を使う
java-oauth-server インスタンスが現在 [https://trial.authlete.net](https://trial.authlete.net) で稼働しており、試用を目的として
[https://trial.authlete.net/api/offer/issue](https://trial.authlete.net/api/offer/issue) エンドポイントを利用できます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issue_page.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=0b4a0cc0a8cd7fd022064a5871eb27b2" alt="" width="660" height="840" data-path="protocols-and-flows/compliance-profiles/credential_offer_issue_page.png" />

HTML ページではユーザ認証が要求されます。
java-oauth-server に埋め込まれているテストアカウントを使用できます。
ただし、mdoc フォーマットの VC を生成したい場合は `inga` を使用してください。

| サブジェクト | ログイン ID |  パスワード |
| :----: | :-----: | :----: |
|  1001  |  `john` | `john` |
|  1002  |  `jane` | `jane` |
|  1003  |  `max`  |  `max` |
|  1004  |  `inga` | `inga` |

### 3.5. クレデンシャルエンドポイント実装

下記の Authlete API を用いてクレデンシャルエンドポイントを実装することができます。

|    | Authlete API                       | 説明                                                            |
| :- | :--------------------------------- | :------------------------------------------------------------ |
| 1  | <nobr>`/auth/introspection`</nobr> | 提示されたアクセストークンの有効性を確認し、アクセストークンの情報を返します。                       |
| 2  | `/vci/single/parse`                | 受け取ったクレデンシャルリクエストを解析して有効性を確認し、クレデンシャルリクエストの情報を返します。           |
| 3  | `/vci/single/issue`                | Verifiable Credential またはトランザクション ID を発行し、クレデンシャルレスポンスを用意します。 |

クレデンシャルエンドポイント実装内の処理手順を見ていきましょう。

最初のステップとして、クレデンシャルエンドポイントの実装はウォレットからクレデンシャルリクエストを受け取ります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_01.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=f9b2712dfc91c1d806a451a0cd009ca1" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_01.png" />

クレデンシャルリクエストからアクセストークンを取り出し、Authlete の `/auth/introspection` API に渡します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_02.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=c6f25d12a36b01c067fd7c798cf948b0" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_02.png" />

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_03.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=25c9d2f3963db166f5d9dd1b04116bbf" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_03.png" />

アクセストークンが有効であれば、エンドポイントの実装はアクセストークンとクレデンシャルリクエストの本文を
`/vci/single/parse` API に送ります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_04.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=c8d595f6b96f4e58f42265f099c48fd4" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_04.png" />

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

`/vci/single/parse` API はクレデンシャルリクエストの解析と有効性確認をおこない、クレデンシャルリクエストの情報を返します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_05.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=929a1fb2bf6efa2205ecc967d4ef2297" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_05.png" />

エンドポイントの実装は、Authlete が VC を発行するのに必要な情報を含む『**クレデンシャル発行指示**』(Credential Issuance Order)
を準備します。この準備の詳細については後ほど議論します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_06.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ee9c5c6c96d3142da9667fd644849a13" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_06.png" />

エンドポイントの実装はクレデンシャル発行指示とアクセストークンを `/vci/single/issue` API に送ります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_07.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=087875429b004bf6f677234074809147" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_07.png" />

<Note>
  再び Authlete にアクセストークンを送る理由は、アクセストークンに紐付く `c_nonce`
  が期限切れした場合に値をリフレッシュする必要があるためです。
</Note>

クレデンシャル発行指示に従い、`/vci/single/issue` API は VC またはトランザクション ID
を発行し、クレデンシャルレスポンスの内容を用意します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_08.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=3dc27550187aa5a031e9baa792d81c5e" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_08.png" />

エンドポイントの実装は、ウォレットに返すクレデンシャルレスポンスを表す HTTP レスポンスを構築します。
`/vci/single/issue` API が用意したレスポンスの内容をクレデンシャルレスポンスのメッセージボディとして使用できます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_09.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=d3513c24ba42f68f62b9a70484a13995" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_09.png" />

最後に、クレデンシャルエンドポイントはクレデンシャルレスポンスをウォレットに返します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint_10.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=9e9d0a4647fcd46058e3f54c33064525" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint_10.png" />

次の図はクレデンシャルエンドポイントの実装内の処理手順を示しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_endpoint.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=cfa3abf96c81baff4bc3038c14502e07" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_endpoint.png" />

#### 3.5.1. クレデンシャル発行指示

クレデンシャル発行指示を用意する手順は次の通りです。

##### 3.5.1.1. クレデンシャル発行指示 ステップ 1

アクセストークン情報からアクセストークンに紐付くユーザのサブジェクト (= 一意識別子) を取得します。
`/auth/introspection` API のレスポンス ([IntrospectionResponse][IntrospectionResponse] 参照)
に含まれる `"subject"` プロパティがサブジェクトの値を保持しています。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_1.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=5e5e47366742bbd85dd8278224da6db5" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_1.png" />

##### 3.5.1.2. クレデンシャル発行指示 ステップ 2

サブジェクトで特定されるユーザの情報をユーザデータベースから取り出します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_2.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=d506798689af9a6df727a42915d2d97a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_2.png" />

##### 3.5.1.3. クレデンシャル発行指示 ステップ 3

アクセストークン情報からアクセストークンに紐付く発行可能クレデンシャルの情報を取得します。
`/auth/introspection` API のレスポンスに含まれる `"issuableCredentials"`
プロパティが情報を文字列として保持しています。この文字列は JSON 配列としてパースする必要があります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_3.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=fe44c2024b16b8cb594b231709a5863c" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_3.png" />

##### 3.5.1.4. クレデンシャル発行指示 ステップ 4

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

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_4.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=d0f693252cea69c6273e98f4da33a629" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_4.png" />

`"details"` プロパティの値は文字列です。この文字列は JSON オブジェクトとしてパースする必要があります。
その JSON オブジェクトの内容は、`"format"` パラメーター、`"proof"` パラメーター、
`"credential_response_encryption"` パラメーターが含まれていないことを除き、
クレデンシャルリクエストとほぼ同じです。

##### 3.5.1.5. クレデンシャル発行指示 ステップ 5

クレデンシャル情報がいずれかの発行可能クレデンシャルのサブセットであるかどうかを調べることにより、
アクセストークンがクレデンシャルリクエストのための必要な権限を持っていることを確認します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_5.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=749800d0f9632d511d909caf10e270ef" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_5.png" />

しかしながら、プログラマであれば、現在の OID4VCI 仕様ではこのステップを実装することが困難なことを理解できるでしょう。
さらに、SD-JWT VC では、「`vct` の値によりクレームの集合を決め、個々のクレームを一つ一つ指定する必要をなくす」という提案があります。
この提案は、JSON オブジェクト同士の包含関係を機械的に調べることでアクセストークンの権限をチェックすることを不可能にします。

そのため、アクセストークンが十分な権限を持っていることの確認は、クレデンシャルイシュアがそれぞれの方針に基づいて実装することになります。
包含関係に基づく権限チェックは Authlete に実装済みではありますが、無効にしてあります。

##### 3.5.1.6. クレデンシャル発行指示 ステップ 6

クレデンシャル情報に基づき、発行する VC に埋め込むユーザクレームの集合を決定し、ユーザデータベースから取り出しておいたデータセットからそれらのユーザクレーム群の情報を取得します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_6.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=444936a7896c9e7eebe5e247a04a81fc" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_6.png" />

##### 3.5.1.7. クレデンシャル発行指示 ステップ 7

集めたデータを使いクレデンシャル発行指示を作成します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_7.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=1adf4255b02fd8f8e7144d271a0550de" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_7.png" />

クレデンシャル発行指示は下表に列挙されたプロパティを持つ JSON オブジェクトです。

| プロパティ                | 型   | 説明                                                                                                                |
| :------------------- | :-- | :---------------------------------------------------------------------------------------------------------------- |
| `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][CredentialSingleIssueRequest] 参照) を用意します。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_8.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=cf579c586db5429b3cdf8c833b9b439a" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_8.png" />

\| /vci/single/issue API へのリクエスト |
\| HTTP メソッドと Content-Type | POST | application/json |
\| リクエストパラメーター | accessToken | クレデンシャルエンドポイントに提示されたアクセストークン。 |
\| order | VC またはトランザクション ID を発行するための命令を提供するクレデンシャル発行指示。 |

##### 3.5.1.9. クレデンシャル発行指示 ステップ 9

用意したリクエストを `/vci/single/issue` API に送ります。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order_9.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=0f369d029b25f1b92a1153b1fa8fbf97" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order_9.png" />

##### 3.5.1.10. クレデンシャル発行指示 ステップの要約

次の図はクレデンシャル発行指示を用意する手順の要約です。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_issuance_order.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=ff381eb4fd09b6b7e45a57d44b8307c6" alt="" width="1600" height="900" data-path="protocols-and-flows/compliance-profiles/credential_issuance_order.png" />

### 3.6. 一括クレデンシャルエンドポイント実装

執筆予定。

## 4. OID4VCI デモ

### 4.1. 事前認可コードフロー + 鍵証明 + SD-JWT VC

#### 4.1.1. セットアップ

このデモで使うリソースをダウンロードします。

```shell theme={null}
git clone git@github.com:authlete/oid4vci-demo.git
cd oid4vci-demo
```

このデモ用のシェル変数を設定します。

```shell theme={null}
CLIENT_ID=218232426
TOKEN_ENDPOINT=https://trial.authlete.net/api/token
CREDENTIAL_ISSUER=https://trial.authlete.net
CREDENTIAL_ENDPOINT=https://trial.authlete.net/api/credential
```

#### 4.1.2. 事前認可コード

『**事前認可コード**』を含む『**クレデンシャルオファー**』を生成するため、
[https://trial.authlete.net/api/offer/issue](https://trial.authlete.net/api/offer/issue) にアクセスします。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issue_page.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=0b4a0cc0a8cd7fd022064a5871eb27b2" alt="" width="660" height="840" data-path="protocols-and-flows/compliance-profiles/credential_offer_issue_page.png" />

この URL で表示されるページは、デモ用に任意のクレデンシャルオファーを生成するためのフォームを提供します。
フォームの『Pre-authorized code grant included』がチェックされていると、生成されるクレデンシャルオファーに事前認可コードが含まれるようになります。

Login ID フィールドと Password フィールドにそれぞれ `inga`、`inga` を入力し、
Pre-authorized code grant included にチェックがついていることを確認し、
Submit ボタンを押します。これにより、結果ページが表示されます。

<img src="https://mintcdn.com/authlete/YFJcSy4uVerokBPD/protocols-and-flows/compliance-profiles/credential_offer_issue_page_result.png?fit=max&auto=format&n=YFJcSy4uVerokBPD&q=85&s=631082c62df9aa4b0f457626859071c0" alt="" width="700" height="800" data-path="protocols-and-flows/compliance-profiles/credential_offer_issue_page_result.png" />

結果ページで表示される QR コードは、クレデンシャルオファーを含む URL を表しています。
クレデンシャルオファーの中身は、QR コードの下に置かれている JSON に表示されます。
この JSON 内の `pre-authorized_code` プロパティの値が発行された事前認可コードです。

次の手順で使うので、発行された事前認可コードをシェル変数 `PRE_AUTHORIZED_CODE` に設定します。

```shell theme={null}
PRE_AUTHORIZED_CODE=NH9udMon5pTuuvbsNsHUNWf8tpU__9wt-gsO9LeYthc
```

#### 4.1.3. アクセストークン

事前認可コードフローを用いて『**トークンリクエスト**』を送ります。
このデモのクライアントはパブリッククライアントなので、クライアント認証は要求されません。
つまり、クライアント認証に関連するリクエストパラメーターを追加する必要はありません。

```shell theme={null}
curl -s $TOKEN_ENDPOINT \
     -d client_id=$CLIENT_ID \
     -d grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code \
     -d pre-authorized_code=$PRE_AUTHORIZED_CODE
```

トークンエンドポイントは次のような応答を返します。

```json theme={null}
{
  "access_token": "xj2YRmSV-_e15n7mTXSvkCH-Yw-XklRagEHF5WXE7R4",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": null,
  "refresh_token": "Oq7H2GsuES4Z6d_63Dn7rWhJ9rCpgzmzwQ-BYtGR1yE",
  "c_nonce": "EhTC8LA6kVrrO6_XiC7N6N_wXdma2Zs1LHAQBZ5E0T0",
  "c_nonce_expires_in": 86400
}
```

レスポンスには `access_token` パラメーターと `c_nonce` パラメーターが含まれます。
後ほど使うので、これらのレスポンスパラメーターの値をシェル変数に設定します。

```shell theme={null}
ACCESS_TOKEN=xj2YRmSV-_e15n7mTXSvkCH-Yw-XklRagEHF5WXE7R4
C_NONCE=EhTC8LA6kVrrO6_XiC7N6N_wXdma2Zs1LHAQBZ5E0T0
```

#### 4.1.4. 鍵証明

保有者の鍵 `holder.jwk` と `generate-key-proof` スクリプトを用いて、JWT 形式の『**鍵証明**』を生成します。
この JWK ファイルとスクリプトは [oid4vci-demo レポジトリ][AUTHLETE_OID4VCI_DEMO]に含まれています。

```shell theme={null}
./generate-key-proof \
    -i $CREDENTIAL_ISSUER \
    -k holder.jwk \
    -c $CLIENT_ID \
    -n $C_NONCE
```

`generate-key-proof` スクリプトは次のような鍵証明を生成します。

```text theme={null}


eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiUFN4UXJEMnpsMF9tWGNBcXoxbWdxU2VCb0Jobm14Mnl4QkVwckJZOEYyMCIsInkiOiJ4VjhmYmkxRlNvc1V1bkxldUxOdUxrSmlxbVk2VEtpTW51ci1HbjJ3UjEwIn19.eyJpc3MiOiIyMTgyMzI0MjYiLCJhdWQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsImlhdCI6MTcwMzg0NzM3Niwibm9uY2UiOiJFaFRDOExBNmtWcnJPNl9YaUM3TjZOX3dYZG1hMlpzMUxIQVFCWjVFMFQwIn0.6l8QnPTclDUoWH5PsVsZQDauA_HcIVDGxU9-TfezflIIAzTFgeC5nTr5rLBkEIgcfUvkUOwKqlM06LdVVwTZlw
```

鍵証明のヘッダとペイロードを base64url でデコードすると、次の JSON が得られます。

```json theme={null}
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
    "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
  }
}
```

```json theme={null}
{
  "iss": "218232426",
  "aud": "https://trial.authlete.net",
  "iat": 1703847376,
  "nonce": "EhTC8LA6kVrrO6_XiC7N6N_wXdma2Zs1LHAQBZ5E0T0"
}
```

`generate-key-proof` スクリプトの実行結果は、次のようにすることで直接シェル変数
`KEY_PROOF_JWT` に設定することができます。

```shell theme={null}
KEY_PROOF_JWT=`./generate-key-proof -i $CREDENTIAL_ISSUER -k holder.jwk -c $CLIENT_ID -n $C_NONCE`
```

#### 4.1.5. SD-JWT VC

生成した鍵証明と一緒に、『**クレデンシャルエンドポイント**』に『**クレデンシャルリクエスト**』を送ります。

```shell theme={null}
curl -s $CREDENTIAL_ENDPOINT \
       -H "Authorization: Bearer $ACCESS_TOKEN" \
       -H "Content-Type: application/json" \
       --data '{
  "format": "vc+sd-jwt",
  "vct": "https://credentials.example.com/identity_credential",
  "proof": {
    "proof_type": "jwt",
    "jwt":"'${KEY_PROOF_JWT}'"
  }
}'
```

クレデンシャルエンドポイントは次のような応答を返します。

```json theme={null}
{
  "credential": "eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJfc2QiOlsiMERFMXBjUHo3LURtYlc5NlRLaFlHUFlENi05dnNtUzFra21EWVQ4NnF1NCIsIjdXeHNTejhXSWtBaHdLZmQ0aUVXRFBrOUhuMFdqZ1V6N0pHX3hqekVwTjQiLCJCVVdOQlh2bkJwZ1ZWaUpaLVdPTWFxZHhiOTRfSUR1OEhNaEZnUjU2aXd3IiwiR1BqSG1lOFhaS2JvWFhLMllPU2Y4cE10QXNzSGlKQU5QdW91WkI1QTZuNCIsIklhN3FqdVNDSmdGWDRiX09uS2p4dWJsU0tTWmRWcUhFdEpVRHZHRWtEWVEiLCJQenUtUEVqUlE5bF9vNkVEUmp0QnBpaWZqUVNMV0RNZ2ExM2VscTZpRW44IiwiVTRQWHdKMDMtenlEeUtpZFlPQWsxUkMzNWNZT2FCdnZ5bG9BQnM3bXZ1RSIsImxrT1BCTm9qNFk0OGE4a1F4VmlTSkJlQWdieE5YTEdSaEI5dkliejJCdjgiLCJuUDdMcmk2QmlqVHF0VVI2cTRfakwxTzlyWnd2OE9sdGlEX1lUWGlTa2ZrIiwidF9WbWxQQmxNcENiRG5NUjhzYUdDX2ZqMVZCb3FCLVUyZk1NYWZNbVRNayJdLCJ2Y3QiOiJodHRwczovL2NyZWRlbnRpYWxzLmV4YW1wbGUuY29tL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0IiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNE05a0lyQjlXWXp0MUdRZ0wxMmx6ZEJac0d5ZVYzbGdQS292MjhvVDVMNCIsIngiOiJQU3hRckQyemwwX21YY0FxejFtZ3FTZUJvQmhubXgyeXhCRXByQlk4RjIwIiwieSI6InhWOGZiaTFGU29zVXVuTGV1TE51TGtKaXFtWTZUS2lNbnVyLUduMndSMTAifX0sImlhdCI6MTcwMzg0NzYwNX0.2k4JTf61BOs461fLToA9VwZbY64i9TIfchZVasC0OCx2rDJYodeRc6uVjYuHBOZUHlMJ1WdTjCFfKuxE5juxMA~WyIxMjBTWFZhTzZKTWxoc0dIZUdVdktRIiwic3ViIiwiMTAwNCJd~WyJVUl9MTU5ocGFLUUVpbEQ1TXc5RnB3IiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJhT2huYjgySmFMbjZ0OHRZZXpGanl3IiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJGNzE0ZktfRFpSMm83ajFWRkpIUW5BIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~",
  "c_nonce": "EhTC8LA6kVrrO6_XiC7N6N_wXdma2Zs1LHAQBZ5E0T0",
  "c_nonce_expires_in": 85956
}
```

レスポンス内の `credential` パラメーターの値が発行された SD-JWT VC です。
この SD-JWT VC がシェル変数 `SD_JWT` に設定されている場合、`decode-sd-jwt`
スクリプトを次のように起動することで、SD-JWT VC の内容をデコードすることができます。

```shell theme={null}
./decode-sd-jwt $SD_JWT
```

結果は次のようになります。

```json theme={null}
{
  "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
  "typ": "vc+sd-jwt",
  "alg": "ES256"
}
{
  "_sd": [
    "0DE1pcPz7-DmbW96TKhYGPYD6-9vsmS1kkmDYT86qu4",
    "7WxsSz8WIkAhwKfd4iEWDPk9Hn0WjgUz7JG_xjzEpN4",
    "BUWNBXvnBpgVViJZ-WOMaqdxb94_IDu8HMhFgR56iww",
    "GPjHme8XZKboXXK2YOSf8pMtAssHiJANPuouZB5A6n4",
    "Ia7qjuSCJgFX4b_OnKjxublSKSZdVqHEtJUDvGEkDYQ",
    "Pzu-PEjRQ9l_o6EDRjtBpiifjQSLWDMga13elq6iEn8",
    "U4PXwJ03-zyDyKidYOAk1RC35cYOaBvvyloABs7mvuE",
    "lkOPBNoj4Y48a8kQxViSJBeAgbxNXLGRhB9vIbz2Bv8",
    "nP7Lri6BijTqtUR6q4_jL1O9rZwv8OltiD_YTXiSkfk",
    "t_VmlPBlMpCbDnMR8saGC_fj1VBoqB-U2fMMafMmTMk"
  ],
  "vct": "https://credentials.example.com/identity_credential",
  "_sd_alg": "sha-256",
  "iss": "https://trial.authlete.net",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "kid": "4M9kIrB9WYzt1GQgL12lzdBZsGyeV3lgPKov28oT5L4",
      "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
      "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
    }
  },
  "iat": 1703847605
}
{
  "digest": "lkOPBNoj4Y48a8kQxViSJBeAgbxNXLGRhB9vIbz2Bv8",
  "WyIxMjBTWFZhTzZKTWxoc0dIZUdVdktRIiwic3ViIiwiMTAwNCJd": [
    "120SXVaO6JMlhsGHeGUvKQ",
    "sub",
    "1004"
  ]
}
{
  "digest": "0DE1pcPz7-DmbW96TKhYGPYD6-9vsmS1kkmDYT86qu4",
  "WyJVUl9MTU5ocGFLUUVpbEQ1TXc5RnB3IiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ": [
    "UR_LMNhpaKQEilD5Mw9Fpw",
    "given_name",
    "Inga"
  ]
}
{
  "digest": "nP7Lri6BijTqtUR6q4_jL1O9rZwv8OltiD_YTXiSkfk",
  "WyJhT2huYjgySmFMbjZ0OHRZZXpGanl3IiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd": [
    "aOhnb82JaLn6t8tYezFjyw",
    "family_name",
    "Silverstone"
  ]
}
{
  "digest": "U4PXwJ03-zyDyKidYOAk1RC35cYOaBvvyloABs7mvuE",
  "WyJGNzE0ZktfRFpSMm83ajFWRkpIUW5BIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd": [
    "F714fK_DZR2o7j1VFJHQnA",
    "birthdate",
    "1991-11-06"
  ]
}
```

### 4.2. 認可コードフロー + PAR + DPoP + mdoc

#### 4.2.1. セットアップ

このデモで使うリソースをダウンロードします。

```shell theme={null}
git clone git@github.com:authlete/oid4vci-demo.git
cd oid4vci-demo
```

このデモ用のシェル変数を設定します。

```shell theme={null}
CLIENT_ID=218232426
TOKEN_ENDPOINT=https://trial.authlete.net/api/token
CREDENTIAL_ISSUER=https://trial.authlete.net
CREDENTIAL_ENDPOINT=https://trial.authlete.net/api/credential
PAR_ENDPOINT=https://trial.authlete.net/api/par
```

#### 4.2.2. リクエスト URI

DPoP 用の秘密鍵 `dpop.jwk` と `generate-dpop-proof` スクリプトを用いて
**DPoP proof JWT** ([RFC 9449][RFC_9449]) を生成します。

```shell theme={null}
DPOP_PROOF_JWT=`./generate-dpop-proof -k dpop.jwk -m POST -u $PAR_ENDPOINT`
```

`generate-dpop-proof` スクリプトは次のような DPoP proof JWT を生成します。

```text theme={null}


eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiaEdmcXpHWGdhbzFRZ1ZJVFk2a2lIWU9LYmFMWEJ4VHFQSmE0RU9pbXhoSSIsInkiOiJFMUtpQV9mQTJ4OElycnlzb0dkbkJUTUI1LW8zRUpUX01nUUFfSG1HdTlNIn19.eyJqdGkiOiJoRm9HQkFBN3ZXTHExbWJ6IiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0L2FwaS9wYXIiLCJpYXQiOjE3MDM4NjQ5ODR9.9VZtrwjASCEeO6v0SuGqEttYtoHORtGMNn95mSx4uNv04oA8hSDDBo4CoPQiaGsEjunJ_d_zKR7VsrF9M8BBZA
```

DPoP proof JWT のヘッダとペイロードを base64url でデコードすると、次の JSON が得られます。
ペイロードの `htu` クレームの値が PAR エンドポイントの URL であることに注目してください。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "hFoGBAA7vWLq1mbz",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/par",
  "iat": 1703864984
}
```

PAR エンドポイントに **PAR リクエスト**を送ります。ここで注目すべき点は、(1) PAR リクエストに
`DPoP` ヘッダが含まれていること、及び (2) `scope` パラメーターが
`org.iso.18013.5.1.mDL` を含んでいることです。

```shell theme={null}
curl -s $PAR_ENDPOINT \
     -H "DPoP: $DPOP_PROOF_JWT" \
     -d client_id=$CLIENT_ID \
     -d response_type=code \
     -d scope=org.iso.18013.5.1.mDL
```

この `scope` の値は、クレデンシャルイシュアメタデータの
`credential_configurations_supported` オブジェクトに、
`scope` プロパティの値が `org.iso.18013.5.1.mDL`
であるクレデンシャル設定が少なくとも一つ含まれていることを想定しています。

```json theme={null}
{
  "credential_configurations_supported": {
    "org.iso.18013.5.1.mDL": {
      "format": "mso_mdoc",
      "doctype": "org.iso.18013.5.1.mDL",
      "scope": "org.iso.18013.5.1.mDL",
      "claims": {
        "org.iso.18013.5.1": {
          "family_name": {},
          ...
        }
      }
    }
  },
  ...
}
```

PAR エンドポイントは次のようなレスポンスを返します。レスポンス内の `request_uri`
パラメーターの値が発行された**リクエスト URI** です。
この値は次のステップで使用します。

```json theme={null}
{
  "expires_in": 600,
  "request_uri": "urn:ietf:params:oauth:request_uri:du-ptCtuukbVDi2MgOjYwwb99cl-ho0bzzLb0X0u1n0"
}
```

#### 4.2.3. 認可コード

ウェブブラウザを使い、認可エンドポイントに**認可リクエスト**を送ります。URL 内の `$REQUEST_URI`
を先ほどのステップで PAR エンドポイントから受け取った実際のリクエスト URI で置き換えることを忘れないでください。

```
https://trial.authlete.net/api/authorization?client_id=218232426&request_uri=$REQUEST_URI
```

認可ページが表示されます。Login ID フィールドと Password フィールドに `inga`, `inga`
と入力し、Authorize ボタンを押してください。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/demo_mdoc_authorization_page.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=a80e37bec4aba0f7a048d7a7543a6119" alt="" width="560" height="840" data-path="protocols-and-flows/compliance-profiles/demo_mdoc_authorization_page.png" />

リダイレクトエンドポイントへとリダイレクトされます。
このエンドポイントで表示されるページでは、発行された**認可コード**の値を確認できます。
この認可コードは次のステップで使用します。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/demo_mdoc_redirection_endpoint.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=2cf426a1510dcb1966b886f5b8a8f24b" alt="" width="580" height="280" data-path="protocols-and-flows/compliance-profiles/demo_mdoc_redirection_endpoint.png" />

#### 4.2.4. アクセストークン

トークンエンドポイントにアクセスするための DPoP proof JWT を生成します。
`generate-dpop-proof` スクリプトの `-u` オプションに渡す引数が `$TOKEN_ENDPOINT`
であること (`$PAR_ENDPOINT` ではないこと) に注意してください。

```shell theme={null}
DPOP_PROOF_JWT=`./generate-dpop-proof -k dpop.jwk -m POST -u $TOKEN_ENDPOINT`
```

DPoP proof JWT のヘッダとペイロードを base64url でデコードすると、次の JSON が得られます。
ペイロードの `htu` クレームの値はトークンエンドポイントの URL になっています。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "KHV6KaCjtqwfnb8r",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/token",
  "iat": 1703865524
}
```

認可コードフローを使い、トークンエンドポイントに**トークンリクエスト**を送ります。
次のコマンドを実行する前に、先ほどのステップで発行された認可コードをシェル変数
`AUTHORIZATION_CODE` に設定することを忘れないでください。

```shell theme={null}
AUTHORIZATION_CODE=QaPvTUqX-aPDnrcFoCcYDZHW66RzC_vfi6EDq7derNs
```

```shell theme={null}
curl -s $TOKEN_ENDPOINT \
     -H "DPoP: $DPOP_PROOF_JWT" \
     -d client_id=$CLIENT_ID \
     -d grant_type=authorization_code \
     -d code=$AUTHORIZATION_CODE
```

トークンエンドポイントは次のようなレスポンスを返します。

```json theme={null}
{
  "access_token": "T01u7-43MOA17hB8DqW-dEaBqUpStWtitYoVW1ewlH4",
  "token_type": "DPoP",
  "expires_in": 86400,
  "scope": "org.iso.18013.5.1.mDL",
  "refresh_token": "17on7yghEeGPbaXmjTEMgEGPG8S79DweIBtCq0MZOHE",
  "c_nonce": "LQwqEX7sT1uJkzzTdULvLsHcUvXfUaT79bkzLWEi7jw",
  "c_nonce_expires_in": 86400
}
```

レスポンスには `access_token` パラメーターが含まれています。
次のステップで使うので、このパラメーターの値をシェル変数 `ACCESS_TOKEN` に設定してください。

```shell theme={null}
ACCESS_TOKEN=T01u7-43MOA17hB8DqW-dEaBqUpStWtitYoVW1ewlH4
```

#### 4.2.5. mdoc

クレデンシャルエンドポイントにアクセスするための DPoP proof JWT を生成します。
`generate-dpop-proof` スクリプトの `-u` オプションに渡す引数が `$CREDENTIAL_ENDPOINT` であること、
DPoP proof JWT に `ath` クレームを埋め込むために `-a` オプションを渡す必要があることに注意してください。

```shell theme={null}
DPOP_PROOF_JWT=`./generate-dpop-proof -k dpop.jwk -m POST -u $CREDENTIAL_ENDPOINT -a $ACCESS_TOKEN`
```

DPoP proof JWT のヘッダとペイロードを base64url でデコードすると、次の JSON が得られます。
ペイロードには `ath` クレームが含まれています。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "caK7sLDiAF9HbOi2",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/credential",
  "iat": 1703865668,
  "ath": "DUuszLa1NHTMoREsPQE0gB9znn1BRKYPUpOwBpVcLJo"
}
```

DPoP proof JWT とアクセストークンを併せて、**クレデンシャルエンドポイント**に**クレデンシャルリクエスト**を送ります。

```shell theme={null}
curl -s $CREDENTIAL_ENDPOINT \
     -H "DPoP: $DPOP_PROOF_JWT" \
     -H "Authorization: DPoP $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     --data '{
  "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": {},
      "document_number": {},
      "driving_privileges": {}
    }
  }
}'
```

クレデンシャルエンドポイントは次のようなレスポンスを返します。

```json theme={null}
{
  "credential": "omdkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGxpc3N1ZXJTaWduZWSiam5hbWVTcGFjZXOhcW9yZy5pc28uMTgwMTMuNS4xiNgYWFukaGRpZ2VzdElEAWZyYW5kb21QJ6e6efO1W1kaYmdXHjpSY3FlbGVtZW50SWRlbnRpZmllcmppc3N1ZV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDIzLTEyLTI52BhYXKRoZGlnZXN0SUQCZnJhbmRvbVBlLj1uVWnDyBHmzifHfxjhcWVsZW1lbnRJZGVudGlmaWVya2V4cGlyeV9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoyMDI0LTEyLTI52BhYWqRoZGlnZXN0SUQDZnJhbmRvbVAMR8e_GTnz4n7RFXKXgrAQcWVsZW1lbnRJZGVudGlmaWVya2ZhbWlseV9uYW1lbGVsZW1lbnRWYWx1ZWtTaWx2ZXJzdG9uZdgYWFKkaGRpZ2VzdElEBGZyYW5kb21QCHsjtktJ-PkSnEpzHOOCnHFlbGVtZW50SWRlbnRpZmllcmpnaXZlbl9uYW1lbGVsZW1lbnRWYWx1ZWRJbmdh2BhYW6RoZGlnZXN0SUQFZnJhbmRvbVAj-grPYzaQs1Np8Jom4yNpcWVsZW1lbnRJZGVudGlmaWVyamJpcnRoX2RhdGVsZWxlbWVudFZhbHVl2QPsajE5OTEtMTEtMDbYGFhVpGhkaWdlc3RJRAZmcmFuZG9tUByAlsGIDKRVgTjKy9AgNMxxZWxlbWVudElkZW50aWZpZXJvaXNzdWluZ19jb3VudHJ5bGVsZW1lbnRWYWx1ZWJVU9gYWFukaGRpZ2VzdElEB2ZyYW5kb21QpIldNj4zHUGw0vcfVFMsDXFlbGVtZW50SWRlbnRpZmllcm9kb2N1bWVudF9udW1iZXJsZWxlbWVudFZhbHVlaDEyMzQ1Njc42BhYoqRoZGlnZXN0SUQIZnJhbmRvbVByP2ESVgTLndyQCDgw1khMcWVsZW1lbnRJZGVudGlmaWVycmRyaXZpbmdfcHJpdmlsZWdlc2xlbGVtZW50VmFsdWWBo3V2ZWhpY2xlX2NhdGVnb3J5X2NvZGVhQWppc3N1ZV9kYXRl2QPsajIwMjMtMDEtMDFrZXhwaXJ5X2RhdGXZA-xqMjA0My0wMS0wMWppc3N1ZXJBdXRohEOhASahGCFZAWEwggFdMIIBBKADAgECAgYBjJHZwhkwCgYIKoZIzj0EAwIwNjE0MDIGA1UEAwwrSjFGd0pQODdDNi1RTl9XU0lPbUpBUWM2bjVDUV9iWmRhRko1R0RuVzFSazAeFw0yMzEyMjIxNDA2NTZaFw0yNDEwMTcxNDA2NTZaMDYxNDAyBgNVBAMMK0oxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQCilV5ugmlhHJzDVgqSRE5d8KkoQqX1jVg8WE4aPjFODZQ66fFPFIhWRP3ioVUi67WGQSgTY3F6Vmjf7JMVQ4MMAoGCCqGSM49BAMCA0cAMEQCIGcWNJwFy8RGV4uMwK7k1vEkqQ2xr-BCGRdN8OZur5PeAiBVrNuxV1C9mCW5z2clhDFaXNdP2Lp_7CBQrHQoJhuPcNgYWQHopWd2ZXJzaW9uYzEuMG9kaWdlc3RBbGdvcml0aG1nU0hBLTI1Nmx2YWx1ZURpZ2VzdHOhcW9yZy5pc28uMTgwMTMuNS4xqAFYIKroraryzIKijf6A0qMLKKEXhO4JkfgeofLS35R-tV-CAlggA1kTuTcqhUUzLu689TY7XaXTKDTQTy-X0CTtJbOgqJsDWCA9I2CynkOK1sgi3P7ZmCZJENPGQl8QsWImdXSNXsqEEARYIJ7fk0E18dWrB3R_X0NGXdshFSplLC2WiMGrqotXnbOVBVggs4p4mEragqpfssdgOpeGrmxeBq8kDp7rpVf-8mngGV4GWCAAGjwiUCuOj0CnVGknOCa217wUJthsqNS8CoxZ5BWQEQdYIDwygoPCSFXyutize7ktwCSKY5T7V4mWpizCFoVSkBy7CFggTWvL8cD_12lYMvje8i2T6YLEwNJNfje5lG6jfeS5I31nZG9jVHlwZXVvcmcuaXNvLjE4MDEzLjUuMS5tRExsdmFsaWRpdHlJbmZvo2ZzaWduZWTAdDIwMjMtMTItMjlUMTY6MDE6NTdaaXZhbGlkRnJvbcB0MjAyMy0xMi0yOVQxNjowMTo1N1pqdmFsaWRVbnRpbMB0MjAyNC0xMi0yOVQxNjowMTo1N1pYQPJyDU5h4tDesMtjRzbxcm77l-np35iKtKAKQj67Vh0XRHJsNxKoX_QJRLPrL1u58HuJDbwyA6c1ewBulm4AUAM",
  "c_nonce": "LQwqEX7sT1uJkzzTdULvLsHcUvXfUaT79bkzLWEi7jw",
  "c_nonce_expires_in": 86256
}
```

レスポンス内の `credential` パラメーターの値が発行された mdoc です。

ウェブサイト **CBOR Zone** ([https://cbor.zone/](https://cbor.zone/)) を使い、mdoc をデコードすることができます。
`credential` パラメーターの値をコピーし、CBOR Zone の Input セクションのテキストエリアに貼り付け、
`base64url` ラジオボタンを選択し、Generate ボタンを押してください。mdoc の内容が CBOR
診断記法 ([RFC 8949, 8. Diagnostic Notation][RFC_8949_8],
[RFC 8610, Appendix G. Extended Diagnostic Notation][RFC_8610_G]) で表示されます。

<img src="https://mintcdn.com/authlete/g-UM9YXVfm3jeKy0/protocols-and-flows/compliance-profiles/demo_mdoc_cbor_zone.png?fit=max&auto=format&n=g-UM9YXVfm3jeKy0&q=85&s=1825346a81327450239552f5d380bccb" alt="" width="1070" height="900" data-path="protocols-and-flows/compliance-profiles/demo_mdoc_cbor_zone.png" />

```
{
  "docType": "org.iso.18013.5.1.mDL",
  "issuerSigned": {
    "nameSpaces": {
      "org.iso.18013.5.1": [
        24(<<
          {
            "digestID": 1,
            "random": h'27a7ba79f3b55b591a6267571e3a5263',
            "elementIdentifier": "issue_date",
            "elementValue": 1004("2023-12-29")
          }
        >>),
        24(<<
          {
            "digestID": 2,
            "random": h'652e3d6e5569c3c811e6ce27c77f18e1',
            "elementIdentifier": "expiry_date",
            "elementValue": 1004("2024-12-29")
          }
        >>),
        24(<<
          {
            "digestID": 3,
            "random": h'0c47c7bf1939f3e27ed115729782b010',
            "elementIdentifier": "family_name",
            "elementValue": "Silverstone"
          }
        >>),
        24(<<
          {
            "digestID": 4,
            "random": h'087b23b64b49f8f9129c4a731ce3829c',
            "elementIdentifier": "given_name",
            "elementValue": "Inga"
          }
        >>),
        24(<<
          {
            "digestID": 5,
            "random": h'23fa0acf633690b35369f09a26e32369',
            "elementIdentifier": "birth_date",
            "elementValue": 1004("1991-11-06")
          }
        >>),
        24(<<
          {
            "digestID": 6,
            "random": h'1c8096c1880ca4558138cacbd02034cc',
            "elementIdentifier": "issuing_country",
            "elementValue": "US"
          }
        >>),
        24(<<
          {
            "digestID": 7,
            "random": h'a4895d363e331d41b0d2f71f54532c0d',
            "elementIdentifier": "document_number",
            "elementValue": "12345678"
          }
        >>),
        24(<<
          {
            "digestID": 8,
            "random": h'723f61125604cb9ddc90083830d6484c',
            "elementIdentifier": "driving_privileges",
            "elementValue": [
              {
                "vehicle_category_code": "A",
                "issue_date": 1004("2023-01-01"),
                "expiry_date": 1004("2043-01-01")
              }
            ]
          }
        >>)
      ]
    },
    "issuerAuth": [
      h'a10126',
      {
        33: h'3082015d30820104a0030201020206018c91d9c219300a06082a8648ce3d04030230363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b301e170d3233313232323134303635365a170d3234313031373134303635365a30363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b3059301306072a8648ce3d020106082a8648ce3d03010703420004028a5579ba09a58472730d582a49113977c2a4a10a97d63560f1613868f8c5383650eba7c53c52215913f78a85548baed61904a04d8dc5e959a37fb24c550e0c300a06082a8648ce3d040302034700304402206716349c05cbc446578b8cc0aee4d6f124a90db1afe04219174df0e66eaf93de022055acdbb15750bd9825b9cf672584315a5cd74fd8ba7fec2050ac7428261b8f70'
      },
      24(<<
        {
          "version": "1.0",
          "digestAlgorithm": "SHA-256",
          "valueDigests": {
            "org.iso.18013.5.1": {
              1: h'aae8adaaf2cc82a28dfe80d2a30b28a11784ee0991f81ea1f2d2df947eb55f82',
              2: h'035913b9372a8545332eeebcf5363b5da5d32834d04f2f97d024ed25b3a0a89b',
              3: h'3d2360b29e438ad6c822dcfed998264910d3c6425f10b1622675748d5eca8410',
              4: h'9edf934135f1d5ab07747f5f43465ddb21152a652c2d9688c1abaa8b579db395',
              5: h'b38a78984ada82aa5fb2c7603a9786ae6c5e06af240e9eeba557fef269e0195e',
              6: h'001a3c22502b8e8f40a75469273826b6d7bc1426d86ca8d4bc0a8c59e4159011',
              7: h'3c328283c24855f2bad8b37bb92dc0248a6394fb578996a62cc2168552901cbb',
              8: h'4d6bcbf1c0ffd7695832f8def22d93e982c4c0d24d7e37b9946ea37de4b9237d'
            }
          },
          "docType": "org.iso.18013.5.1.mDL",
          "validityInfo": {
            "signed": 0("2023-12-29T16:01:57Z"),
            "validFrom": 0("2023-12-29T16:01:57Z"),
            "validUntil": 0("2024-12-29T16:01:57Z")
          }
        }
      >>),
      h'f2720d4e61e2d0deb0cb634736f1726efb97e9e9df988ab4a00a423ebb561d1744726c3712a85ff40944b3eb2f5bb9f07b890dbc3203a7357b006e966e005003'
    ]
  }
}
```

### 4.3. POTENTIAL 相互運用性イベント / トラック 1 / Light プロファイル

[POTENTIAL][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)`       |

**認可サーバ**のソースコードは [https://github.com/authlete/java-oauth-server](https://github.com/authlete/java-oauth-server)
で入手可能です。ただしこの実装はサンプルであり、商用利用は想定していないので注意してください。

##### 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`                                                                            |
| クライアントタイプ  | パブリック (= [クライアント認証][CLIENT_AUTHENTICATION]は要求されない)                                        |
| リダイレクト URI | `https://nextdev-api.authlete.net/api/mock/redirection` または `eudi-openid4ci://authorize/` |

このクライアントにリダイレクト URI の追加登録が必要であるか、または自分専用のクライアントが必要であれば、我々に[ご連絡ください][CONTACT_US]。

<Note>
  Authlete メンバーへ: 新しいクライアントは
  "Trial" (組織 = 283415) /
  "NextDev" (サーバ = 2704222) /
  "Authlete Trial" (サービス = 986126671)
  に登録してください。
</Note>

#### 4.3.2. デモ手順

##### 4.3.2.1. 手順 1 : クレデンシャルオファー

クレデンシャルイシュアのサンプル実装は、開発者がテスト用に任意の**クレデンシャルオファー**を生成できるウェブページを提供しています。
ページの URL は [https://trial.authlete.net/api/offer/issue](https://trial.authlete.net/api/offer/issue) です。
このウェブページにアクセスすると、クレデンシャルオファーの内容を設定するフォームが表示されます。

以下の指示に従ってフォームを編集してください。

1. Login ID フィールドと Password フィールドに、 `inga`、`inga` を入力する。
2. Credential Configuration IDs を編集する。値は、文字列 `potential.light.profile` を含む JSON 配列とする。
3. Authorization Code Grant の横にある "include?" チェックボックスをチェックする。
4. Pre-Authorized Code Grant の横にある "include?" チェックボックスのチェックを外す。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track1_light_credential_offer_form.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=17c69fd445b8c934e47c9ffe4a53dd60" alt="" width="710" height="930" data-path="protocols-and-flows/compliance-profiles/potential_track1_light_credential_offer_form.png" />

フォーム編集後に Submit ボタンを押してください。
生成されたクレデンシャルオファーを含む URL を表す QR コードが表示されます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track1_light_credential_offer_qr_code.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=ae31e2596bc887b03858f75029315bbe" alt="" width="710" height="790" data-path="protocols-and-flows/compliance-profiles/potential_track1_light_credential_offer_qr_code.png" />

QR コードの下にある JSON はクレデンシャルオファーの内容を表しています。
JSON 内の `issuer_state` プロパティの値は発行された**イシュアステート**です。
上の例では、イシュアステートの値は
`tXkAkhSu5N9ORSNES9T64Bd9PAiKn9OmEOT5qDL0lkA`
です。

イシュアステートは、後ほど実行する認可リクエストに含めることになります。

##### 4.3.2.2. 手順 2 : コードベリファイアとコードチャレンジ

`pkce` コマンドを用いて、**コードベリファイア**を生成し、また、対応する**コードチャレンジ**を計算します
([RFC 7636][RFC_7636] 参照)。

```shell theme={null}
git clone git@github.com:authlete/oid4vci-demo.git
cd oid4vci-demo
./pkce
```

`pkce` コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。

```shell theme={null}
CODE_VERIFIER=gzRNlV7DLS_HyKMQKQMrzgYQ8aY3H2rVJ3iIlYK0cjE
CODE_CHALLENGE=j_4gpG9Kr3M7ilMO-MRoSROP-W3h2EZem0KSEU-RAhM
```

計算したコードチャレンジは次の手順で**認可リクエスト**に含めることになります。
また、生成したコードベリファイアは認可リクエストの後に実行する**トークンリクエスト**に含めることになります。

##### 4.3.2.3. 手順 3 : 認可リクエスト

**認可コードフロー** ([RFC 6749, 4.1][RFC_6749_4_1] 参照) を用いて**認可リクエスト**を実行します。
次の URL をお使いのウェブブラウザのアドレスバーに入力してください。URL 内の `${ISSUER_STATE}` と
`${CODE_CHALLENGE}` は、これまでの手順で生成したイシュアステートとコードチャレンジの実際の値で置き換えてください。

```
https://trial.authlete.net/api/authorization?client_id=track1_light&response_type=code&issuer_state=${ISSUER_STATE}&redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection&code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&prompt=login
```

URL にアクセスすると、**認可ページ**が表示されます。
このページにはログインフォームがあるので、Login ID フィールドと Password フィールドに
`inga`、`inga` と入力し、Authorize ボタンを押してください。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track1_light_authorization_page.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=629049ce72e234f6a9e41faf9ffedb1d" alt="" width="710" height="650" data-path="protocols-and-flows/compliance-profiles/potential_track1_light_authorization_page.png" />

リダイレクションエンドポイント ([RFC 6749, 3.1.2][RFC_6749_3_1_2] 参照)
にリダイレクトされます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track1_light_redirection_endpoint.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=7fb0ca3e8364ea1a3ab3070f7025307b" alt="" width="580" height="250" data-path="protocols-and-flows/compliance-profiles/potential_track1_light_redirection_endpoint.png" />

このリダイレクションエンドポイントは、受け取ったキー・バリューの組を表示します。
表示されている `code` パラメータの値が発行された**認可コード**です。
この例では、認可コードの値は
`gR43MQf2olvhMt6KekVDkUOdQPrVYgBiKXMwu_UFnB8`
です。

認可コードは次のセクションのトークンリクエストで使います。
認可コードは 10 分で期限切れとなるため、すみやかにトークンリクエスト実行しなければならないことに注意してください。

##### 4.3.2.4. 手順 4 : トークンリクエスト

認可コードフローを用いて**トークンリクエスト**を実行します。下記の `curl` コマンド内の
`${AUTHORIZATION_CODE}` と `${CODE_VERIFIER}` は、これまでの手順で取得した認可コードとコードベリファイアの実際の値で置き換えてください。

```shell theme={null}
curl -s https://trial.authlete.net/api/token \
     -d client_id=track1_light \
     -d grant_type=authorization_code \
     -d code=${AUTHORIZATION_CODE} \
     -d redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection \
     -d code_verifier=${CODE_VERIFIER}
```

トークンリクエストが有効であれば、トークンエンドポイントは次のような JSON を返します。

```json theme={null}
{
  "access_token": "tNR1stglRuBVUtS2sZ7tiThPcpNDENxY0LniVpRdp0E",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": null,
  "refresh_token": "nt3ba0H42UqMBw8FMY2keDgGAF65pBHY45-kydZFmSE",
  "c_nonce": "v-1b-n82kEJGbHROSekGsmR-xEuamCxY_T0tXtQN-dY",
  "c_nonce_expires_in": 86400
}
```

JSON 内の `access_token` プロパティの値は発行された**アクセストークン**です。
これは、**クレデンシャルリクエスト**を実行する際に提示する必要があります。

`c_nonce` プロパティの値は**鍵証明**に含めなければならないノンス値です。

##### 4.3.2.5. 手順 5 : CWT 鍵証明

[authlete/cbor][AUTHLETE_CBOR] ライブラリには、**CWT 鍵証明**を生成するためのユーティリティクラス
`CWTKeyProofBuilder` が含まれています。当ライブラリのレポジトリに含まれるシェルスクリプト
`bin/generate-cwt-key-proof` は、このユーティリティクラスをコマンドラインから起動するためのラッパーです。

次に示すように CWT 鍵証明を生成することができます。コマンドライン内の `${NONCE}` を、
先の手順でトークンエンドポイントから発行された `c_nonce` の値で置き換えてください。
また、`${PRIVATE_KEY_FILE}` を、JWK フォーマット ([RFC 7517][RFC_7517] 参照)
で秘密鍵を含むファイルの実際のパスで置き換えてください。
[authlete/oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリ内の `holder.jwk`
ファイルをこの用途で使うことができます。

```shell theme={null}
git clone git@github.com:authlete/cbor.git
cd cbor
mvn compile
./bin/generate-cwt-key-proof \
    --issuer https://trial.authlete.net \
    --key ${PRIVATE_KEY_FILE} \
    --client track1_light \
    --nonce ${NONCE}
```

`generate-cwt-key-proof` スクリプトは次のように CWT 鍵証明を表示します。

```text theme={null}

2D3ShFifowEmA3RvcGVuaWQ0dmNpLXByb29mK2N3dGhDT1NFX0tleVh7pgECAlgrMWU1QVk5RXlCMDFYblV6YTZMcEp6azAybjZZX0FtbW5TYjBGQmVOVlZyVQMmIAEhWCA9LFCsPbOXT-ZdwCrPWaCpJ4GgGGebHbLEESmsFjwXbSJYIMVfH24tRUqLFLpy3rizbi5CYqpmOkyojJ7q_hp9sEddoFhgpAFsdHJhY2sxX2xpZ2h0A3gaaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQGGmZf3KsKWCt2LTFiLW44MmtFSkdiSFJPU2VrR3NtUi14RXVhbUN4WV9UMHRYdFFOLWRZWEDVVsA-MQ9dAiaIRThTJ5JgmND4RZuhxcIiNx04TZ7fSqlQYJlRW9AyNqXeJHIEl1KqQs_yZtlPd98kRbvziTEi

```

この CWT 鍵証明を [CBOR Zone][CBOR_ZONE] を用いてデコードすると、次のようになります。

```
61(18(/ COSE_Sign1 / [
  / protected / <<
    {
      1: -7,
      3: "openid4vci-proof+cwt",
      "COSE_Key": h'a6010202582b3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255032620012158203d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d225820c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475d'
    }
  >>,
  / unprotected / {
  },
  h'a4016c747261636b315f6c6967687403781a68747470733a2f2f747269616c2e617574686c6574652e6e6574061a665fdcab0a582b762d31622d6e38326b454a476248524f53656b47736d522d784575616d4378595f5430745874514e2d6459',
  h'd556c03e310f5d02268845385327926098d0f8459ba1c5c222371d384d9edf4aa9506099515bd03236a5de2472049752aa42cff266d94f77df2445bbf3893122'
]))
```

保護ヘッダー内の `COSE_Key` の値は CBOR byte string で、COSE 鍵を内包しています。
この byte string をデコードすると、次の COSE 鍵が得られます。

```
{
  1: 2,
  2: h'3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255',
  3: -7,
  -1: 1,
  -2: h'3d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d',
  -3: h'c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475d'
}
```

##### 4.3.2.6. 手順 6 : クレデンシャルリクエスト

アクセストークンと CWT 鍵証明を使い、**クレデンシャルリクエスト**を実行します。
次のコマンドライン内の `${ACCESS_TOKEN}` と `${CWT_KEY_PROOF}`
は実際の値で置き換えてください。

```shell theme={null}
curl -s https://trial.authlete.net/api/credential \
     -H "Authorization: Bearer ${ACCESS_TOKEN}" \
     -H "Content-Type: application/json" \
     --data '{
  "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": {},
      "document_number": {},
      "driving_privileges": {}
    }
  },
  "proof": {
    "proof_type": "cwt",
    "cwt":"'${CWT_KEY_PROOF}'"
  }
}'
```

クレデンシャルリクエストが有効であれば、クレデンシャルエンドポイントは次のような JSON を返します。
JSON 内の `credential` プロパティの値が発行された **Verifiable Credential** (**VC**) です。

```json theme={null}
{
  "credential": "ompuYW1lU3BhY2VzoXFvcmcuaXNvLjE4MDEzLjUuMYjYGFhbpGhkaWdlc3RJRAFmcmFuZG9tUEJDfxiBFQGMwsBY7jE6mkdxZWxlbWVudElkZW50aWZpZXJqaXNzdWVfZGF0ZWxlbGVtZW50VmFsdWXZA-xqMjAyNC0wNi0wNdgYWFykaGRpZ2VzdElEAmZyYW5kb21QuWRGth4zjRXOJN_iGNTy0nFlbGVtZW50SWRlbnRpZmllcmtleHBpcnlfZGF0ZWxlbGVtZW50VmFsdWXZA-xqMjAyNS0wNi0wNdgYWFqkaGRpZ2VzdElEA2ZyYW5kb21Q7Zx7xYZtB0D02nL-x0UGFXFlbGVtZW50SWRlbnRpZmllcmtmYW1pbHlfbmFtZWxlbGVtZW50VmFsdWVrU2lsdmVyc3RvbmXYGFhSpGhkaWdlc3RJRARmcmFuZG9tUPMV5L8B03Uuj0GRMFZvWpJxZWxlbWVudElkZW50aWZpZXJqZ2l2ZW5fbmFtZWxlbGVtZW50VmFsdWVkSW5nYdgYWFukaGRpZ2VzdElEBWZyYW5kb21Q3fLHe4K4bUMJDFsSYKJ513FlbGVtZW50SWRlbnRpZmllcmpiaXJ0aF9kYXRlbGVsZW1lbnRWYWx1ZdkD7GoxOTkxLTExLTA22BhYVaRoZGlnZXN0SUQGZnJhbmRvbVDIzuaMNAe24KBZ3QQpP5o8cWVsZW1lbnRJZGVudGlmaWVyb2lzc3VpbmdfY291bnRyeWxlbGVtZW50VmFsdWViVVPYGFhbpGhkaWdlc3RJRAdmcmFuZG9tUJV-wSoCvKEqVh_g3844LmdxZWxlbWVudElkZW50aWZpZXJvZG9jdW1lbnRfbnVtYmVybGVsZW1lbnRWYWx1ZWgxMjM0NTY3ONgYWKKkaGRpZ2VzdElECGZyYW5kb21QZHMJeAleAPyXtFA-TiWBD3FlbGVtZW50SWRlbnRpZmllcnJkcml2aW5nX3ByaXZpbGVnZXNsZWxlbWVudFZhbHVlgaN1dmVoaWNsZV9jYXRlZ29yeV9jb2RlYUFqaXNzdWVfZGF0ZdkD7GoyMDIzLTAxLTAxa2V4cGlyeV9kYXRl2QPsajIwNDMtMDEtMDFqaXNzdWVyQXV0aIRDoQEmoRghWQFhMIIBXTCCAQSgAwIBAgIGAYyR2cIZMAoGCCqGSM49BAMCMDYxNDAyBgNVBAMMK0oxRndKUDg3QzYtUU5fV1NJT21KQVFjNm41Q1FfYlpkYUZKNUdEblcxUmswHhcNMjMxMjIyMTQwNjU2WhcNMjQxMDE3MTQwNjU2WjA2MTQwMgYDVQQDDCtKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAopVeboJpYRycw1YKkkROXfCpKEKl9Y1YPFhOGj4xTg2UOunxTxSIVkT94qFVIuu1hkEoE2NxelZo3-yTFUODDAKBggqhkjOPQQDAgNHADBEAiBnFjScBcvERleLjMCu5NbxJKkNsa_gQhkXTfDmbq-T3gIgVazbsVdQvZgluc9nJYQxWlzXT9i6f-wgUKx0KCYbj3BZArLYGFkCraZndmVyc2lvbmMxLjBvZGlnZXN0QWxnb3JpdGhtZ1NIQS0yNTZsdmFsdWVEaWdlc3RzoXFvcmcuaXNvLjE4MDEzLjUuMagBWCBtyGKRLbYNCtXpIqSixji4RYcXb4Vf7IDoQta4QfRWsAJYIJVrdxQWwcfqiFi75y5R3Saj8YpA8miZxmeoQL_JtB5-A1ggnoXpxMgIsgiIr8HlJ9JzfalESFVLgFxmES9SqSIsIG0EWCD-4Mo98S8qg8SJ8R-PMO7oCHW3wbdCfU8GGS0nG7VahwVYIE9yvCITC8M8p7-m2M4A5MwokXN3oS97uLkhk2AIj6GRBlgg8IaPGI_7Tp2rf2fLhEq0dDzm71FmTZUPc16BdJsCDgkHWCAKnWjJaTmwvgq1Yon8cLwPaPS1-lOEVASldrxYkeKLcwhYIEXVTVGxIhP9R64iPFGseCD_adyfhYZdCw-eOO8ckRjzbWRldmljZUtleUluZm-iaWRldmljZUtleaYBAgJYKzFlNUFZOUV5QjAxWG5VemE2THBKemswMm42WV9BbW1uU2IwRkJlTlZWclUDJiABIVggPSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20iWCDFXx9uLUVKixS6ct64s24uQmKqZjpMqIye6v4afbBHXXFrZXlBdXRob3JpemF0aW9uc6FqbmFtZVNwYWNlc4Fxb3JnLmlzby4xODAxMy41LjFnZG9jVHlwZXVvcmcuaXNvLjE4MDEzLjUuMS5tRExsdmFsaWRpdHlJbmZvo2ZzaWduZWTAdDIwMjQtMDYtMDVUMDM6MzU6MTRaaXZhbGlkRnJvbcB0MjAyNC0wNi0wNVQwMzozNToxNFpqdmFsaWRVbnRpbMB0MjAyNS0wNi0wNVQwMzozNToxNFpYQAs0d0MAErcaA1auodhHxivYcqiSXdQW9KtG9HpZoxo_oEPfkf7_dRQm_Z-ffhZn2qbLTc2Op3x0a1R-gif9Mtg",
  "c_nonce": "v-1b-n82kEJGbHROSekGsmR-xEuamCxY_T0tXtQN-dY",
  "c_nonce_expires_in": 86205
}
```

#### 4.3.3. VC フォーマット

前のセクションの VC を CBOR 診断記法で表すと次のようになります。

```
{
  "nameSpaces": {
    "org.iso.18013.5.1": [
      24(<<
        {
          "digestID": 1,
          "random": h'42437f188115018cc2c058ee313a9a47',
          "elementIdentifier": "issue_date",
          "elementValue": 1004("2024-06-05")
        }
      >>),
      24(<<
        {
          "digestID": 2,
          "random": h'b96446b61e338d15ce24dfe218d4f2d2',
          "elementIdentifier": "expiry_date",
          "elementValue": 1004("2025-06-05")
        }
      >>),
      24(<<
        {
          "digestID": 3,
          "random": h'ed9c7bc5866d0740f4da72fec7450615',
          "elementIdentifier": "family_name",
          "elementValue": "Silverstone"
        }
      >>),
      24(<<
        {
          "digestID": 4,
          "random": h'f315e4bf01d3752e8f419130566f5a92',
          "elementIdentifier": "given_name",
          "elementValue": "Inga"
        }
      >>),
      24(<<
        {
          "digestID": 5,
          "random": h'ddf2c77b82b86d43090c5b1260a279d7',
          "elementIdentifier": "birth_date",
          "elementValue": 1004("1991-11-06")
        }
      >>),
      24(<<
        {
          "digestID": 6,
          "random": h'c8cee68c3407b6e0a059dd04293f9a3c',
          "elementIdentifier": "issuing_country",
          "elementValue": "US"
        }
      >>),
      24(<<
        {
          "digestID": 7,
          "random": h'957ec12a02bca12a561fe0dfce382e67',
          "elementIdentifier": "document_number",
          "elementValue": "12345678"
        }
      >>),
      24(<<
        {
          "digestID": 8,
          "random": h'64730978095e00fc97b4503e4e25810f',
          "elementIdentifier": "driving_privileges",
          "elementValue": [
            {
              "vehicle_category_code": "A",
              "issue_date": 1004("2023-01-01"),
              "expiry_date": 1004("2043-01-01")
            }
          ]
        }
      >>)
    ]
  },
  "issuerAuth": [
    h'a10126',
    {
      33: h'3082015d30820104a0030201020206018c91d9c219300a06082a8648ce3d04030230363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b301e170d3233313232323134303635365a170d3234313031373134303635365a30363134303206035504030c2b4a3146774a50383743362d514e5f5753494f6d4a415163366e3543515f625a6461464a3547446e5731526b3059301306072a8648ce3d020106082a8648ce3d03010703420004028a5579ba09a58472730d582a49113977c2a4a10a97d63560f1613868f8c5383650eba7c53c52215913f78a85548baed61904a04d8dc5e959a37fb24c550e0c300a06082a8648ce3d040302034700304402206716349c05cbc446578b8cc0aee4d6f124a90db1afe04219174df0e66eaf93de022055acdbb15750bd9825b9cf672584315a5cd74fd8ba7fec2050ac7428261b8f70'
    },
    h'd8185902ada66776657273696f6e63312e306f646967657374416c676f726974686d675348412d3235366c76616c756544696765737473a1716f72672e69736f2e31383031332e352e31a80158206dc862912db60d0ad5e922a4a2c638b84587176f855fec80e842d6b841f456b0025820956b771416c1c7ea8858bbe72e51dd26a3f18a40f26899c667a840bfc9b41e7e0358209e85e9c4c808b20888afc1e527d2737da94448554b805c66112f52a9222c206d045820fee0ca3df12f2a83c489f11f8f30eee80875b7c1b7427d4f06192d271bb55a870558204f72bc22130bc33ca7bfa6d8ce00e4cc28917377a12f7bb8b9219360088fa191065820f0868f188ffb4e9dab7f67cb844ab4743ce6ef51664d950f735e81749b020e090758200a9d68c96939b0be0ab56289fc70bc0f68f4b5fa53845404a576bc5891e28b7308582045d54d51b12213fd47ae223c51ac7820ff69dc9f85865d0b0f9e38ef1c9118f36d6465766963654b6579496e666fa2696465766963654b6579a6010202582b3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255032620012158203d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d225820c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475d716b6579417574686f72697a6174696f6e73a16a6e616d6553706163657381716f72672e69736f2e31383031332e352e3167646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c76616c6964697479496e666fa3667369676e6564c074323032342d30362d30355430333a33353a31345a6976616c696446726f6dc074323032342d30362d30355430333a33353a31345a6a76616c6964556e74696cc074323032352d30362d30355430333a33353a31345a',
    h'0b3477430012b71a0356aea1d847c62bd872a8925dd416f4ab46f47a59a31a3fa043df91feff751426fd9f9f7e1667daa6cb4dcd8ea77c746b547e8227fd32d8'
  ]
}
```

この例では、VC は `IssuerSigned` 構造を表しています。この構造は、
[ISO/IEC 18013-5:2021][ISO_IEC_18013_5] のセクション
"8.3.2.1.2.2 Device retrieval mdoc response" で次のように定義されています。

```
IssuerSigned = {
  ? "nameSpaces" : IssuerNameSpaces,
  "issuerAuth" : IssuerAuth
}
```

<Note>
  意外ですが、フォーマットが `mso_mdoc` のときに `credential`
  プロパティがどの CBOR 構造を表すかについて、OID4VCI 仕様は指定していません。
  これは意図的とは考えにくく、単なる仕様の不備です。

  この曖昧さのため、Authlete の以前の実装では `IssuerSigned` 構造ではなく
  `Document` 構造が使われていました。興味深いことに、EUDI Wallet の実装は
  `IssuerSigned` 構造も `Document` 構造も想定していないようです。
  代わりに `DeviceResponse` 構造を想定しているようです。

  Authlete の実装を `IssuerSigned` 構造を用いるように変更した理由は、
  POTENTIAL Interop Event Track 1 のドキュメントが `IssuerSigned`
  構造を使うべきだと明示的に述べているからです。
</Note>

また、`IssuerAuth` 構造および関連する構造は次のように定義されています。

```
IssuerAuth = COSE_Sign1 ; The payload is MobileSecurityObjectBytes

MobileSecurityObjectBytes = #6.24(bstr .cbor MobileSecurityObject)

MobileSecurityObject = {
    "version" : tstr, ; Version of the MobileSecurityObject
    "digestAlgorithm" : tstr, ; Message digest algorithm used
    "valueDigests" : ValueDigests, ; Digests of all data elements per namespace
    "deviceKeyInfo" : DeviceKeyInfo,
    "docType" : tstr, ; docType as used in Documents
    "validityInfo" : ValidityInfo
}

DeviceKeyInfo = {
    "deviceKey" : DeviceKey
    ? "keyAuthorizations" : KeyAuthorizations,
    ? "keyInfo" : KeyInfo
}

DeviceKey = COSE_Key
```

`IssuerAuth` と `MobileSecurityObjectBytes`
の定義は、(CBOR タグで始まる) `MobileSecurityObjectBytes` が
`COSE_Sign1` のペイロードとして直接使われる印象を与えます。しかし、
`MobileSecurityObjectBytes` をさらに byte string
に変換する必要があります。

ですので、`h'd81859` で始まる、`"issuerAuth"` 配列の三番目の要素は、
`MobileSecurityObjectBytes` を含む byte string を表しています。
その byte string をデコードすることで、次の CBOR 構造を見ることができます。

```
24(<<
  {
    "version": "1.0",
    "digestAlgorithm": "SHA-256",
    "valueDigests": {
      "org.iso.18013.5.1": {
        1: h'6dc862912db60d0ad5e922a4a2c638b84587176f855fec80e842d6b841f456b0',
        2: h'956b771416c1c7ea8858bbe72e51dd26a3f18a40f26899c667a840bfc9b41e7e',
        3: h'9e85e9c4c808b20888afc1e527d2737da94448554b805c66112f52a9222c206d',
        4: h'fee0ca3df12f2a83c489f11f8f30eee80875b7c1b7427d4f06192d271bb55a87',
        5: h'4f72bc22130bc33ca7bfa6d8ce00e4cc28917377a12f7bb8b9219360088fa191',
        6: h'f0868f188ffb4e9dab7f67cb844ab4743ce6ef51664d950f735e81749b020e09',
        7: h'0a9d68c96939b0be0ab56289fc70bc0f68f4b5fa53845404a576bc5891e28b73',
        8: h'45d54d51b12213fd47ae223c51ac7820ff69dc9f85865d0b0f9e38ef1c9118f3'
      }
    },
    "deviceKeyInfo": {
      "deviceKey": {
        1: 2,
        2: h'3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255',
        3: -7,
        -1: 1,
        -2: h'3d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d',
        -3: h'c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475d'
      },
      "keyAuthorizations": {
        "nameSpaces": [
          "org.iso.18013.5.1"
        ]
      }
    },
    "docType": "org.iso.18013.5.1.mDL",
    "validityInfo": {
      "signed": 0("2024-06-05T03:35:14Z"),
      "validFrom": 0("2024-06-05T03:35:14Z"),
      "validUntil": 0("2025-06-05T03:35:14Z")
    }
  }
>>)
```

注目すべき点は、CWT 鍵証明に埋め込まれた公開鍵が、`deviceKey` の値として VC 内に現れることです。
CWT 鍵証明内の `COSE_Key` の値と VC 内の `deviceKey` の値が同一であることを確認してください。
双方とも次の COSE Key を保持しています。

```
{
  / kty /  1:  2 / EC2 /,
  / kid /  2: h'3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255',
  / alg /  3: -7 / ES256 /,
  / crv / -1:  1 / P-256 /,
  /  x  / -2: h'3d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d',
  /  y  / -3: h'c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475d'
}
```

COSE Key 内の整数ラベルと整数値については
[IANA: CBOR Object Signing and Encryption (COSE)][IANA_COSE] を参照してください。

### 4.4. POTENTIAL 相互運用性イベント / トラック 2 / Light プロファイル

[POTENTIAL][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)`       |

**認可サーバ**のソースコードは [https://github.com/authlete/java-oauth-server](https://github.com/authlete/java-oauth-server)
で入手可能です。ただしこの実装はサンプルであり、商用利用は想定していないので注意してください。

##### 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`                                                                            |
| クライアントタイプ  | パブリック (= [クライアント認証][CLIENT_AUTHENTICATION]は要求されない)                                        |
| リダイレクト URI | `https://nextdev-api.authlete.net/api/mock/redirection` または `eudi-openid4ci://authorize/` |

このクライアントにリダイレクト URI の追加登録が必要であるか、または自分専用のクライアントが必要であれば、我々に[ご連絡ください][CONTACT_US]。

<Note>
  Authlete メンバーへ: 新しいクライアントは
  "Trial" (組織 = 283415) /
  "NextDev" (サーバ = 2704222) /
  "Authlete Trial" (サービス = 986126671)
  に登録してください。
</Note>

#### 4.4.2. デモ手順

##### 4.4.2.1. 手順 1 : コードベリファイアとコードチャレンジ

`pkce` コマンドを用いて、**コードベリファイア**を生成し、また、対応する**コードチャレンジ**を計算します
([RFC 7636][RFC_7636] 参照)。

```shell theme={null}
git clone git@github.com:authlete/oid4vci-demo.git
cd oid4vci-demo
./pkce
```

`pkce` コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。

```shell theme={null}
CODE_VERIFIER=gzRNlV7DLS_HyKMQKQMrzgYQ8aY3H2rVJ3iIlYK0cjE
CODE_CHALLENGE=j_4gpG9Kr3M7ilMO-MRoSROP-W3h2EZem0KSEU-RAhM
```

計算したコードチャレンジは次の手順で**認可リクエスト**に含めることになります。
また、生成したコードベリファイアは認可リクエストの後に実行する**トークンリクエスト**に含めることになります。

##### 4.4.2.2. 手順 2 : 認可リクエスト

**認可コードフロー** ([RFC 6749, 4.1][RFC_6749_4_1] 参照) を用いて**認可リクエスト**を実行します。
次の URL をお使いのウェブブラウザのアドレスバーに入力してください。URL 内の `${CODE_CHALLENGE}`
は、先の手順で生成したコードチャレンジの実際の値で置き換えてください。

```
https://trial.authlete.net/api/authorization?client_id=track2_light&response_type=code&scope=potential.track2.light.profile&redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection&code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&prompt=login
```

URL にアクセスすると、**認可ページ**が表示されます。
このページにはログインフォームがあるので、Login ID フィールドと Password フィールドに
`inga`、`inga` と入力し、Authorize ボタンを押してください。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track2_light_authorization_page.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=eaf2cd62de0f0cc0b833d0e88cab3ef4" alt="" width="1460" height="1760" data-path="protocols-and-flows/compliance-profiles/potential_track2_light_authorization_page.png" />

リダイレクションエンドポイント ([RFC 6749, 3.1.2][RFC_6749_3_1_2] 参照)
にリダイレクトされます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track1_light_redirection_endpoint.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=7fb0ca3e8364ea1a3ab3070f7025307b" alt="" width="580" height="250" data-path="protocols-and-flows/compliance-profiles/potential_track1_light_redirection_endpoint.png" />

このリダイレクションエンドポイントは、受け取ったキー・バリューの組を表示します。
表示されている `code` パラメータの値が発行された**認可コード**です。
この例では、認可コードの値は
`gR43MQf2olvhMt6KekVDkUOdQPrVYgBiKXMwu_UFnB8`
です。

認可コードは次のセクションのトークンリクエストで使います。
認可コードは 10 分で期限切れとなるため、すみやかにトークンリクエスト実行しなければならないことに注意してください。

##### 4.4.2.3. 手順 3 : トークンリクエスト

認可コードフローを用いて**トークンリクエスト**を実行します。下記の `curl` コマンド内の
`${AUTHORIZATION_CODE}` と `${CODE_VERIFIER}` は、これまでの手順で取得した認可コードとコードベリファイアの実際の値で置き換えてください。

```shell theme={null}
curl -s https://trial.authlete.net/api/token \
     -d client_id=track2_light \
     -d grant_type=authorization_code \
     -d code=${AUTHORIZATION_CODE} \
     -d redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection \
     -d code_verifier=${CODE_VERIFIER}
```

トークンリクエストが有効であれば、トークンエンドポイントは次のような JSON を返します。

```json theme={null}
{
  "access_token": "FvF1eeUbbWwteF5v0nfsO6vb0jlWifgsP5U666qKSGs",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "potential.track2.light.profile",
  "refresh_token": "WUCNjsuU02XhOMWN5qHRkKKbZDX5g2HjJx52GWC_1Gw",
  "c_nonce": "rvw3Mo_ZHyEgYOoWQ9GEotemwFbhRvVVdI6e5Z0lhEs",
  "c_nonce_expires_in": 86400
}
```

JSON 内の `access_token` プロパティの値は発行された**アクセストークン**です。
これは、**クレデンシャルリクエスト**を実行する際に提示する必要があります。

`c_nonce` プロパティの値は**鍵証明**に含めなければならないノンス値です。

##### 4.4.2.4. 手順 4 : JWT 鍵証明

保有者の鍵 `holder.jwk` と `generate-key-proof` スクリプトを用いて、JWT 形式の『**鍵証明**』を生成します。
この JWK ファイルとスクリプトは [oid4vci-demo レポジトリ][AUTHLETE_OID4VCI_DEMO]に含まれています。

次のコマンドライン内の `$C_NONCE` は、先の手順で受け取ったトークンレスポンスに含まれる `c_nonce`
プロパティの実際の値で置き換えてください。

```shell theme={null}
./generate-key-proof \
    -i https://trial.authlete.net \
    -k holder.jwk \
    -c track2_light \
    -n $C_NONCE
```

`generate-key-proof` スクリプトは次のような鍵証明を生成します。

```text theme={null}


eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiUFN4UXJEMnpsMF9tWGNBcXoxbWdxU2VCb0Jobm14Mnl4QkVwckJZOEYyMCIsInkiOiJ4VjhmYmkxRlNvc1V1bkxldUxOdUxrSmlxbVk2VEtpTW51ci1HbjJ3UjEwIn19.eyJpc3MiOiJ0cmFjazJfbGlnaHQiLCJhdWQiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsImlhdCI6MTcxNzYxNzk1Nywibm9uY2UiOiJydnczTW9fWkh5RWdZT29XUTlHRW90ZW13RmJoUnZWVmRJNmU1WjBsaEVzIn0.E-9pdaSW2oaFqI2V0N1aRiSRI3LzOxwQFNR5tewaLXxP8R7ZHrU9-M7TLuqP5OmWRecdFrJ9yQAM83kbc4f5-A
```

鍵証明のヘッダとペイロードを base64url でデコードすると、次の JSON が得られます。

```json theme={null}
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
    "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
  }
}
```

```json theme={null}
{
  "iss": "track2_light",
  "aud": "https://trial.authlete.net",
  "iat": 1717617957,
  "nonce": "rvw3Mo_ZHyEgYOoWQ9GEotemwFbhRvVVdI6e5Z0lhEs"
}
```

`generate-key-proof` スクリプトの実行結果は、次のようにすることで直接シェル変数
`JWT_KEY_PROOF` に設定することができます。

```shell theme={null}
JWT_KEY_PROOF=`./generate-key-proof -i https://trial.authlete.net -k holder.jwk -c track2_light -n $C_NONCE`
```

##### 4.4.2.5. 手順 5 : クレデンシャルリクエスト

アクセストークンと JWT 鍵証明を使い、**クレデンシャルリクエスト**を実行します。
次のコマンドライン内の `${ACCESS_TOKEN}` と `${JWT_KEY_PROOF}`
は実際の値で置き換えてください。

```shell theme={null}
curl -s https://trial.authlete.net/api/credential \
     -H "Authorization: Bearer ${ACCESS_TOKEN}" \
     -H "Content-Type: application/json" \
       --data '{
  "format": "vc+sd-jwt",
  "vct": "urn:eu.europa.ec.eudi:pid:1",
  "proof": {
    "proof_type": "jwt",
    "jwt":"'${JWT_KEY_PROOF}'"
  }
}'
```

クレデンシャルリクエストが有効であれば、クレデンシャルエンドポイントは次のような JSON を返します。
JSON 内の `credential` プロパティの値が発行された **Verifiable Credential** (**VC**) です。

```json theme={null}
{
  "credential": "eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJwbGFjZV9vZl9iaXJ0aCI6eyJfc2QiOlsiRUFiQW1SN1owN1dpMVczczZLSVROMFdhamFzUTlObEJmYm9ocjgtU3hfcyIsImJCZ19NSWlKNnJhTU9jZ0dEd2ZtSUFMSEpFU2NJTEMyRjhCTmpOVW1MdG8iXX0sIl9zZCI6WyIxQThmRmJKMVlhM3RmQ3ZEUXpLNHNMSUhMRFJERWJEYk1oUEVmcF9TRzVVIiwiMjhqTDd3SFV0cTBuMXdaQUpmY1doTDVOWkt5QmtMMFRVM3NpaVNPbGV6WSIsIjJjcl9FNTM2cU1RMDB3Z1BTMURfbHZyZUFhc21tc3B4YU52T1Ffd3ZtTEEiLCI1dXE2ei13QWhaZUJEMkt3VjFONU5lcURqSWpXVHpqQi0xVU91anZOUllZIiwiNndhVlRLelZpMWZoMUxQc0ZfbURKdWJrcmFhZGpnUEtYTUdJN1B6blYwZyIsIjc4cmN0UnNtRWFuV1oybnZPVFdyNVlvWEZ5eW50ZklxMU1OOGp1bXJCOG8iLCI4OHZ3c1VVbHI1RmFiUGhPNVhhY3dIdG5nTXVTdjREVmFfa0E5OUUxa3lzIiwiOUd6YU4xZWc1NlczVEN4aGxwOWZLU093SFNfbmhEeEYxVnJTbEg3Z3ExRSIsIkJ3WkZRVENqVk0xRW5Ic1VIeXQzZ3JjdGhWMlJIVnFkTGJUdjMtLUVrOGciLCJFZDdVbFhYS0sydXdsblJNdHpSZHRnOFQwbVduUXhBOVVOblBldEt1T3VjIiwiRk56eFdmSGRhN0hXcEdkQWpJM1R3WnhXeE5YR0xwNHdqcEd1X0NqR0FYYyIsIkduSUZGOFg5TlpCbVRKQ2E5OUx4UFFST0c1YzZYUWsyemJ1NG9jbG45SWsiLCJMc2ZscHFUTFg4T0pYYk53eTdxcDU3MHRKY0I5T0dQeE9qTUxEU21BUTJJIiwiZHNKVjBHZ2JfZlVjeGlPalRvVUlDaEpGR1F5aFJMZHp2WWltQmNlSTN6YyIsImgydlN3UVN0SV9LcGtxU1djN011TG44VlB5a0VjelJFWjNEZ1hUd3QzM1EiLCJqQ0l4Z0lkY2JOUnVDbUJDeF9DQVQwZ2FvZURCU29VQnl4XzdfRFUxQmRvIiwia3RlSGlZdlhfbWphR0s0YkU4YjYyRktnUnZ2bFRCTVNxLXhpVlJQZTB6USIsInB5dXJrNU9zeGtYS2FoZ2lkbXdrTU56NTBUaWtGLV8zRkY0WG9SYlg0bDQiLCJ2VHc5VlpSOFpNQW0zWkhxZGJxNVBxSVBBZ0M2bVlyWGF4YmFkekFQOGpZIl0sImFkZHJlc3MiOnsiX3NkIjpbIjBXYUJrS3U4Q1lPV1NldjFDTThsYVNwS3VCbTZSTW1odktSR3kyWWRjaWMiLCJNbTdWX1dXRThVSk1TSHV0aV8xd0Nhb0puLUxKcTdaWG5FSDY1dXUxRTlrIiwiUFZKYmFmZjVzWmJCYm1HY2dkRWdOOXZsTWRndU9aal8yMjVYUk0xTHR3RSIsImlRT1pBN2RXQWVUaTg1RE1RQ1N0UmkySnVzSHB6YVJEN0FVRXZPQTJWN1UiLCJtMGVhYlEyTDViTEVPY3UwYjRRTkZQeWNvTHluUDAzYkxoRm9zTVdLeXRRIiwibXV0TU9aLVgxQlRoenM2OXdxQ3E3RFRieHFKNjRnWG9Yb2xHbnpyOUlmZyIsIm5LaXRPS3dBNW9oZ0QtNnVPNERIMW8wQnRoN0tWSndJaXlVSUhfcmJLLUUiLCJyQk15UlR6TFZkQV9uY291bDNLenN1cVluYWxLX0lnYWFMV0Z3aS14MjdzIiwidTgyUXhEemxyRVlsQWlSNUV1bGJ3ZWJSaFNnYWVaZ0o5dkEyRmd4M3ZvVSJdfSwidmN0IjoidXJuOmV1LmV1cm9wYS5lYy5ldWRpOnBpZDoxIiwiX3NkX2FsZyI6InNoYS0yNTYiLCJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsImtpZCI6IjRNOWtJckI5V1l6dDFHUWdMMTJsemRCWnNHeWVWM2xnUEtvdjI4b1Q1TDQiLCJ4IjoiUFN4UXJEMnpsMF9tWGNBcXoxbWdxU2VCb0Jobm14Mnl4QkVwckJZOEYyMCIsInkiOiJ4VjhmYmkxRlNvc1V1bkxldUxOdUxrSmlxbVk2VEtpTW51ci1HbjJ3UjEwIn19LCJpYXQiOjE3MTc2MTg2NjEsImFnZV9lcXVhbF9vcl9vdmVyIjp7Il9zZCI6WyIzZGo2NXpOMTMzS2haN1QwV1RidHczSVhialh4VHRIZUtoMlRWOWJVMzRjIiwiRFJUNi0tU2YtNDU4bGNaOEdobGd5TU5TZUVyNHRya3R1ZVhkNXNzNGtPRSJdfX0.EaUDXo2hWBNOqsdYBDAWpuHDYfGm9xNepZJn7rafTGAb3kHVxNJoSZTvOvLhk_sy30GpK2kLFWvVlR1nzxSMVg~WyJyeHR0ck5MbXUwNWc5cjVZVmc3bUtnIiwic3ViIiwiMTAwNCJd~WyJaR2lyT3Y3dUdLVXZOWUpVcFZ0QXJBIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyIwcGt4eEVwVmIwdW5mQUQ1R1VsZXVnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyI2RWtWSGN2U0lIZ215akE0VW5fZlNRIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~WyJhUzhNbVlFWHVWR1A5ODYwQV9lZDZRIiwiMTgiLHRydWVd~WyJMX1JRdm00Mll0XzdESHVjTi1IUHRRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyJmQmpkVWRTV0NBX0o4NXF2anlmcXVBIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd~WyJIOGVpZ0UxckQ2d3o3RDA3b0pnNjl3Iiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ~WyIxdngwVjJmTUVrTTBXNnVCYWg5VjRBIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyJHVnZfZWV0VElPLW93NTgzRTRMSDBBIiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd~WyJrYjJYUkhsMTQxazFyZG1xeGdDM2xRIiwiY291bnRyeSIsIlVTQSJd~WyJLU0VlbEV0dU5qbzZHQWR6NTFqSG93IiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd~WyJ0ZzBZQ3RNeHNPSW54aW9pUExDNV93IiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ~",
  "c_nonce": "rvw3Mo_ZHyEgYOoWQ9GEotemwFbhRvVVdI6e5Z0lhEs",
  "c_nonce_expires_in": 83596
}
```

#### 4.4.3. VC フォーマット

レスポンス内の `credential` パラメーターの値が発行された SD-JWT VC です。
この SD-JWT VC がシェル変数 `SD_JWT` に設定されている場合、`decode-sd-jwt`
スクリプトを次のように起動することで、SD-JWT VC の内容をデコードすることができます。

```shell theme={null}
./decode-sd-jwt $SD_JWT
```

結果は次のようになります。

```json theme={null}
{
  "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
  "typ": "vc+sd-jwt",
  "alg": "ES256"
}
{
  "place_of_birth": {
    "_sd": [
      "EAbAmR7Z07Wi1W3s6KITN0WajasQ9NlBfbohr8-Sx_s",
      "bBg_MIiJ6raMOcgGDwfmIALHJEScILC2F8BNjNUmLto"
    ]
  },
  "_sd": [
    "1A8fFbJ1Ya3tfCvDQzK4sLIHLDRDEbDbMhPEfp_SG5U",
    "28jL7wHUtq0n1wZAJfcWhL5NZKyBkL0TU3siiSOlezY",
    "2cr_E536qMQ00wgPS1D_lvreAasmmspxaNvOQ_wvmLA",
    "5uq6z-wAhZeBD2KwV1N5NeqDjIjWTzjB-1UOujvNRYY",
    "6waVTKzVi1fh1LPsF_mDJubkraadjgPKXMGI7PznV0g",
    "78rctRsmEanWZ2nvOTWr5YoXFyyntfIq1MN8jumrB8o",
    "88vwsUUlr5FabPhO5XacwHtngMuSv4DVa_kA99E1kys",
    "9GzaN1eg56W3TCxhlp9fKSOwHS_nhDxF1VrSlH7gq1E",
    "BwZFQTCjVM1EnHsUHyt3grcthV2RHVqdLbTv3--Ek8g",
    "Ed7UlXXKK2uwlnRMtzRdtg8T0mWnQxA9UNnPetKuOuc",
    "FNzxWfHda7HWpGdAjI3TwZxWxNXGLp4wjpGu_CjGAXc",
    "GnIFF8X9NZBmTJCa99LxPQROG5c6XQk2zbu4ocln9Ik",
    "LsflpqTLX8OJXbNwy7qp570tJcB9OGPxOjMLDSmAQ2I",
    "dsJV0Ggb_fUcxiOjToUIChJFGQyhRLdzvYimBceI3zc",
    "h2vSwQStI_KpkqSWc7MuLn8VPykEczREZ3DgXTwt33Q",
    "jCIxgIdcbNRuCmBCx_CAT0gaoeDBSoUByx_7_DU1Bdo",
    "kteHiYvX_mjaGK4bE8b62FKgRvvlTBMSq-xiVRPe0zQ",
    "pyurk5OsxkXKahgidmwkMNz50TikF-_3FF4XoRbX4l4",
    "vTw9VZR8ZMAm3ZHqdbq5PqIPAgC6mYrXaxbadzAP8jY"
  ],
  "address": {
    "_sd": [
      "0WaBkKu8CYOWSev1CM8laSpKuBm6RMmhvKRGy2Ydcic",
      "Mm7V_WWE8UJMSHuti_1wCaoJn-LJq7ZXnEH65uu1E9k",
      "PVJbaff5sZbBbmGcgdEgN9vlMdguOZj_225XRM1LtwE",
      "iQOZA7dWAeTi85DMQCStRi2JusHpzaRD7AUEvOA2V7U",
      "m0eabQ2L5bLEOcu0b4QNFPycoLynP03bLhFosMWKytQ",
      "mutMOZ-X1BThzs69wqCq7DTbxqJ64gXoXolGnzr9Ifg",
      "nKitOKwA5ohgD-6uO4DH1o0Bth7KVJwIiyUIH_rbK-E",
      "rBMyRTzLVdA_ncoul3KzsuqYnalK_IgaaLWFwi-x27s",
      "u82QxDzlrEYlAiR5EulbwebRhSgaeZgJ9vA2Fgx3voU"
    ]
  },
  "vct": "urn:eu.europa.ec.eudi:pid:1",
  "_sd_alg": "sha-256",
  "iss": "https://trial.authlete.net",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "kid": "4M9kIrB9WYzt1GQgL12lzdBZsGyeV3lgPKov28oT5L4",
      "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
      "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
    }
  },
  "iat": 1717618661,
  "age_equal_or_over": {
    "_sd": [
      "3dj65zN133KhZ7T0WTbtw3IXbjXxTtHeKh2TV9bU34c",
      "DRT6--Sf-458lcZ8GhlgyMNSeEr4trktueXd5ss4kOE"
    ]
  }
}
{
  "digest": "GnIFF8X9NZBmTJCa99LxPQROG5c6XQk2zbu4ocln9Ik",
  "WyJyeHR0ck5MbXUwNWc5cjVZVmc3bUtnIiwic3ViIiwiMTAwNCJd": [
    "rxttrNLmu05g9r5YVg7mKg",
    "sub",
    "1004"
  ]
}
{
  "digest": "jCIxgIdcbNRuCmBCx_CAT0gaoeDBSoUByx_7_DU1Bdo",
  "WyJaR2lyT3Y3dUdLVXZOWUpVcFZ0QXJBIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd": [
    "ZGirOv7uGKUvNYJUpVtArA",
    "family_name",
    "Silverstone"
  ]
}
{
  "digest": "h2vSwQStI_KpkqSWc7MuLn8VPykEczREZ3DgXTwt33Q",
  "WyIwcGt4eEVwVmIwdW5mQUQ1R1VsZXVnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ": [
    "0pkxxEpVb0unfAD5GUleug",
    "given_name",
    "Inga"
  ]
}
{
  "digest": "dsJV0Ggb_fUcxiOjToUIChJFGQyhRLdzvYimBceI3zc",
  "WyI2RWtWSGN2U0lIZ215akE0VW5fZlNRIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd": [
    "6EkVHcvSIHgmyjA4Un_fSQ",
    "birthdate",
    "1991-11-06"
  ]
}
{
  "digest": "DRT6--Sf-458lcZ8GhlgyMNSeEr4trktueXd5ss4kOE",
  "WyJhUzhNbVlFWHVWR1A5ODYwQV9lZDZRIiwiMTgiLHRydWVd": [
    "aS8MmYEXuVGP9860A_ed6Q",
    "18",
    true
  ]
}
{
  "digest": "EAbAmR7Z07Wi1W3s6KITN0WajasQ9NlBfbohr8-Sx_s",
  "WyJMX1JRdm00Mll0XzdESHVjTi1IUHRRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "L_RQvm42Yt_7DHucN-HPtQ",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "rBMyRTzLVdA_ncoul3KzsuqYnalK_IgaaLWFwi-x27s",
  "WyJmQmpkVWRTV0NBX0o4NXF2anlmcXVBIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd": [
    "fBjdUdSWCA_J85qvjyfquA",
    "formatted",
    "114 Old State Hwy 127, Shoshone, CA 92384, USA"
  ]
}
{
  "digest": "iQOZA7dWAeTi85DMQCStRi2JusHpzaRD7AUEvOA2V7U",
  "WyJIOGVpZ0UxckQ2d3o3RDA3b0pnNjl3Iiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ": [
    "H8eigE1rD6wz7D07oJg69w",
    "street_address",
    "114 Old State Hwy 127"
  ]
}
{
  "digest": "Mm7V_WWE8UJMSHuti_1wCaoJn-LJq7ZXnEH65uu1E9k",
  "WyIxdngwVjJmTUVrTTBXNnVCYWg5VjRBIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "1vx0V2fMEkM0W6uBah9V4A",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "PVJbaff5sZbBbmGcgdEgN9vlMdguOZj_225XRM1LtwE",
  "WyJHVnZfZWV0VElPLW93NTgzRTRMSDBBIiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd": [
    "GVv_eetTIO-ow583E4LH0A",
    "postal_code",
    "CA 92384"
  ]
}
{
  "digest": "m0eabQ2L5bLEOcu0b4QNFPycoLynP03bLhFosMWKytQ",
  "WyJrYjJYUkhsMTQxazFyZG1xeGdDM2xRIiwiY291bnRyeSIsIlVTQSJd": [
    "kb2XRHl141k1rdmqxgC3lQ",
    "country",
    "USA"
  ]
}
{
  "digest": "88vwsUUlr5FabPhO5XacwHtngMuSv4DVa_kA99E1kys",
  "WyJLU0VlbEV0dU5qbzZHQWR6NTFqSG93IiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd": [
    "KSEelEtuNjo6GAdz51jHow",
    "issuing_authority",
    "US"
  ]
}
{
  "digest": "kteHiYvX_mjaGK4bE8b62FKgRvvlTBMSq-xiVRPe0zQ",
  "WyJ0ZzBZQ3RNeHNPSW54aW9pUExDNV93IiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ": [
    "tg0YCtMxsOInxioiPLC5_w",
    "issuing_country",
    "US"
  ]
}
```

### 4.5. POTENTIAL 相互運用性イベント / トラック 2 / Full プロファイル

[POTENTIAL][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)`       |

**認可サーバ**のソースコードは [https://github.com/authlete/java-oauth-server](https://github.com/authlete/java-oauth-server)
で入手可能です。ただしこの実装はサンプルであり、商用利用は想定していないので注意してください。

##### 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/` |

このクライアントにリダイレクト URI の追加登録が必要であるか、または自分専用のクライアントが必要であれば、我々に[ご連絡ください][CONTACT_US]。

<Note>
  Authlete メンバーへ: 新しいクライアントは
  "Trial" (組織 = 283415) /
  "NextDev" (サーバ = 2704222) /
  "Authlete Trial" (サービス = 986126671)
  に登録してください。
</Note>

#### 4.5.2. デモ手順

##### 4.5.2.1. 手順 1 : コードベリファイアとコードチャレンジ

`pkce` コマンドを用いて、**コードベリファイア**を生成し、また、対応する**コードチャレンジ**を計算します
([RFC 7636][RFC_7636] 参照)。

```shell theme={null}
git clone git@github.com:authlete/oid4vci-demo.git
cd oid4vci-demo
./pkce
```

`pkce` コマンドは生成したコードベリファイアと計算したコードチャレンジを次のように表示します。

```shell theme={null}
CODE_VERIFIER=gzRNlV7DLS_HyKMQKQMrzgYQ8aY3H2rVJ3iIlYK0cjE
CODE_CHALLENGE=j_4gpG9Kr3M7ilMO-MRoSROP-W3h2EZem0KSEU-RAhM
```

計算したコードチャレンジは **PAR リクエスト** ([RFC 9126][RFC_9126]) に、生成したコードベリファイアは**トークンリクエスト**に含めることになります。

##### 4.5.2.2. 手順 2 : クライアントアテステーションとクライアントアテステーション PoP

POTENTIAL の Track 2 Full プロファイルでは
[OAuth 2.0 Attestation-Based Client Authentication][ATTESTATION_BASED_CLIENT_AUTH]
と呼ばれる新しいクライアント認証方式を用います。この方式のため、JWT を二つ用意しなければなりません。
それらの JWT はそれぞれ、**クライアントアテステーション** (**Client Attestation**)、
**クライアントアテステーション PoP** (**Client Attestation PoP**) と呼ばれます。

これらの JWT を生成するため、[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリには
`generate-client-attestation` と
`generate-client-attestation-pop`
という二つのスクリプトが含まれています。使い方は次の通りです。

```
使い方: generate-client-attestation [オプション]
        --attester-id=ATTESTER_ID    クライアントアテステーション発行者の識別子
        --attester-key=FILE          クライアントアテステーション発行者の秘密鍵を JWK 形式で含むファイル
        --client-id=CLIENT_ID        クライアントアプリケーションの識別子
        --client-key=FILE            クライアントアプリケーションの公開鍵を JWK 形式で含むファイル
        --duration=DURATION          クライアントアテステーションの有効秒数 (デフォルトは 86400)
```

```
使い方: generate-client-attestation-pop [オプション]
        --as-id=AS_ID                認可サーバの識別子
        --client-id=CLIENT_ID        クライアントアプリケーションの識別子
        --client-key=FILE            クライアントアプリケーションの秘密鍵を JWK 形式で含むファイル
        --duration=DURATION          クライアントアテステーション PoP の有効秒数 (デフォルトは 86400)
```

クライアントアテステーションを生成するためには、**クライアントアテステーション発行者**の秘密鍵とクライアントアプリケーションの公開鍵が必要です。
クライアントアテステーション発行者の秘密鍵はクライアントアテステーションに署名するのに使われます。
クライアントアプリケーションの公開鍵はクライアントアテステーションに埋め込まれます。

[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリにはデモ用のクライアントアテステーション発行者秘密鍵
(`attester.jwk`) とクライアントアプリケーションの秘密鍵 (`client.jwk`) が含まれています。
これらの鍵を用い、クライアントアテステーションを次のように生成することができます。

```shell theme={null}
./generate-client-attestation \
    --attester-id=https://attester.example.com \
    --attester-key=attester.jwk \
    --client-id=track2_full \
    --client-key=client.jwk
```

<Note>
  仮に**秘密鍵**が与えられたとしても、`generate-client-attestation`
  スクリプトは指定されたクライアント鍵の**公開**部分しか使いません。
  そのため、クライアントの**秘密鍵**を含むファイルを `--client-key`
  オプションに直接渡すことができます。
</Note>

<Note>
  上記の例ではクライアントアテステーション発行者の識別子として
  `https://attester.example.com` を用いています。Authlete
  の現在の実装は値について気にしないので、どんな値でも動きます。

  OAuth 2.0 Attestation-Based Client Authentication の現在の仕様 (この記事を執筆している時点では
  [draft 03](https://www.ietf.org/archive/id/draft-ietf-oauth-attestation-based-client-auth-03.html)) ではクライアントアテステーションの署名を検証するための公開鍵をどのように取得するかが決められていないことに注意してください。
  この点に関して、仕様は各エコシステムが独自ルールを定めることを期待しているように見受けられます。

  そのため、現在の Authlete の実装はクライアントアテステーションの署名を検証**しません**。
  クライアントアテステーション発行者の識別子の値も気にしません。
  クライアントアテステーションの署名の検証は、あなたの認可サーバの実装で実施しなければなりません。

  将来、この検証処理を補助する仕組みを Authlete は提供するかもしれません。
</Note>

`generate-client-attestation` スクリプトは次のような JWT
フォーマットのクライアントアテステーションを生成します。

```text theme={null}


eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6InpYOXhiSnFCemlNV0s1dm1qWEhnWlRtaVkxNnhmblp4elNFYTBHcVk1X1EifQ.eyJpc3MiOiJodHRwczovL2F0dGVzdGVyLmV4YW1wbGUuY29tIiwic3ViIjoidHJhY2syX2Z1bGwiLCJpYXQiOjE3MTk0NzMzNTIsImV4cCI6MTcxOTU1OTc1MiwiY25mIjp7Imp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6IjFBbVZyNEdvSGRQZ2s0OExXZFMzVDltNm0xbVA0VlRjajl1c29TQm5DUWsiLCJ5IjoidGUtV0l1VUlxMnc4dFhtWHlkbEVYNHBlOWxOZS1QQmNvekE4bjd5OFhURSJ9fX0._jNM-9vEL14AOJrfk03ipIi7YECL-SGXUvqtdSiaYKVGhq7AK15QiqzzIwBj92Lij7Y4DvrtGix-0Pf4hwhPmQ
```

次の JSON は生成された JWT のヘッダとペイロードを base64url でデコードしたものです。
クライアントアテステーション発行者の識別子が `iss` クレームの値として使われていること、
クライアントの**公開鍵**が `cnf.jwk` プロパティの値として埋め込まれていることを確認できます。

```json theme={null}
{
  "typ": "JWT",
  "alg": "ES256",
  "kid": "zX9xbJqBziMWK5vmjXHgZTmiY16xfnZxzSEa0GqY5_Q"
}
```

```json theme={null}
{
  "iss": "https://attester.example.com",
  "sub": "track2_full",
  "iat": 1719473352,
  "exp": 1719559752,
  "cnf": {
    "jwk": {
      "crv": "P-256",
      "kty": "EC",
      "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
      "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
    }
  }
}
```

クライアントアテステーション PoP を生成するためには、クライアントの秘密鍵が必要です。
クライアントの秘密鍵はクライアントアテステーション PoP に署名するのに使われます。

[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリ内のクライアント秘密鍵 (`client.jwk`) を使い、
クライアントアテステーション PoP を次のように生成することができます。

```shell theme={null}
./generate-client-attestation-pop \
    --as-id=https://trial.authlete.net \
    --client-id=track2_full \
    --client-key=client.jwk
```

`generate-client-attestation-pop` スクリプトは次のような JWT
フォーマットのクライアントアテステーション PoP を生成します。

```text theme={null}


eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ijd5TmhJSFZlYVBGSUJfMGstWXBpRkFUb21DTHB4SXYtZTJBQUZtQ1JCTEUifQ.eyJpc3MiOiJ0cmFjazJfZnVsbCIsImlhdCI6MTcxOTQ3MzUxOSwiZXhwIjoxNzE5NTU5OTE5LCJqdGkiOiJvRmJGNXhhdnZLMTBRekJhIiwiYXVkIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQifQ.TXeCcijI8tICBH1bhOcNYTof9D0vDKAlu9Y0rl21EnPkUOCcsohiI8K7B1MlP1z82oC0LlYywXpcZ_gNnAC8BQ
```

次の JSON は生成された JWT のヘッダとペイロードを base64url でデコードしたものです。
クライアントの識別子が `iss` クレームの値として使われていること、認可サーバの識別子が
`aud` クレームの値として指定されていることを確認できます。

```json theme={null}
{
  "typ": "JWT",
  "alg": "ES256",
  "kid": "7yNhIHVeaPFIB_0k-YpiFATomCLpxIv-e2AAFmCRBLE"
}
```

```json theme={null}
{
  "iss": "track2_full",
  "iat": 1719473519,
  "exp": 1719559919,
  "jti": "oFbF5xavvK10QzBa",
  "aud": "https://trial.authlete.net"
}
```

##### 4.5.2.3. 手順 3 : PAR リクエスト用 DPoP Proof JWT

DPoP Proof JWT を生成するため、[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリ内の
`generate-dpop-proof` スクリプトを使うことができます。

oid4vci-demo レポジトリにある DPoP デモ用の鍵 (`dpop.jwk`) を使い、次のようにスクリプトを起動できます。

```shell theme={null}
./generate-dpop-proof -k dpop.jwk -m POST \
    -u https://trial.authlete.net/api/par
```

<Note>
  `generate-dpop-proof` スクリプトの `-u` オプション
  (`--htu` オプションの短縮版) で DPoP Proof JWT の `htu`
  クレームの値を指定します。

  ここで生成する DPoP Proof JWT は PAR リクエストのためのものなので、`-u`
  オプションの値として PAR エンドポイントの URL
  (`https://trial.authlete.net/api/par`)
  を指定しています。
</Note>

`generate-dpop-proof` スクリプトは次のような JWT
フォーマットの DPoP Proof JWT を生成します。

```text theme={null}


eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiaEdmcXpHWGdhbzFRZ1ZJVFk2a2lIWU9LYmFMWEJ4VHFQSmE0RU9pbXhoSSIsInkiOiJFMUtpQV9mQTJ4OElycnlzb0dkbkJUTUI1LW8zRUpUX01nUUFfSG1HdTlNIn19.eyJqdGkiOiJxMWZJS21ad2FMNHlna1JQIiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0L2FwaS9wYXIiLCJpYXQiOjE3MTk0NzQ2MzZ9.K8Mp44eK586UNCE-63bt5-m0v8B8KV840lDBe_5h2wLBcNWceS5x2fbFh9Koe7V7Rrbn6VT_hnCF8jYqkt6-dg
```

次の JSON は生成された JWT のヘッダとペイロードを base64url でデコードしたものです。
`htu` クレームが PAR エンドポイントの URL を保持しています。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "q1fIKmZwaL4ygkRP",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/par",
  "iat": 1719474636
}
```

##### 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}`
は、ここまでの手順で取得した実際の値で置き換えてください。

```shell theme={null}
curl -s https://trial.authlete.net/api/par \
     -H "OAuth-Client-Attestation: ${CLIENT_ATTESTATION}" \
     -H "OAuth-Client-Attestation-PoP: ${CLIENT_ATTESTATION_POP}" \
     -H "DPoP: ${DPOP_PROOF_JWT_FOR_PAR_REQUEST}" \
     -d client_id=track2_full \
     -d response_type=code \
     -d redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection \
     -d scope=potential.track2.full.profile \
     -d code_challenge=${CODE_CHALLENGE} \
     -d code_challenge_method=S256
```

PAR エンドポイントは次のような JSON を応答として返します。成功した場合、JSON には `request_uri` プロパティが含まれています。
このプロパティの値は、事前登録された認可リクエストを表す**リクエスト URI** です。

```json theme={null}
{
  "expires_in": 600,
  "request_uri": "urn:ietf:params:oauth:request_uri:-CYpNdxTlS3S7e0PQKJVehPMnC0iiIk4pqJpD25k0Ws"
}
```

この例ではリクエスト URI の値は
`urn:ietf:params:oauth:request_uri:-CYpNdxTlS3S7e0PQKJVehPMnC0iiIk4pqJpD25k0Ws`
です。この値は認可リクエストの `request_uri` パラメーターの値として用いることになります。

##### 4.5.2.5. 手順 5 : 認可リクエスト

次の URL をあなたのウェブブラウザのアドレスバーに入力してください。
これは、認可サーバの認可エンドポイントへの認可リクエストです。
URL 内の `${REQUEST_URI}` を直前の手順で取得したリクエスト URI
の実際の値で置き換えることを忘れないでください。

```
https://trial.authlete.net/api/authorization?client_id=track2_full&request_uri=${REQUEST_URI}
```

認可エンドポイントは次のような認可ページを返します。ログイン ID とパスワードとして
`inga`、`inga` を入力し、続けて Authorize ボタンを押してください。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track2_full_authorization_page.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=44cf147f7136d1bc926416038ab894ec" alt="" width="720" height="880" data-path="protocols-and-flows/compliance-profiles/potential_track2_full_authorization_page.png" />

リダイレクションエンドポイント ([RFC 6749, 3.1.2][RFC_6749_3_1_2] 参照)
にリダイレクトされます。

<img src="https://mintcdn.com/authlete/U02sYmcLE8xIcCKt/protocols-and-flows/compliance-profiles/potential_track2_full_redirection_endpoint.png?fit=max&auto=format&n=U02sYmcLE8xIcCKt&q=85&s=9ef54d454beecfc5c8204f37c44a19e0" alt="" width="660" height="300" data-path="protocols-and-flows/compliance-profiles/potential_track2_full_redirection_endpoint.png" />

このリダイレクションエンドポイントは、受け取ったキー・バリューの組を表示します。
表示されている `code` パラメータの値が発行された**認可コード**です。
この例では、認可コードの値は
`yn1W7SLX9OEGqFZ2D986iPowVnoQtIRpPByBEyiIrBk`
です。

認可コードはのちほどトークンリクエストで使います。

##### 4.5.2.6. 手順 6 : トークンリクエスト用 DPoP Proof JWT

トークンエンドポイントにアクセスするため、新しい DPoP Proof JWT を作成する必要があります。
PAR リクエスト用に作成した DPoP Proof JWT を再利用することはできません。

次のコマンドにより DPoP Proof JWT を作成します。`-u` オプションの値が (PAR エンドポイントではなく)
トークンエンドポイントの URL であることに注意してください。

```shell theme={null}
./generate-dpop-proof -k dpop.jwk -m POST \
    -u https://trial.authlete.net/api/token
```

`generate-dpop-proof` スクリプトは次のような JWT を生成します。

```text theme={null}


eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiaEdmcXpHWGdhbzFRZ1ZJVFk2a2lIWU9LYmFMWEJ4VHFQSmE0RU9pbXhoSSIsInkiOiJFMUtpQV9mQTJ4OElycnlzb0dkbkJUTUI1LW8zRUpUX01nUUFfSG1HdTlNIn19.eyJqdGkiOiJFYzVhdklIcTN5Q25pUUFNIiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0L2FwaS90b2tlbiIsImlhdCI6MTcxOTQ3NTAxNX0.0ahIcVPSpMY-g-_SfkB8C84wDhalE1FLfobyDciBoFv16W82gMIuoBw3kDIhHmGJAxxOVKOyTQFKMi25c30vlw
```

この DPoP Proof JWT のヘッダとペイロードを base64url でデコードすると次のようになります。
`htu` クレームがトークンエンドポイントの URL を保持しています。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "Ec5avIHq3yCniQAM",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/token",
  "iat": 1719475015
}
```

##### 4.5.2.7. 手順 7 : トークンリクエスト

これまでの手順で次のものを用意しました。

* クライアントアテステーション (JWT)
* クライアントアテステーション PoP (JWT)
* トークンリクエスト用 DPoP Proof JWT (JWT)
* 認可コード
* コードベリファイア

これらを用い、次のようにトークンリクエストを実行できます。
コマンドライン内の変数をこれまでの手順で生成した実際の値で置き換えることを忘れないでください。

```shell theme={null}
curl -s https://trial.authlete.net/api/token \
     -H "OAuth-Client-Attestation: ${CLIENT_ATTESTATION}" \
     -H "OAuth-Client-Attestation-PoP: ${CLIENT_ATTESTATION_POP}" \
     -H "DPoP: ${DPOP_PROOF_JWT_FOR_TOKEN_REQUEST}" \
     -d client_id=track2_full \
     -d grant_type=authorization_code \
     -d code=${AUTHORIZATION_CODE} \
     -d redirect_uri=https://nextdev-api.authlete.net/api/mock/redirection \
     -d code_verifier=${CODE_VERIFIER}
```

トークンエンドポイントは応答として次のような JSON を返します。

```json theme={null}
{
  "access_token": "_aPAJGv3bnb8UoSbkBCP9XF0tnCHoLDGBc6chbFSWkg",
  "token_type": "DPoP",
  "expires_in": 86400,
  "scope": "potential.track2.full.profile",
  "refresh_token": "NPJv7yAu5YKT7a6qeWes4mL8exDx-bPruXDQE3p8u80",
  "c_nonce": "01bcC_9FtNM22wO9pnUqRkeFQuJNEE3sHA6M-oDnsHs",
  "c_nonce_expires_in": 86400
}
```

`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][OID4VCI_PR293]"
で導入された新しい機能を使います。この新しい機能は、一回のクレデンシャルリクエストで複数の
VC を発行することを可能にします。

複数の VC を要求するには、クレデンシャルリクエストに複数の鍵証明を含める必要があります。
そのため、ここでは、異なる保有者鍵を使って二つの JWT Key Proof を作ることにします。

[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリには、`holder.jwk` と `holder2.jwk`
という二つのデモ用保有者鍵が含まれています。これらの鍵と
`generate-key-proof` スクリプトを用い、次のように JWT Key Proof
を生成することができます。コマンドを実行する前に、コマンドライン内の `${C_NONCE}`
を先の手順で取得したトークンレスポンスに含まれる `c_nonce` プロパティの実際の値で置き換えてください。

```shell theme={null}
JWT_KEY_PROOF_1=`./generate-key-proof -i https://trial.authlete.net -k holder.jwk -c track2_full -n ${C_NONCE}`
JWT_KEY_PROOF_2=`./generate-key-proof -i https://trial.authlete.net -k holder2.jwk -c track2_full -n ${C_NONCE}`
```

<Note>
  トークンレスポンスの `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](https://www.rfc-editor.org/rfc/rfc6749.html) と衝突することになるでしょう。
</Note>

次のものは `holder.jwk` を用いた JWT Key Proof の例です。ヘッダ内の `jwk` クレームが
`holder.jwk` 内の秘密鍵に対応する公開鍵を保持していることに注目してください。

```text theme={null}


eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiUFN4UXJEMnpsMF9tWGNBcXoxbWdxU2VCb0Jobm14Mnl4QkVwckJZOEYyMCIsInkiOiJ4VjhmYmkxRlNvc1V1bkxldUxOdUxrSmlxbVk2VEtpTW51ci1HbjJ3UjEwIn19.eyJpc3MiOiJ0cmFjazJfZnVsbCIsImF1ZCI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0IiwiaWF0IjoxNzE5NDc2Mjg4LCJub25jZSI6IjAxYmNDXzlGdE5NMjJ3TzlwblVxUmtlRlF1Sk5FRTNzSEE2TS1vRG5zSHMifQ.lgI038MOL6DtbDnPOa8GZen0d2EoiZ-dgn_IU9hJYe5aWxL81hADNOS6v7ChJ9zxcU90sPDEJEyM12tDVm7VPQ
```

```json theme={null}
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
    "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
  }
}
```

```json theme={null}
{
  "iss": "track2_full",
  "aud": "https://trial.authlete.net",
  "iat": 1719476288,
  "nonce": "01bcC_9FtNM22wO9pnUqRkeFQuJNEE3sHA6M-oDnsHs"
}
```

同様に、次のものは `holder2.jwk` を用いた JWT Key Proof の例です。ヘッダ内の `jwk` クレームが
`holder2.jwk` 内の秘密鍵に対応する公開鍵を保持しています。

```text theme={null}


eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiSkotN2YwQXNRNWZJUmRxaDJySXoxSS02SkpBTUowQjUzM1Iybm8tRmtfQSIsInkiOiJ6LTFFZnc2ZmRoZ2RLVEZISVhOSDI5bV9UTlpjWUpDLUxDSVU2WWRQdFI4In19.eyJpc3MiOiJ0cmFjazJfZnVsbCIsImF1ZCI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0IiwiaWF0IjoxNzE5NDc2MzAwLCJub25jZSI6IjAxYmNDXzlGdE5NMjJ3TzlwblVxUmtlRlF1Sk5FRTNzSEE2TS1vRG5zSHMifQ.nNGWEYSDvH_B632TF_Z_ecG14fzmBR6QTjQS3Irjp5xiPLkHtm_XXGvKFeVLTc8erZpmWPvD_2e99DUvDsajyA
```

```json theme={null}
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "JJ-7f0AsQ5fIRdqh2rIz1I-6JJAMJ0B533R2no-Fk_A",
    "y": "z-1Efw6fdhgdKTFHIXNH29m_TNZcYJC-LCIU6YdPtR8"
  }
}
```

```json theme={null}
{
  "iss": "track2_full",
  "aud": "https://trial.authlete.net",
  "iat": 1719476300,
  "nonce": "01bcC_9FtNM22wO9pnUqRkeFQuJNEE3sHA6M-oDnsHs"
}
```

##### 4.5.2.9. 手順 9 : クレデンシャルリクエスト用 DPoP Proof JWT

クレデンシャルエンドポイントにアクセスするため、再度 DPoP Proof JWT を生成する必要があります。

`-u` オプションの値としてクレデンシャルエンドポイントの URL を指定することに加え、今回はアクセストークンの値を
`-a` オプション (`--at` オプションの短縮版) で指定する必要があります。このオプションは DPoP Key Proof に
`ath` クレームを含めるために必要です。

```shell theme={null}
./generate-dpop-proof -k dpop.jwk -m POST \
    -u https://trial.authlete.net/api/credential \
    -a ${ACCESS_TOKEN}
```

下記はクレデンシャルリクエスト用の DPoP Proof JWT の例です。ペイロードに `ath` クレームが含まれることに注目してください。
このクレームは、アクセストークンのハッシュ値を表しています。

```text theme={null}


eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoiaEdmcXpHWGdhbzFRZ1ZJVFk2a2lIWU9LYmFMWEJ4VHFQSmE0RU9pbXhoSSIsInkiOiJFMUtpQV9mQTJ4OElycnlzb0dkbkJUTUI1LW8zRUpUX01nUUFfSG1HdTlNIn19.eyJqdGkiOiI3Vm9zZW1YZ3ZLNUpVMVI0IiwiaHRtIjoiUE9TVCIsImh0dSI6Imh0dHBzOi8vdHJpYWwuYXV0aGxldGUubmV0L2FwaS9jcmVkZW50aWFsIiwiaWF0IjoxNzE5NDc2ODQxLCJhdGgiOiIzQWV6TzBZMTFnZzgwVm5Zd3puLUpDbXFNVnZkc2pJZXlBMTRoc1BOdHVvIn0.zDZYZdgb2jo4KKM0_OariZK0yrEcIFmPdpImX0Q-pttqw8480-nVdW-lQlQqQvcMtDKEWwZtgcNTsNExgomZ2g
```

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "hGfqzGXgao1QgVITY6kiHYOKbaLXBxTqPJa4EOimxhI",
    "y": "E1KiA_fA2x8IrrysoGdnBTMB5-o3EJT_MgQA_HmGu9M"
  }
}
```

```json theme={null}
{
  "jti": "7VosemXgvK5JU1R4",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/credential",
  "iat": 1719476841,
  "ath": "3AezO0Y11gg80VnYwzn-JCmqMVvdsjIeyA14hsPNtuo"
}
```

##### 4.5.2.10. 手順 10 : クレデンシャルリクエスト

ここまでの手順で次のものが用意できました。

* アクセストークン
* クレデンシャルリクエスト用 DPoP Proof JWT (JWT)
* JWT Key Proof 1 (JWT)
* JWT Key Proof 2 (JWT)

これらを用い、次のようにクレデンシャルリクエスト実行できます。

```shell theme={null}
curl -s https://trial.authlete.net/api/credential \
     -H "Authorization: Bearer ${ACCESS_TOKEN}" \
     -H "DPoP: ${DPOP_PROOF_JWT_FOR_CREDENTIAL_REQUEST}" \
     -H "Content-Type: application/json" \
       --data '{
  "format": "vc+sd-jwt",
  "vct": "urn:eu.europa.ec.eudi:pid:1",
  "proofs": {
    "jwt": [
      "'${JWT_KEY_PROOF_1}'",
      "'${JWT_KEY_PROOF_2}'"
    ]
  }
}'
```

ここでポイントとなるのは、クレデンシャルリクエストのメッセージボディが `proof` プロパティではなく
`proofs` プロパティを含んでいることです。この `proofs` プロパティは
[OpenID4VCI PR 293][OID4VCI_PR293] により新たに導入されたものであり、複数の鍵証明を含めることを可能にします。

クレデンシャルエンドポイントは次のような応答を返します。

```json theme={null}
{
  "credentials": [
    "eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJwbGFjZV9vZl9iaXJ0aCI6eyJfc2QiOlsiTkVXa1ZYODhqaENvMVVFZ0ZiTktQNjYyNkVhVXp6TldCRzdId1VZOFY4VSIsIlRfaUs3UG9ISDRfalNBWkdaMVljbXc2ckl2ZE1fM1pHTFpMV0JxUTZCOTgiXX0sIl9zZCI6WyItOWNGNnJ1TkFTRzdMX09ndEdTZlhSX0pDT1VmQ3pkVmF6dVB2RFFsV3FnIiwiMXdVMDdzdHR2NnBMN2FHal95YjJ5Z0tqVUFTeVZpLVk1cUxPcWgzN3ZPQSIsIjR1TF8taHhQTUpJTzVZdTdwTm4wbU95SEJBWjVsR0cwYWNhM2pZaG84cFUiLCI3dUZXV05vQURlTUpzVzFmcnhiVDV4czlHM3h4Qy0wSWRYTGV3RE5yWGxnIiwiOV82Y3hMMXNlRzUxRVdiZjlOcjFIZklpRTVpajdnWU9ONllxRXdqOGl5SSIsIjljWkJFUURYUTY2RGhqd1JPMUhzcXZOLVBLRHRuYW5BWlk2QW03aXUxMEkiLCJBTlRHcEZkaXk2cFpiXzdvb1pXQmQtVVlGUHR3ZDRiNDRXcW5WeGUxQjFBIiwiQkJTTU03ZXdYb2t3cVdSY1lDUmlLazJzbW1pNWdrM05NU21EMlpONnlTcyIsIlA4WG0zMUNUSXN3UzVTNlFyYkstc2tfc1dTUGMtZmJuWGM2c1VfMUpDRkUiLCJUckRwYVZxcnpSVWxfM0ktejE0SWtZdmxEZndTY2djbXI5Ui1maEZjcVhFIiwiZXpPREtNdkNGWW9ER2c0bWNLRFJ1VzJPemlMaml4VjRKRkNRS0Z6QnRsTSIsIm0yYmRpOHNPcEhRZTg1NTNhamJYQTNwakNTRzN0Qjh4T3VvaUN5eVlVYmMiLCJ1dG1yaWxSWGdTRHBsblFkdW5OUzZ2Ym8xOFB2cktsNnhEa2tzVFZ3YXVZIiwieEozS3NOam5faFl6aTNMWlZITDBoRklOWVdFM3EtZVJoRUdGRWVUQlBIOCJdLCJhZGRyZXNzIjp7Il9zZCI6WyIzUTFVdk1GbGl0VFYxM0EwN016ZjI3UzZfVW1Na2JEVFBfa0N3RklkTlJnIiwiQTgzNG9MTlY1dEVPb0c2eVMtRnRFM0FhalR0UF9GV1VhUXhBOWdHVXlnWSIsIkZRdG5MLXBaVkNRUUhRQ1Y3TVl6M0hwaUpOX1JIRmZObDlVSms3SGgwTUkiLCJHVWxzcjBpcUlMTVk1QXk4TnlZMzFiczNkd1NqdkZrd09aZHQxRlR1QndnIiwiSXk1TEFhLVEtNDhkMWN2d0VDN3VxYjBEMFR5VmxWX2l0dkhzck1KZE1UdyIsIkxzYlBzTGg4N0FiU3dwellYRmdTRnZZNHNFTFdZZXB2S0JzeVNBRWxhMXciLCJVZlE0QktRR2ZmZF9wU1VCYkd1RUJQM2d6Rm9zNU9sTFNvMUlxd1k0TWxJIiwiVjQtRTc2V1NKUjBuMU1xZHdsbElTTmoxaEtnRGc4d09qdElyam5rQ2tZZyIsIlhSZkNFZTVPcy1KcFM5OVFXY1pqRF9udXQ3d0Jwc0QzX1djWjZ1amhseDAiLCJpQ05YazdMLTQ3MnZnUmo2R0RDZ0RqWE5SUVBKaXM4amJTb3lRV09KRC1BIiwibkc5LUY4RDVPZWZZNmdLQmxVSU1WdFBaZXluX0FISGhmMzZIRzNmQ2tWNCIsInBYYlJTUTFfeFNUYUhIRjRhaFEzZFZPenQ1ODI3TkYxa0ZLUmtnUEd3cVUiXX0sInZjdCI6InVybjpldS5ldXJvcGEuZWMuZXVkaTpwaWQ6MSIsIl9zZF9hbGciOiJzaGEtMjU2IiwiaXNzIjoiaHR0cHM6Ly90cmlhbC5hdXRobGV0ZS5uZXQiLCJjbmYiOnsiandrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJraWQiOiI0TTlrSXJCOVdZenQxR1FnTDEybHpkQlpzR3llVjNsZ1BLb3YyOG9UNUw0IiwieCI6IlBTeFFyRDJ6bDBfbVhjQXF6MW1ncVNlQm9CaG5teDJ5eEJFcHJCWThGMjAiLCJ5IjoieFY4ZmJpMUZTb3NVdW5MZXVMTnVMa0ppcW1ZNlRLaU1udXItR24yd1IxMCJ9fSwiaWF0IjoxNzE5NDc2ODU1LCJhZ2VfZXF1YWxfb3Jfb3ZlciI6eyJfc2QiOlsiS1pPZzhDUENVWkI4Tl85ZC1YTVVvQ0tYQ2xTbEh3NHBiTmlFOEE4Mzk5ZyIsImZmZ2lfTmhVV0JWbVNiZ3J5WmtrMXpSdmhJNXJHQjFhd2diT2ZiRC1oZU0iXX19.dlnBVF7xd9uFbaUS0ExMHN-62uOnmzAmGSNOYJrP3jNNpV1ihmu02hdDTFEFuhhMQ2DXeKYG3mnbYZ4gjQogVw~WyJubFJHOFlwVXRyWlZybnZMaGsxVVNRIiwic3ViIiwiMTAwNCJd~WyJ1U0pTVHhqZHBKLVZKYzVJTTY3cHNnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJtWFg5ZHBLNHFZWC16WHRuczdnb2tnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJ0Q0NxOUNvWHJRTjJSY3FoY1dUTG9nIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~WyJlQU1BaG51QlAxQTY4Und3YU9YUU13IiwiMTgiLHRydWVd~WyJ0MVJ2YS1jeTVLQS0xT1hYQW93ZklRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyJpNXJNNDVZdjN1WHplRnZEekpxbjdnIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd~WyJvaFhiOVdFQTdHTmc0SEVrem9yVG5BIiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ~WyJFdmY1dkhCRFc4RmgzQk84SnZNOHR3IiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyIyZFJVWFBfajlIUF9nX1VFYTZRVkh3IiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd~WyJSbmNCeVBRdW5NbTNtb3hDRnVaOFpRIiwiY291bnRyeSIsIlVTQSJd~WyI1NmJLM1BKcG1wZ1kzdlA4WHNUYnZnIiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd~WyJjdXNabVM1MHVteUk3ZWc2SGhJYWNnIiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ~",
    "eyJraWQiOiJKMUZ3SlA4N0M2LVFOX1dTSU9tSkFRYzZuNUNRX2JaZGFGSjVHRG5XMVJrIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRVMyNTYifQ.eyJwbGFjZV9vZl9iaXJ0aCI6eyJfc2QiOlsiSXdtalFNd3ROTk9nVkJ5ZW5rYWYxemRyYnNSLWlsbFptN3pHNmFvem1NVSIsIlNxU25Rb0FnbWJqS3dkVzBNMDhvVnVfdktLLWk1bVA3RHNVNnlwdzFOenMiXX0sIl9zZCI6WyIzcXlKY0luTVRFOFZtb0FQdDVNUmNtdUREYXBUTF9BSmRHbGNxUzdJRVBFIiwiNkotbGQ5S3ktQ3hUSXhqbnlGNnYzX0JLajUyR01GQ3hndF9BSnZJTnNRVSIsIjZrY3dwdkRCZ05DVkUzM2RnUmd5YjJ1cERBNW45TUZhNS1ra1phSkZzZTQiLCJEWDRJT0hGVUVoVDZvNlNqTzVoUGZieUdPb3NmcC1HVjhNdmxkZnV2aXJZIiwiRWItMG1PRkNGWWViV2VPY3VNNmtQRWFpRFh4TnZETFBqcjkzbzNROUppcyIsIklLTzl5OEZ2TllpTGRpYUVwT0hBZWpYRGFYMVdXeVRPUnRUdnY3aUlTLU0iLCJJS1QwNGRxZ1NhM1B6aUlNZWRtU0NOWTl6MjRvcEEzRmh6LWUwbTdxV0VZIiwiSXlIemhjSDdpM3NkS182S0VJSWdDaVkzRWdDOVBUaU5zY1dpd1BGS3FHayIsIkpNeXg4QzRhakxVTzNLR3NTRDJobkMxcUJpSV80SThlc2QxZDNlcnNMU2siLCJTUUMzSUJDMlphVlBCZFU0QmYyZUZIcFVDUjJaRU1uZkFQUW1OMmVraWlvIiwiWEVJVmo4X2NXSjRBV1N3cTZWMlpOblA5Z3JfaVU1cUJkcGxTQXIwdC1JOCIsIlo0NXZjM19acUk2Uk1GN0xaaE5XZVp2YlIwRVA3NUNtLXdNcUVuSkdaVkEiLCJfRjZWTE56dTN3cVNTOHBRV1p5eXpOLVRybEZWX1h5LXp1WmNRbDFWd2NRIiwiYXl2UlVTdmc4a3N5Mnk0QjhGUk16NGxoTVdyWFRkcFVZT2p0aVlnVVFEUSIsImc4UjhhZnBRVERzZVFkZjZqbXJfTGNoVUxUc2V1enJ1SWxUVWllNFRXVjAiLCJnd2lwTUJESFRDanFsMHl0b1c2djdBUGo1Vm5sbVpMTWwyUlNYZVZTRXdJIiwiaEJ4UXhqT3QwQzN4SUpZYmNPaFJwU2Y5ajZjSm0wRTNoUU5WVFNPT3oyQSIsImw1UkZ5RVJRUHRFLUx6a2RFUGhXeXo0d215dzFGLU1RSTBBdjFIZER6NEUiLCJxNHZXNHRLNGQydS1vZHkybDNtNl9qYm14NVpTUmlVTzVHN0lwMTNOSjF3IiwidVhpTzQ3WFdXbEdQRGE2cS1zSk5Qc0R6THdXTGxpMTQyN2NQNkEzQzNIVSIsInlCb1B4aURuWjVhaWdJdjVZek9VMTEyQVdHT3BVaVNDRjNKZHgydjZEdDgiLCJ6T1E2alU3X094MDdxWXFJSjdvVzIxNmJiUWRzbXlfQXlHcTBpbW5ueUFjIl0sImFkZHJlc3MiOnsiX3NkIjpbIjJDdml3VXo1eEwwUllGc1BhSFlZeFVKVXgwY09vRFhCYUlsZnNvWHJoem8iLCI1NmswNWpXTmNaLUVwZ1loaDNjUnBESjhuSkVXOC04WnFvSWNyWFVicEFNIiwiN3d5cjd4MzlvMlN6Vjd0cmJ1SUN4d0xqTVBiaXdRdnU0eHVHN09sQUxpWSIsIkpsOEJveURITXkxeVpKQWEwRHliU0JzbUJSZ1hFVU9FUTQxb2xwS29uOHciLCJLc1h4c0JIWW9fb3dVa2J4VlVRT0ZjUHRoOWVqRG5BZzhjYVNXQVd4R2FJIiwiWXpsdWY0bTRMdGFoMEVzaGszQ0Y3aVMtcTJ0Um0yaVdfVXVZaWNtTzlLcyIsIm4talZaSEU2ZDN0ODVaQ1BXYTFOQm5KTVNFdDgweU9MMUphdFF1ZVhmd28iLCJvbUF4a2xVS3JyMk9sNW9nRlk2WGdJLVhtNHY2M1VrVmIxX09XYVhra0VRIiwid1dCa1dQZU1SdUdGM2I2S0drQnhyeGdZY2tqVzNxUERET3RyOVBOd0NiRSJdfSwidmN0IjoidXJuOmV1LmV1cm9wYS5lYy5ldWRpOnBpZDoxIiwiX3NkX2FsZyI6InNoYS0yNTYiLCJpc3MiOiJodHRwczovL3RyaWFsLmF1dGhsZXRlLm5ldCIsImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsImtpZCI6IkI4b3M4ZE5CTTF2aU9OWU96T0hmUEtKd3AzU0dsTVlLU05BQ1NXdVpScXMiLCJ4IjoiSkotN2YwQXNRNWZJUmRxaDJySXoxSS02SkpBTUowQjUzM1Iybm8tRmtfQSIsInkiOiJ6LTFFZnc2ZmRoZ2RLVEZISVhOSDI5bV9UTlpjWUpDLUxDSVU2WWRQdFI4In19LCJpYXQiOjE3MTk0NzY4NTUsImFnZV9lcXVhbF9vcl9vdmVyIjp7Il9zZCI6WyJJOEdHR2VXQXJFRzAwUHFiNV9qZkJnMGhYRndET1k5aTRnbU9ZTGp1OS1ZIiwidUhmbDRiZ00wV2I2YTBWSHUzWWx0YU1mSGR1TXZIbzIyMVVBUUJkMDhYVSJdfX0.oI6tgincnKaRqACfYe46PweL1kvbrbjJcnwKnBtGDpUfWbvRTj2B8pn4JWVQ2XPBDEnAJaeO0tJ7B1U1infWMA~WyJBMFYzTDlwdzQ3U1BfSk5XYTVFOGhBIiwic3ViIiwiMTAwNCJd~WyJLZy1VTFN4N2JlOGRlYm5yMngyVjRnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJZLUVCUkw0OTJyUm54T3BGaWtUOE1BIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJreUFTdHg1SWNUaXVfQ3RNdTBDck5RIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~WyI4WGJCNGRRZENZbkh6a3BuR094YU1RIiwiMTgiLHRydWVd~WyJYM0RBUHdFWTRGaEQ2UUNNSU5idXBnIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyJ3SDhKTE5tc1dkcVdfZ3Q3RmtQbGpRIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd~WyJEVUJaRXNkWVVPREhoZTJ3TUxFMnpBIiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ~WyJ6dXQzd0pnbjN1MExCcTJRNTlXZEFRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd~WyJsVzdXQTkxakRON1RGWkpRRzJNUi1BIiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd~WyJlczdiUHpNeXdNaXJON0tzemtpMFdRIiwiY291bnRyeSIsIlVTQSJd~WyJtOEVlUUM2akhIeUlSWGVDQXhERi1nIiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd~WyIxMzhhaHkwMVdvNFFxekZyNFlpSld3IiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ~"
  ],
  "c_nonce": "01bcC_9FtNM22wO9pnUqRkeFQuJNEE3sHA6M-oDnsHs",
  "c_nonce_expires_in": 84589
}
```

成功時、応答には `credential` プロパティではなく `credentials` プロパティが含まれます。
`credentials` 配列内の要素は発行された VC です。この例では、クレデンシャルリクエストが
2 つの鍵証明を含んでいたので、`credentials` 配列は二つの VC を含んでいます。

VC のフォーマットは SD-JWT です。[oid4vci-demo][AUTHLETE_OID4VCI_DEMO] レポジトリにある
`decode-sd-jwt` スクリプトを用いて、これらの VC をデコードすることができます。

一番目の VC をデコードすると次のようになります。

```json theme={null}
{
  "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
  "typ": "vc+sd-jwt",
  "alg": "ES256"
}
{
  "place_of_birth": {
    "_sd": [
      "NEWkVX88jhCo1UEgFbNKP6626EaUzzNWBG7HwUY8V8U",
      "T_iK7PoHH4_jSAZGZ1Ycmw6rIvdM_3ZGLZLWBqQ6B98"
    ]
  },
  "_sd": [
    "-9cF6ruNASG7L_OgtGSfXR_JCOUfCzdVazuPvDQlWqg",
    "1wU07sttv6pL7aGj_yb2ygKjUASyVi-Y5qLOqh37vOA",
    "4uL_-hxPMJIO5Yu7pNn0mOyHBAZ5lGG0aca3jYho8pU",
    "7uFWWNoADeMJsW1frxbT5xs9G3xxC-0IdXLewDNrXlg",
    "9_6cxL1seG51EWbf9Nr1HfIiE5ij7gYON6YqEwj8iyI",
    "9cZBEQDXQ66DhjwRO1HsqvN-PKDtnanAZY6Am7iu10I",
    "ANTGpFdiy6pZb_7ooZWBd-UYFPtwd4b44WqnVxe1B1A",
    "BBSMM7ewXokwqWRcYCRiKk2smmi5gk3NMSmD2ZN6ySs",
    "P8Xm31CTIswS5S6QrbK-sk_sWSPc-fbnXc6sU_1JCFE",
    "TrDpaVqrzRUl_3I-z14IkYvlDfwScgcmr9R-fhFcqXE",
    "ezODKMvCFYoDGg4mcKDRuW2OziLjixV4JFCQKFzBtlM",
    "m2bdi8sOpHQe8553ajbXA3pjCSG3tB8xOuoiCyyYUbc",
    "utmrilRXgSDplnQdunNS6vbo18PvrKl6xDkksTVwauY",
    "xJ3KsNjn_hYzi3LZVHL0hFINYWE3q-eRhEGFEeTBPH8"
  ],
  "address": {
    "_sd": [
      "3Q1UvMFlitTV13A07Mzf27S6_UmMkbDTP_kCwFIdNRg",
      "A834oLNV5tEOoG6yS-FtE3AajTtP_FWUaQxA9gGUygY",
      "FQtnL-pZVCQQHQCV7MYz3HpiJN_RHFfNl9UJk7Hh0MI",
      "GUlsr0iqILMY5Ay8NyY31bs3dwSjvFkwOZdt1FTuBwg",
      "Iy5LAa-Q-48d1cvwEC7uqb0D0TyVlV_itvHsrMJdMTw",
      "LsbPsLh87AbSwpzYXFgSFvY4sELWYepvKBsySAEla1w",
      "UfQ4BKQGffd_pSUBbGuEBP3gzFos5OlLSo1IqwY4MlI",
      "V4-E76WSJR0n1MqdwllISNj1hKgDg8wOjtIrjnkCkYg",
      "XRfCEe5Os-JpS99QWcZjD_nut7wBpsD3_WcZ6ujhlx0",
      "iCNXk7L-472vgRj6GDCgDjXNRQPJis8jbSoyQWOJD-A",
      "nG9-F8D5OefY6gKBlUIMVtPZeyn_AHHhf36HG3fCkV4",
      "pXbRSQ1_xSTaHHF4ahQ3dVOzt5827NF1kFKRkgPGwqU"
    ]
  },
  "vct": "urn:eu.europa.ec.eudi:pid:1",
  "_sd_alg": "sha-256",
  "iss": "https://trial.authlete.net",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "kid": "4M9kIrB9WYzt1GQgL12lzdBZsGyeV3lgPKov28oT5L4",
      "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
      "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
    }
  },
  "iat": 1719476855,
  "age_equal_or_over": {
    "_sd": [
      "KZOg8CPCUZB8N_9d-XMUoCKXClSlHw4pbNiE8A8399g",
      "ffgi_NhUWBVmSbgryZkk1zRvhI5rGB1awgbOfbD-heM"
    ]
  }
}
{
  "digest": "4uL_-hxPMJIO5Yu7pNn0mOyHBAZ5lGG0aca3jYho8pU",
  "WyJubFJHOFlwVXRyWlZybnZMaGsxVVNRIiwic3ViIiwiMTAwNCJd": [
    "nlRG8YpUtrZVrnvLhk1USQ",
    "sub",
    "1004"
  ]
}
{
  "digest": "9_6cxL1seG51EWbf9Nr1HfIiE5ij7gYON6YqEwj8iyI",
  "WyJ1U0pTVHhqZHBKLVZKYzVJTTY3cHNnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd": [
    "uSJSTxjdpJ-VJc5IM67psg",
    "family_name",
    "Silverstone"
  ]
}
{
  "digest": "m2bdi8sOpHQe8553ajbXA3pjCSG3tB8xOuoiCyyYUbc",
  "WyJtWFg5ZHBLNHFZWC16WHRuczdnb2tnIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ": [
    "mXX9dpK4qYX-zXtns7gokg",
    "given_name",
    "Inga"
  ]
}
{
  "digest": "BBSMM7ewXokwqWRcYCRiKk2smmi5gk3NMSmD2ZN6ySs",
  "WyJ0Q0NxOUNvWHJRTjJSY3FoY1dUTG9nIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd": [
    "tCCq9CoXrQN2RcqhcWTLog",
    "birthdate",
    "1991-11-06"
  ]
}
{
  "digest": "KZOg8CPCUZB8N_9d-XMUoCKXClSlHw4pbNiE8A8399g",
  "WyJlQU1BaG51QlAxQTY4Und3YU9YUU13IiwiMTgiLHRydWVd": [
    "eAMAhnuBP1A68RwwaOXQMw",
    "18",
    true
  ]
}
{
  "digest": "T_iK7PoHH4_jSAZGZ1Ycmw6rIvdM_3ZGLZLWBqQ6B98",
  "WyJ0MVJ2YS1jeTVLQS0xT1hYQW93ZklRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "t1Rva-cy5KA-1OXXAowfIQ",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "V4-E76WSJR0n1MqdwllISNj1hKgDg8wOjtIrjnkCkYg",
  "WyJpNXJNNDVZdjN1WHplRnZEekpxbjdnIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd": [
    "i5rM45Yv3uXzeFvDzJqn7g",
    "formatted",
    "114 Old State Hwy 127, Shoshone, CA 92384, USA"
  ]
}
{
  "digest": "nG9-F8D5OefY6gKBlUIMVtPZeyn_AHHhf36HG3fCkV4",
  "WyJvaFhiOVdFQTdHTmc0SEVrem9yVG5BIiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ": [
    "ohXb9WEA7GNg4HEkzorTnA",
    "street_address",
    "114 Old State Hwy 127"
  ]
}
{
  "digest": "GUlsr0iqILMY5Ay8NyY31bs3dwSjvFkwOZdt1FTuBwg",
  "WyJFdmY1dkhCRFc4RmgzQk84SnZNOHR3IiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "Evf5vHBDW8Fh3BO8JvM8tw",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "LsbPsLh87AbSwpzYXFgSFvY4sELWYepvKBsySAEla1w",
  "WyIyZFJVWFBfajlIUF9nX1VFYTZRVkh3IiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd": [
    "2dRUXP_j9HP_g_UEa6QVHw",
    "postal_code",
    "CA 92384"
  ]
}
{
  "digest": "XRfCEe5Os-JpS99QWcZjD_nut7wBpsD3_WcZ6ujhlx0",
  "WyJSbmNCeVBRdW5NbTNtb3hDRnVaOFpRIiwiY291bnRyeSIsIlVTQSJd": [
    "RncByPQunMm3moxCFuZ8ZQ",
    "country",
    "USA"
  ]
}
{
  "digest": "utmrilRXgSDplnQdunNS6vbo18PvrKl6xDkksTVwauY",
  "WyI1NmJLM1BKcG1wZ1kzdlA4WHNUYnZnIiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd": [
    "56bK3PJpmpgY3vP8XsTbvg",
    "issuing_authority",
    "US"
  ]
}
{
  "digest": "ezODKMvCFYoDGg4mcKDRuW2OziLjixV4JFCQKFzBtlM",
  "WyJjdXNabVM1MHVteUk3ZWc2SGhJYWNnIiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ": [
    "cusZmS50umyI7eg6HhIacg",
    "issuing_country",
    "US"
  ]
}
```

ここでポイントとなるのは、`cnf.jwk` プロパティの値が一番目の鍵証明に埋め込まれている公開鍵と合致することです。

```json theme={null}
"cnf": {
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "kid": "4M9kIrB9WYzt1GQgL12lzdBZsGyeV3lgPKov28oT5L4",
    "x": "PSxQrD2zl0_mXcAqz1mgqSeBoBhnmx2yxBEprBY8F20",
    "y": "xV8fbi1FSosUunLeuLNuLkJiqmY6TKiMnur-Gn2wR10"
  }
}
```

同様に、二番目の VC をデコードすると次のようになります。

```json theme={null}
{
  "kid": "J1FwJP87C6-QN_WSIOmJAQc6n5CQ_bZdaFJ5GDnW1Rk",
  "typ": "vc+sd-jwt",
  "alg": "ES256"
}
{
  "place_of_birth": {
    "_sd": [
      "IwmjQMwtNNOgVByenkaf1zdrbsR-illZm7zG6aozmMU",
      "SqSnQoAgmbjKwdW0M08oVu_vKK-i5mP7DsU6ypw1Nzs"
    ]
  },
  "_sd": [
    "3qyJcInMTE8VmoAPt5MRcmuDDapTL_AJdGlcqS7IEPE",
    "6J-ld9Ky-CxTIxjnyF6v3_BKj52GMFCxgt_AJvINsQU",
    "6kcwpvDBgNCVE33dgRgyb2upDA5n9MFa5-kkZaJFse4",
    "DX4IOHFUEhT6o6SjO5hPfbyGOosfp-GV8MvldfuvirY",
    "Eb-0mOFCFYebWeOcuM6kPEaiDXxNvDLPjr93o3Q9Jis",
    "IKO9y8FvNYiLdiaEpOHAejXDaX1WWyTORtTvv7iIS-M",
    "IKT04dqgSa3PziIMedmSCNY9z24opA3Fhz-e0m7qWEY",
    "IyHzhcH7i3sdK_6KEIIgCiY3EgC9PTiNscWiwPFKqGk",
    "JMyx8C4ajLUO3KGsSD2hnC1qBiI_4I8esd1d3ersLSk",
    "SQC3IBC2ZaVPBdU4Bf2eFHpUCR2ZEMnfAPQmN2ekiio",
    "XEIVj8_cWJ4AWSwq6V2ZNnP9gr_iU5qBdplSAr0t-I8",
    "Z45vc3_ZqI6RMF7LZhNWeZvbR0EP75Cm-wMqEnJGZVA",
    "_F6VLNzu3wqSS8pQWZyyzN-TrlFV_Xy-zuZcQl1VwcQ",
    "ayvRUSvg8ksy2y4B8FRMz4lhMWrXTdpUYOjtiYgUQDQ",
    "g8R8afpQTDseQdf6jmr_LchULTseuzruIlTUie4TWV0",
    "gwipMBDHTCjql0ytoW6v7APj5VnlmZLMl2RSXeVSEwI",
    "hBxQxjOt0C3xIJYbcOhRpSf9j6cJm0E3hQNVTSOOz2A",
    "l5RFyERQPtE-LzkdEPhWyz4wmyw1F-MQI0Av1HdDz4E",
    "q4vW4tK4d2u-ody2l3m6_jbmx5ZSRiUO5G7Ip13NJ1w",
    "uXiO47XWWlGPDa6q-sJNPsDzLwWLli1427cP6A3C3HU",
    "yBoPxiDnZ5aigIv5YzOU112AWGOpUiSCF3Jdx2v6Dt8",
    "zOQ6jU7_Ox07qYqIJ7oW216bbQdsmy_AyGq0imnnyAc"
  ],
  "address": {
    "_sd": [
      "2CviwUz5xL0RYFsPaHYYxUJUx0cOoDXBaIlfsoXrhzo",
      "56k05jWNcZ-EpgYhh3cRpDJ8nJEW8-8ZqoIcrXUbpAM",
      "7wyr7x39o2SzV7trbuICxwLjMPbiwQvu4xuG7OlALiY",
      "Jl8BoyDHMy1yZJAa0DybSBsmBRgXEUOEQ41olpKon8w",
      "KsXxsBHYo_owUkbxVUQOFcPth9ejDnAg8caSWAWxGaI",
      "Yzluf4m4Ltah0Eshk3CF7iS-q2tRm2iW_UuYicmO9Ks",
      "n-jVZHE6d3t85ZCPWa1NBnJMSEt80yOL1JatQueXfwo",
      "omAxklUKrr2Ol5ogFY6XgI-Xm4v63UkVb1_OWaXkkEQ",
      "wWBkWPeMRuGF3b6KGkBxrxgYckjW3qPDDOtr9PNwCbE"
    ]
  },
  "vct": "urn:eu.europa.ec.eudi:pid:1",
  "_sd_alg": "sha-256",
  "iss": "https://trial.authlete.net",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "kid": "B8os8dNBM1viONYOzOHfPKJwp3SGlMYKSNACSWuZRqs",
      "x": "JJ-7f0AsQ5fIRdqh2rIz1I-6JJAMJ0B533R2no-Fk_A",
      "y": "z-1Efw6fdhgdKTFHIXNH29m_TNZcYJC-LCIU6YdPtR8"
    }
  },
  "iat": 1719476855,
  "age_equal_or_over": {
    "_sd": [
      "I8GGGeWArEG00Pqb5_jfBg0hXFwDOY9i4gmOYLju9-Y",
      "uHfl4bgM0Wb6a0VHu3YltaMfHduMvHo221UAQBd08XU"
    ]
  }
}
{
  "digest": "l5RFyERQPtE-LzkdEPhWyz4wmyw1F-MQI0Av1HdDz4E",
  "WyJBMFYzTDlwdzQ3U1BfSk5XYTVFOGhBIiwic3ViIiwiMTAwNCJd": [
    "A0V3L9pw47SP_JNWa5E8hA",
    "sub",
    "1004"
  ]
}
{
  "digest": "IKT04dqgSa3PziIMedmSCNY9z24opA3Fhz-e0m7qWEY",
  "WyJLZy1VTFN4N2JlOGRlYm5yMngyVjRnIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd": [
    "Kg-ULSx7be8debnr2x2V4g",
    "family_name",
    "Silverstone"
  ]
}
{
  "digest": "uXiO47XWWlGPDa6q-sJNPsDzLwWLli1427cP6A3C3HU",
  "WyJZLUVCUkw0OTJyUm54T3BGaWtUOE1BIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ": [
    "Y-EBRL492rRnxOpFikT8MA",
    "given_name",
    "Inga"
  ]
}
{
  "digest": "zOQ6jU7_Ox07qYqIJ7oW216bbQdsmy_AyGq0imnnyAc",
  "WyJreUFTdHg1SWNUaXVfQ3RNdTBDck5RIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd": [
    "kyAStx5IcTiu_CtMu0CrNQ",
    "birthdate",
    "1991-11-06"
  ]
}
{
  "digest": "uHfl4bgM0Wb6a0VHu3YltaMfHduMvHo221UAQBd08XU",
  "WyI4WGJCNGRRZENZbkh6a3BuR094YU1RIiwiMTgiLHRydWVd": [
    "8XbB4dQdCYnHzkpnGOxaMQ",
    "18",
    true
  ]
}
{
  "digest": "IwmjQMwtNNOgVByenkaf1zdrbsR-illZm7zG6aozmMU",
  "WyJYM0RBUHdFWTRGaEQ2UUNNSU5idXBnIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "X3DAPwEY4FhD6QCMINbupg",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "7wyr7x39o2SzV7trbuICxwLjMPbiwQvu4xuG7OlALiY",
  "WyJ3SDhKTE5tc1dkcVdfZ3Q3RmtQbGpRIiwiZm9ybWF0dGVkIiwiMTE0IE9sZCBTdGF0ZSBId3kgMTI3LCBTaG9zaG9uZSwgQ0EgOTIzODQsIFVTQSJd": [
    "wH8JLNmsWdqW_gt7FkPljQ",
    "formatted",
    "114 Old State Hwy 127, Shoshone, CA 92384, USA"
  ]
}
{
  "digest": "Jl8BoyDHMy1yZJAa0DybSBsmBRgXEUOEQ41olpKon8w",
  "WyJEVUJaRXNkWVVPREhoZTJ3TUxFMnpBIiwic3RyZWV0X2FkZHJlc3MiLCIxMTQgT2xkIFN0YXRlIEh3eSAxMjciXQ": [
    "DUBZEsdYUODHhe2wMLE2zA",
    "street_address",
    "114 Old State Hwy 127"
  ]
}
{
  "digest": "wWBkWPeMRuGF3b6KGkBxrxgYckjW3qPDDOtr9PNwCbE",
  "WyJ6dXQzd0pnbjN1MExCcTJRNTlXZEFRIiwibG9jYWxpdHkiLCJTaG9zaG9uZSJd": [
    "zut3wJgn3u0LBq2Q59WdAQ",
    "locality",
    "Shoshone"
  ]
}
{
  "digest": "n-jVZHE6d3t85ZCPWa1NBnJMSEt80yOL1JatQueXfwo",
  "WyJsVzdXQTkxakRON1RGWkpRRzJNUi1BIiwicG9zdGFsX2NvZGUiLCJDQSA5MjM4NCJd": [
    "lW7WA91jDN7TFZJQG2MR-A",
    "postal_code",
    "CA 92384"
  ]
}
{
  "digest": "Yzluf4m4Ltah0Eshk3CF7iS-q2tRm2iW_UuYicmO9Ks",
  "WyJlczdiUHpNeXdNaXJON0tzemtpMFdRIiwiY291bnRyeSIsIlVTQSJd": [
    "es7bPzMywMirN7Kszki0WQ",
    "country",
    "USA"
  ]
}
{
  "digest": "IyHzhcH7i3sdK_6KEIIgCiY3EgC9PTiNscWiwPFKqGk",
  "WyJtOEVlUUM2akhIeUlSWGVDQXhERi1nIiwiaXNzdWluZ19hdXRob3JpdHkiLCJVUyJd": [
    "m8EeQC6jHHyIRXeCAxDF-g",
    "issuing_authority",
    "US"
  ]
}
{
  "digest": "6J-ld9Ky-CxTIxjnyF6v3_BKj52GMFCxgt_AJvINsQU",
  "WyIxMzhhaHkwMVdvNFFxekZyNFlpSld3IiwiaXNzdWluZ19jb3VudHJ5IiwiVVMiXQ": [
    "138ahy01Wo4QqzFr4YiJWw",
    "issuing_country",
    "US"
  ]
}
```

二番目の VC の `cnf.jwk` プロパティが二番目の鍵証明に埋め込まれた公開鍵に合致することを確認できます。

```json theme={null}
"cnf": {
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "kid": "B8os8dNBM1viONYOzOHfPKJwp3SGlMYKSNACSWuZRqs",
    "x": "JJ-7f0AsQ5fIRdqh2rIz1I-6JJAMJ0B533R2no-Fk_A",
    "y": "z-1Efw6fdhgdKTFHIXNH29m_TNZcYJC-LCIU6YdPtR8"
  }
}
```

[RFC_6749]: https://www.rfc-editor.org/rfc/rfc6749.html

[RFC_6749_3_1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-3.1

[RFC_6749_3_1_2]: https://www.rfc-editor.org/rfc/rfc6749.html#section-3.1.2

[RFC_6749_3_2]: https://www.rfc-editor.org/rfc/rfc6749.html#section-3.2

[RFC_6749_4_1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1

[RFC_7515_4_1_3]: https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.3

[RFC_7515_4_1_4]: https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.4

[RFC_7515_4_1_6]: https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.6

[RFC_7517]: https://www.rfc-editor.org/rfc/rfc7517.html

[RFC_7519]: https://www.rfc-editor.org/rfc/rfc7519.html

[RFC_7519_4_1_6]: https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.6

[RFC_7636]: https://www.rfc-editor.org/rfc/rfc7636.html

[RFC_8392]: https://www.rfc-editor.org/rfc/rfc8392.html

[RFC_8610_G]: https://www.rfc-editor.org/rfc/rfc8610#appendix-G

[RFC_8949]: https://www.rfc-editor.org/rfc/rfc8949.html

[RFC_8949_8]: https://www.rfc-editor.org/rfc/rfc8949#section-8

[RFC_9052]: https://www.rfc-editor.org/rfc/rfc9052.html

[RFC_9053]: https://www.rfc-editor.org/rfc/rfc9053.html

[RFC_9126]: https://www.rfc-editor.org/rfc/rfc9126.html

[RFC_9396]: https://www.rfc-editor.org/rfc/rfc9396.html

[RFC_9449]: https://www.rfc-editor.org/rfc/rfc9449.html

[W3C_DATA_INTEGRITY]: https://w3c.github.io/vc-data-integrity/

[W3C_DID_DID_URL]: https://www.w3.org/TR/did-core/#dfn-did-urls

[W3C_JOSE_COSE]: https://w3c.github.io/vc-jose-cose/

[W3C_JOSE_COSE_REPO]: https://github.com/w3c/vc-jose-cose

[W3C_VCDM]: https://www.w3.org/TR/vc-data-model/

[W3C_VCDM_1_1]: https://www.w3.org/TR/vc-data-model-1.1/

[W3C_VCDM_2_0]: https://www.w3.org/TR/vc-data-model-2.0/

[ISO_IEC_18013_5]: https://www.iso.org/standard/69084.html

[IANA_COSE]: https://www.iana.org/assignments/cose/cose.xhtml

[OID4VCI]: https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html

[OID4VCI_PR293]: https://github.com/openid/OpenID4VCI/pull/293

[OIDFED]: https://openid.net/specs/openid-federation-1_0.html

[ATTESTATION_BASED_CLIENT_AUTH]: https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth/

[AUTHLETE_CBOR]: https://github.com/authlete/cbor

[AUTHLETE_JAVA_COMMON]: https://github.com/authlete/authlete-java-common

[AUTHLETE_JAVA_COMMON_JAVADOC]: https://authlete.github.io/authlete-java-common/

[AUTHLETE_OID4VCI_DEMO]: https://github.com/authlete/oid4vci-demo

[AUTHLETE_SD_JWT]: https://github.com/authlete/sd-jwt

[CBOR_ZONE]: https://cbor.zone/

[CLIENT_AUTHENTICATION]: https://medium.com/@darutk/oauth-2-0-client-authentication-4b5f929305d4

[CONTACT_US]: https://www.authlete.com/ja/contact/

[CREDENTIAL_PROFILE_COMPARISON]: https://github.com/vcstuff/credential-profile-comparison

[HAIP]: https://vcstuff.github.io/oid4vc-haip-sd-jwt-vc/draft-oid4vc-haip-sd-jwt-vc.html

[JAVA_OAUTH_SERVER]: https://github.com/authlete/java-oauth-server

[POTENTIAL]: https://www.digital-identity-wallet.eu/

[SD_JWT]: https://datatracker.ietf.org/doc/draft-ietf-oauth-selective-disclosure-jwt/

[SD_JWT_VC]: https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/

[CredentialSingleIssueRequest]: https://authlete.github.io/authlete-java-common/com/authlete/common/dto/CredentialSingleIssueRequest.html

[CredentialSingleParseResponse]: https://authlete.github.io/authlete-java-common/com/authlete/common/dto/CredentialSingleParseResponse.html

[IntrospectionResponse]: https://authlete.github.io/authlete-java-common/com/authlete/common/dto/IntrospectionResponse.html
