> ## 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.

# HAIP 準拠 VC 発行

> OpenID4VC High Assurance Interoperability Profile 1.0 (HAIP) に準拠する Verifiable Credential (VC) 発行手順に関する解説です。

## はじめに

本記事では **[OpenID4VC High Assurance Interoperability Profile 1.0][HAIP]**
(以降 **HAIP**（ハイプ）) に準拠する
**Verifiable Credential** (以降 **VC**) 発行手順について解説します。

<br />

## 仕様の要点

VC 発行手順に関しては、HAIP は概ね
**[OpenID for Verifiable Credential Issuance 1.0][OID4VCI]**
(以降 **OID4VCI**) と
**[FAPI 2.0 Security Profile][FAPI2SP]**
(以降 **FAPI2SP**) を組み合わせたものだと言えます。
ただし、留意すべき差分があるので、主要なものについて紹介します。

<br />

### 送信者限定アクセストークン

FAPI2SP では、**送信者限定アクセストークン**を実現する方法として次のものが利用可能です。

* **MTLS** ([RFC 8705][RFC_8705])
* **DPoP** ([RFC 9449][RFC_9449])

一方、HAIP で許可されるのは DPoP のみです。

<br />

### クライアント認証

FAPI2SP では、**クライアント認証**方式として次のものが利用可能です。

* `tls_client_auth` ([RFC 8705][RFC_8705])
* `self_signed_tls_client_auth` ([RFC 8705][RFC_8705])
* `private_key_jwt` ([RFC 7523][RFC_7523])

HAIP では、これらに加えて
**[OAuth 2.0 Attestation-Based Client Authentication][ABCA]**
(以降 **ABCA**) も利用可能です。

* `attest_jwt_client_auth` ([ABCA][ABCA])

なお、HAIP の文脈で ABCA を利用する場合、**クライアント・アテステーション**は
`x5c` ヘッダパラメーターを含まなければなりません。
また、署名検証用公開鍵を含む X.509 証明書 (証明書チェーンの先頭の証明書)
は、自己署名証明書であってはなりません。

<Note>
  HAIP 仕様を字句通りに解釈すると、ABCA 以外のクライアント認証方式も利用可能です。
  しかし、HAIP 仕様の議論は ABCA の利用を前提として進められているように見受けられので、HAIP
  仕様がその考えを反映するように変更される (「ABCA のみを許可する」と仕様変更される)
  可能性があるため、本記事ではクライアント認証として ABCA を使います。
</Note>

<br />

### キー・アテステーション

OID4VCI は、クレデンシャルリクエストに含める**鍵証明**のフォーマットを幾つか定義しています。
これらのうち、jwt Proof Type ([OID4VCI Appendix F.1][OID4VCI_F1])
では、`key_attestation` ヘッダパラメーターに**キー・アテステーション**
([OID4VCI Appendix D][OID4VCI_D]) を指定することができます。
また、attestation Proof Type ([OID4VCI Appendix F.3][OID4VCI_F3])
では、キー・アテステーションそのものを鍵証明として指定します。

HAIP の文脈でキー・アテステーションを用いる場合、それらは `x5c`
ヘッダパラメーターを含まなければなりません。
また、署名検証用公開鍵を含む X.509 証明書 (証明書チェーンの先頭の証明書)
は、自己署名証明書であってはなりません。

<br />

### スコープ

一般的に、アクセストークンは一つ以上のスコープと紐付いています。
HAIP の文脈では、それらのスコープの中に、特定のクレデンシャル設定を指すものが含まれていなければなりません。

具体的には、クレデンシャル・イシュア・メタデータの
`credential_configurations_supported`
に列挙されているクレデンシャル設定群の、どれか一つ以上のクレデンシャル設定の
`scope` プロパティーの値が、アクセストークンに紐付いている必要があります。

<br />

## 手順の概要

認可コードフローによる VC 発行手順の概要は下記の通りです。

1. PAR リクエスト
2. 認可リクエスト
3. トークンリクエスト
4. クレデンシャルリクエスト

しかし、それぞれのリクエストが様々なトークン群を要求するため、実際の手順はより複雑になります。
下記は、トークン群の生成も含めた手順の概要を示しています。

1. PAR リクエスト
   * PKCE トークン (コード・ベリファイアとコード・チャレンジ) 生成 ([PKCE][RFC_7636])
   * クライアント・アテステーション生成 ([ABCA][ABCA])
   * アテステーション・チャレンジ取得 ([ABCA][ABCA])
   * クライアント・アテステーション・PoP 生成 ([ABCA][ABCA])
   * DPoP Proof JWT 生成 ([DPoP][RFC_9449])
   * PAR リクエスト送信 ([PAR][RFC_9126])
2. 認可リクエスト
   * 認可リクエスト送信
3. トークンリクエスト
   * クライアント・アテステーション生成 ([ABCA][ABCA]) (再利用可)
   * アテステーション・チャレンジ取得 ([ABCA][ABCA]) (再利用可)
   * クライアント・アテステーション・PoP 生成 ([ABCA][ABCA]) (再利用可)
   * DPoP Proof JWT 生成 ([DPoP][RFC_9449])
   * トークンリクエスト送信
4. クレデンシャルリクエスト
   * ノンス取得 ([OID4VCI][OID4VCI])
   * キー・アテステーション生成 ([OID4VCI][OID4VCI])
   * 鍵証明生成 ([OID4VCI][OID4VCI])
   * DPoP Proof JWT 生成 ([DPoP][RFC_9449])
   * クレデンシャルリクエスト送信 ([OID4VCI][OID4VCI])

<br />

## 実際の手順

このセクションでは、実際の手順をみていきます。

なお、トークン群の生成に用いるスクリプト群や秘密鍵・公開鍵・証明書については、[authlete/oid4vci-demo][OID4VCI_DEMO]
で公開しているものを利用します。

<br />

### PAR リクエスト

<img alt="" class="mx-auto d-block" src="https://mintcdn.com/authlete/WGQFc11Y4wUplGrc/ja/protocols-and-flows/advanced-flows/haip-compliant_par_request.png?fit=max&auto=format&n=WGQFc11Y4wUplGrc&q=85&s=8625a39ffd62581f7cd0d1653c99e5f4" width="1920" height="1080" data-path="ja/protocols-and-flows/advanced-flows/haip-compliant_par_request.png" />

HAIP は FAPI2SP をベースとしており、FAPI2SP が [PAR][RFC_9126]
を必須としているため、HAIP 準拠の認可リクエストでも PAR の利用が必須となります。
ここでは、PAR エンドポイントで認可リクエストを登録し、**リクエスト URI** を取得します。

<br />

#### PKCE トークン生成

HAIP は FAPI2SP をベースとしており、FAPI2SP が [PKCE][RFC_7636]
を必須としているため、HAIP 準拠の認可リクエストにはコード・チャレンジ、トークンリクエストにコード・ベリファイアを含めなければなりません。
そのため、`pkce` スクリプトを用いてそれらを用意します。

```shell theme={null}
./pkce
```

実行結果:

```shell theme={null}
CODE_VERIFIER=3HlzvGOxhJz3jK2fwstAM8aV2GvqzWFpvfnyOGm53kk
CODE_CHALLENGE=elpP-j7DRK-dvxy4GBOzSr4EjnWzwRBquR-mY-ijtT8
```

シェル組込コマンド `eval` を次のように用いると、`pkce`
スクリプトの出力結果をそのままシェル変数に代入することができます。

```shell theme={null}
eval "$(./pkce)"
```

<br />

#### クライアント・アテステーション生成

クライアント・アテステーションは `generate-client-attestation`
スクリプトを用いて生成することができます。
なお、HAIP では `x5c` ヘッダパラメーターが必須なので、`--x5c`
オプションを用いて `x5c` ヘッダパラメーターに列挙する X.509 証明書を指定する必要があるので注意してください。
`--x5c` オプションは複数回指定可能で、指定された順番で X.509
証明書を `x5c` ヘッダパラメーターに追加していきます。

```shell theme={null}
CLIENT_ATTESTATION=`./generate-client-attestation \
  --attester-key=keys/client-attester-private.jwk \
  --client-id=${CLIENT_ID} \
  --client-key=client.jwk \
  --x5c=keys/client-attester-certificate.pem`
```

下記は、生成されるクライアント・アテステーションのヘッダとペイロードの例です。

```json theme={null}
{
  "typ": "oauth-client-attestation+jwt",
  "alg": "ES256",
  "x5c": [
    "MIIBnTCCAUOgAwIBAgIUZr+BYJKFUDY6CIbWubXMjo1cEH8wCgYIKoZIzj0EAwIw
     HzEdMBsGA1UEAwwUQ2xpZW50IEF0dGVzdGVyIFJvb3QwIBcNMjYwNDE0MTc1OTQy
     WhgPNDc2NDAzMTExNzU5NDJaMBoxGDAWBgNVBAMMD0NsaWVudCBBdHRlc3RlcjBZ
     MBMGByqGSM49AgEGCCqGSM49AwEHA0IABI7riGciOegPsU1MJrSF5CnwImt7Cjzx
     YIgSpcLa4woMIxPaeKzhgHf+mi3qSset92VCeQIo0YljKsn6GS057bWjYDBeMAwG
     A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBRwEoaaN/q/s+jX
     HSE2bybFF82G3zAfBgNVHSMEGDAWgBQ5hrFgDwFhQ8FuCJQETUlyd2pj0jAKBggq
     hkjOPQQDAgNIADBFAiEA2YOKXOd7UgtSMbVs0mMlss3RNXnMMK2RF2JlkrHQemIC
     IAY6Qx5VxmHwovlc0PJgrCDOQZZRUOKBoedy6AoXLSYh"
  ],
  "kid": "I6NQ3o1a3D2LW4pExAS620B3Amw4pkbNoAcxzkygYhM"
}
{
  "sub": "trial_client",
  "iat": 1776702629,
  "exp": 1776789029,
  "cnf": {
    "jwk": {
      "crv": "P-256",
      "kty": "EC",
      "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
      "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
    }
  }
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `oauth-client-attestation+jwt` である。
* `x5c` ヘッダパラメーターに署名検証用公開鍵の X.509 証明書 (`--x5c` オプションで指定したもの) が含まれている。
* `sub` クレームにクライアント識別子 (`--client-id` オプションで指定したもの) が設定されている。
* `cnf.jwk` クレームにクライアントの鍵 (`--client-key` オプションで指定したもの) が設定されている。

<br />

#### アテステーション・チャレンジ取得

[ABCA][ABCA] 仕様によれば、認可サーバーが**チャレンジエンドポイント**を提供している場合、そのエンドポイントから発行されるアテステーション・チャレンジをクライアント・アテステーション・PoP
に埋め込む必要があります。
認可サーバーがチャレンジエンドポイントを提供しているかどうかは、サーバーメタデータに
`challenge_endpoint` パラメーターが含まれているかどうかで判定することができます。

チャレンジエンドポイントは、HTTP POST リクエストを受け、`attestation_challenge`
プロパティを含む JSON を返します。
下記は [ABCA][ABCA] 仕様から抜粋したリクエストとレスポンスの例です。

アテステーション・チャレンジ・リクエストの例

```http theme={null}
POST /as/challenge HTTP/1.1
Host: as.example.com
Accept: application/json
```

アテステーション・チャレンジ・レスポンスの例

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

{
  "attestation_challenge": "AYjcyMzY3ZDhiNmJkNTZ"
}
```

`CHALLENGE_ENDPOINT` というシェル変数にチャレンジエンドポイントの
URL が入っている場合、次のコマンドを実行することでアテステーション・チャレンジの値を
`CHALLENGE` というシェル変数に代入することができます。

```shell theme={null}
CHALLENGE=`curl ${CHALLENGE_ENDPOINT} \
  -X POST | \
  jq -r .attestation_challenge`
```

<br />

#### クライアント・アテステーション・PoP 生成

クライアント・アテステーション・PoP は `generate-client-attestation-pop`
スクリプトを用いて生成することができます。
`challenge` クレームを含める場合は `--challenge` オプションを指定してください。

```shell theme={null}
CLIENT_ATTESTATION_POP=`./generate-client-attestation-pop \
  --as-id=${AUTHORIZATION_SERVER} \
  --client-key=client.jwk \
  --challenge=${CHALLENGE}`
```

下記は、生成されるクライアント・アテステーション・PoP のヘッダとペイロードの例です。

```json theme={null}
{
  "typ": "oauth-client-attestation-pop+jwt",
  "alg": "ES256",
  "kid": "7yNhIHVeaPFIB_0k-YpiFATomCLpxIv-e2AAFmCRBLE"
}
{
  "aud": "https://trial.authlete.net",
  "jti": "tiZaOFhUK0au8RA0",
  "iat": 1776704669,
  "exp": 1776791069,
  "challenge": "HECMLA_LpoE9hSDlVP4yptT2i1zOnOdkIPnVa39rInA"
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `oauth-client-attestation-pop+jwt` である。
* `aud` クレームに認可サーバー識別子 (`--as-id` オプションで指定したもの) が設定されている。
* `challenge` クレームにアテステーション・チャレンジ (`--challenge` オプションで指定したもの) が設定されている。

<br />

#### DPoP Proof JWT 生成

FAPI2SP に次のように書かれているため、認可コードも DPoP-bound にする必要があります。

> if using DPoP, shall support "Authorization Code Binding to DPoP Key"
> (as required by [Section 10.1][RFC_9449_10_1] of [RFC9449][RFC_9449]);

これを実現する方法は、PAR エンドポイントで登録するリクエストに `dpop_jkt`
リクエストパラメーターを加えるか、もしくは DPoP Proof JWT
を加えるか、のどちらかになります。

仕様書にも書かれているように DPoP Proof JWT のほうが実装が単純になるので
(リクエストの種類に関わらずクライアントは認可サーバーに送るリクエストに常に
DPoP Proof JWT を含めるという実装にすればよいので)、ここでは
DPoP Proof JWT を生成することにします。

`generate-dpop-proof` スクリプトに、PAR
リクエストの HTTP メソッド (POST 固定) を指定する `-m POST`
オプションと、PAR エンドポイントの URL を表す `-u $PAR_ENDPOINT`
オプション、クライアントの鍵を表す `-k client.jwk` オプションを渡して
DPoP Proof JWT を生成します。

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

下記は、生成される DPoP Proof JWT のヘッダとペイロードの例です。

```json theme={null}
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "alg": "ES256",
    "crv": "P-256",
    "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
    "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
  }
}
{
  "jti": "zrZOAIoZJvCbEQrM",
  "htm": "POST",
  "htu": "https://trial.authlete.net/api/par",
  "iat": 1776708531
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `dpop+jwt` である。
* `jwk` ヘッダパラメーターにクライアントの鍵 (`-k` オプションで指定したもの) が設定されている。
* `htm` クレームに PAR リクエストの HTTP メソッド (`-m` オプションで指定したもの) が設定されている。
* `htu` クレームに PAR エンドポイントの URL (`-u` オプションで指定したもの) が設定されている。

<Note>
  認可サーバーによっては、DPoP Proof JWT が `nonce`
  クレームを含むことを要求します。
  その場合は `-n` オプションをつけて DPoP Proof JWT を生成してください。
  DPoP Nonce の詳細については『<a href="https://qiita.com/TakahikoKawasaki/items/b50385444d90665a1b17">DPoP
  Nonce</a>』を参照してください。
</Note>

<br />

#### PAR リクエスト送信

トークン群の用意ができたので、PAR リクエストを送信します。

```shell theme={null}
curl ${PAR_ENDPOINT} \
  -H "OAuth-Client-Attestation: ${CLIENT_ATTESTATION}" \
  -H "OAuth-Client-Attestation-PoP: ${CLIENT_ATTESTATION_POP}" \
  -H "DPoP: ${DPOP_PROOF}" \
  -d client_id=${CLIENT_ID} \
  -d response_type=code \
  -d scope=digital_credential+haip \
  -d redirect_uri=${REDIRECT_URI} \
  -d code_challenge=${CODE_CHALLENGE} \
  -d code_challenge_method=S256
```

このリクエストの要点は次の通りです。

| 項目                      | 説明                                                                                                                                                                                              |
| :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| クライアント認証                | ABCA を用いる場合、`OAuth-Client-Attestation` HTTP ヘッダと `OAuth-Client-Attestation-PoP` HTTP ヘッダに、ぞれぞれクライアント・アテステーション、クライアント・アテステーション・PoP を設定します。                                                       |
| 送信者限定                   | `DPoP` HTTP ヘッダに DPoP Proof JWT を設定します。                                                                                                                                                         |
| `client_id`             | 認可リクエストでは `client_id` リクエストパラメーターは必須です。                                                                                                                                                         |
| `response_type`         | FAPI2SP では `response_type` リクエストパラメーターの値は `code` でなければなりません。(`code` 以外を含めることはできません)                                                                                                             |
| `scope`                 | HAIP 仕様に準拠するため、何かしらのクレデンシャル設定に対応するスコープを `scope` リクエストパラメーターに含めなければなりません。 この例では、`digital_credential` という文字列が何かしらのクレデンシャル設定の `scope` プロパティーに設定されているものと想定しています。 また、この例では追加で `haip` というスコープも含めています。 |
| `redirect_uri`          | FAPI2SP では `redirect_uri` リクエストパラメーターは必須です。                                                                                                                                                     |
| `code_challenge`        | FAPI2SP では PKCE 対応が必須のため、`code_challenge` リクエストパラメーターを含めます。                                                                                                                                     |
| `code_challenge_method` | FAPI2SP ではコードチャレンジメソッドとして `S256` を使うことが必須のため、明示的に `code_challenge_method=S256` を含めます。                                                                                                           |

PAR リクエストが成功すると、PAR エンドポイントからは
`request_uri` プロパティーを含む JSON が返されます。
下記は PAR 仕様から抜粋した PAR レスポンスの例です。

```http theme={null}
HTTP/1.1 201 Created
Cache-Control: no-cache, no-store
Content-Type: application/json

{
  "request_uri": "urn:example:bwc4JK-ESC0w8acc191e-Y1LTC2",
  "expires_in": 90
}
```

`request_uri` プロパティーの値は、発行された**リクエスト URI** です。
このリクエスト URI は、後ほど認可リクエストの `request_uri`
リクエストパラメーターの値として用います。

<Note>
  FAPI2SP の要請により、リクエスト URI の有効時間は 600 秒未満となります。
</Note>

<br />

### 認可リクエスト

ブラウザ経由で、認可サーバーの認可エンドポイントに認可リクエストを投げます。
その際、PAR エンドポイントから発行されたリクエスト URI を
`request_uri` リクエストパラメーターの値として用います。

```
${AUTHORIZATION_ENDPOINT}?client_id=${CLIENT_ID}&request_uri=${REQUEST_URI}
```

<br />

認可エンドポイントから返される認可ページでユーザー認証と権限付与同意をおこなうと、**認可コード**が発行されます。
この認可コードは、後ほどトークンリクエストの `code`
リクエストパラメーターの値として用います。

<Note>
  FAPI2SP の要請により、認可コードの有効時間は最長で 60 秒となります。
  すぐに有効期限が切れるので、手作業でトークンリクエストを投げる場合は注意してください。
</Note>

<br />

### トークンリクエスト

#### トークン群生成

トークンリクエストにおいても、クライアント・アテステーションとクライアント・アテステーション・PoP
が必要となりますが、PAR リクエスト用に作成したものがまだ有効期限切れしていなければ、再利用可能です。

一方、DPoP Proof JWT は、`htu` クレームにエンドポイントの URL
を設定する必要があるため、PAR リクエスト用に作成したものを再利用することはできません。
`-u` オプションにトークンエンドポイントの URL を指定して
`generate-dpop-proof` スクリプトを再実行し、DPoP
Proof JWT を再生成してください。

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

#### トークンリクエスト送信

トークン群を用意後、トークンリクエストを送信します。

```shell theme={null}
curl ${TOKEN_ENDPOINT} \
  -H "OAuth-Client-Attestation: ${CLIENT_ATTESTATION}" \
  -H "OAuth-Client-Attestation-PoP: ${CLIENT_ATTESTATION_POP}" \
  -H "DPoP: ${DPOP_PROOF}" \
  -d grant_type=authorization_code \
  -d code=${AUTHORIZATION_CODE} \
  -d redirect_uri=${REDIRECT_URI} \
  -d code_verifier=${CODE_VERIFIER}
```

このリクエストの要点は次の通りです。

| 項目              | 説明                                                                                                                                        |
| :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| クライアント認証        | ABCA を用いる場合、`OAuth-Client-Attestation` HTTP ヘッダと `OAuth-Client-Attestation-PoP` HTTP ヘッダに、ぞれぞれクライアント・アテステーション、クライアント・アテステーション・PoP を設定します。 |
| 送信者限定           | `DPoP` HTTP ヘッダに DPoP Proof JWT を設定します。                                                                                                   |
| `grant_type`    | 認可コードフローであることを示すため、`authorization_code` という値を設定します。                                                                                       |
| `code`          | 認可リクエストの結果発行された認可コードを指定します。                                                                                                               |
| `redirect_uri`  | PAR リクエストに含めたのと同一のリダイレクト URI を指定します。                                                                                                      |
| `code_verifier` | PAR リクエストに含めたコード・チャレンジに対応するコード・ベリファイアを指定します。                                                                                              |

トークンリクエストが成功すると、トークンエンドポイントからは
`access_token` プロパティーを含む JSON が返されます。

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

{
  "access_token": "zdRKYNzJ0hR99ztiBgd8TTXzQhbattjhtSd-NDykt1A",
  "token_type": "DPoP",
  "expires_in": 86400,
  "scope": "digital_credential haip",
  "refresh_token": "EiHKJFol1UOm7sa9CaKvlnmDH0TP4_takv1I7iWnHI8"
}
```

`access_token` プロパティーの値は、発行された**アクセストークン**です。
このアクセストークンは、後ほどクレデンシャルリクエストの `Authorization`
HTTP ヘッダに設定します。

<br />

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

<img alt="" class="mx-auto d-block" src="https://mintcdn.com/authlete/WGQFc11Y4wUplGrc/ja/protocols-and-flows/advanced-flows/haip-compliant_credential_request.png?fit=max&auto=format&n=WGQFc11Y4wUplGrc&q=85&s=2e3ba33a254113dc3821f20982f64263" width="1920" height="1080" data-path="ja/protocols-and-flows/advanced-flows/haip-compliant_credential_request.png" />

HAIP 仕様を字句通りに解釈すると、必ずしもクレデンシャルリクエストに鍵証明を含める必要はありません。
しかし、現実のユースケースにおいてキー・バインディングを行わないとは考えにくいので、ここで示すクレデンシャルリクエストの例には鍵証明を含めます。

<br />

#### ノンス取得

クレデンシャル・イシュアがノンスエンドポイントを提供している場合、鍵証明やキー・アテステーションにはそのノンスエンドポイントが発行するノンスを含めなければなりません。
クレデンシャル・イシュアがノンスエンドポイントを提供しているかどうかは、クレデンシャル・イシュアのメタデータに
`nonce_endpoint` パラメーターが含まれているかどうかで判定することができます。

ノンスエンドポイントは、HTTP POST リクエストを受け、`c_nonce` プロパティを含む
JSON を返します。下記は [OID4VCI][OID4VCI] 仕様から抜粋したリクエストとレスポンスの例です。

ノンスリクエストの例

```http theme={null}
POST /nonce HTTP/1.1
Host: credential-issuer.example.com
Content-Length: 0
```

ノンスレスポンスの例

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v

{
  "c_nonce": "wKI4LT17ac15ES9bw8ac4"
}
```

`NONCE_ENDPOINT` というシェル変数にノンスエンドポイントの
URL が入っている場合、次のコマンドを実行することでノンスの値を
`NONCE` というシェル変数に代入することができます。

```shell theme={null}
NONCE=`curl ${NONCE_ENDPOINT} \
  -X POST | \
  jq -r .c_nonce`
```

<br />

#### キー・アテステーション生成

キー・アテステーションは `generate-key-attestation`
スクリプトで生成することができます。
なお、HAIP では `x5c` ヘッダパラメーターが必須なので、`--x5c`
オプションを用いて `x5c` ヘッダパラメーターに列挙する X.509 証明書を指定する必要があるので注意してください。
`--x5c` オプションは複数回指定可能で、指定された順番で X.509
証明書を `x5c` ヘッダパラメーターに追加していきます。

```shell theme={null}
KEY_ATTESTATION=`./generate-key-attestation \
  --attester-key=keys/key-attester-private.jwk \
  --attested-key=client.jwk \
  --nonce=${NONCE} \
  --x5c=keys/key-attester-certificate.pem`
```

下記は、生成されるキー・アテステーションのヘッダとペイロードの例です。

```json theme={null}
{
  "typ": "key-attestation+jwt",
  "alg": "ES256",
  "x5c": [
    "MIIBmDCCAT2gAwIBAgIUTD2qHZdvCkld8qneVGlwL4l+rWAwCgYIKoZIzj0EAwIw
     HDEaMBgGA1UEAwwRS2V5IEF0dGVzdGVyIFJvb3QwIBcNMjYwNDE0MTkwODQ1WhgP
     NDc2NDAzMTExOTA4NDVaMBcxFTATBgNVBAMMDEtleSBBdHRlc3RlcjBZMBMGByqG
     SM49AgEGCCqGSM49AwEHA0IABEj5wOUzDlQKX800+V7kanDu8wASHTw6ivrO2HOW
     keWGUNXaToM14Z4EtyM/szOZYv0UOvsdXNLI1cnZAOgPp3+jYDBeMAwGA1UdEwEB
     /wQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBTCXpsU7JVvhynt3n5r5baJ
     xPy21jAfBgNVHSMEGDAWgBRCjxuwwwG/DC9yI5yJ07oD04YvKzAKBggqhkjOPQQD
     AgNJADBGAiEAv3aywa9hsZM5d9zV70GHVP9qmbFleq4SZbmQzIBDNHMCIQDqBvWI
     G9avgr0k6TpwmzhomOTY1H0JigyGaZzuzBe9yQ=="
  ],
  "kid": "qLgVYBf9lZ63QsEz04r9zb4NN3iZnf2-dnoc2k1GWbA"
}
{
  "iat": 1776719761,
  "exp": 1776806161,
  "attested_keys": [
    {
      "crv": "P-256",
      "kty": "EC",
      "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
      "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
    }
  ],
  "nonce": "8aREnUPLVHJT0gswV8dD91YeTBWEKa4YCAd2HpXcOYw"
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `key-attestation+jwt` である。
* `x5c` ヘッダパラメーターに署名検証用公開鍵の X.509 証明書 (`--x5c` オプションで指定したもの) が含まれている。
* `attested_keys` クレームにアテストされる鍵 (`--attested-key` オプションで指定したもの) が含まれている。
* `nonce` クレームにノンス (`--nonce` オプションで指定したもの) が設定されている。

<br />

#### 鍵証明生成

jwt Proof Type の鍵証明は `generate-key-proof`
スクリプトで生成することができます。

```shell theme={null}
JWT_KEY_PROOF=`./generate-key-proof \
  --client-id=${CLIENT_ID} \
  --issuer=${CREDENTIAL_ISSUER} \
  --key=client.jwk \
  --nonce=${NONCE} \
  --key-attestation=${KEY_ATTESTATION}`
```

下記は、生成される鍵証明のヘッダとペイロードの例です。

```json theme={null}
{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "jwk": {
    "crv": "P-256",
    "kty": "EC",
    "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
    "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
  },
  "key_attestation":
    "eyJ0eXAiOiJrZXktYXR0ZXN0YXRpb24rand0IiwiYWxnIjoiRVMyNTYiLCJ4NWMi
     OlsiTUlJQm1EQ0NBVDJnQXdJQkFnSVVURDJxSFpkdkNrbGQ4cW5lVkdsd0w0bCty
     V0F3Q2dZSUtvWkl6ajBFQXdJd0hERWFNQmdHQTFVRUF3d1JTMlY1SUVGMGRHVnpk
     R1Z5SUZKdmIzUXdJQmNOTWpZd05ERTBNVGt3T0RRMVdoZ1BORGMyTkRBek1URXhP
     VEE0TkRWYU1CY3hGVEFUQmdOVkJBTU1ERXRsZVNCQmRIUmxjM1JsY2pCWk1CTUdC
     eXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQkVqNXdPVXpEbFFLWDgwMCtWN2th
     bkR1OHdBU0hUdzZpdnJPMkhPV2tlV0dVTlhhVG9NMTRaNEV0eU0vc3pPWll2MFVP
     dnNkWE5MSTFjblpBT2dQcDMrallEQmVNQXdHQTFVZEV3RUIvd1FDTUFBd0RnWURW
     UjBQQVFIL0JBUURBZ2VBTUIwR0ExVWREZ1FXQkJUQ1hwc1U3SlZ2aHludDNuNXI1
     YmFKeFB5MjFqQWZCZ05WSFNNRUdEQVdnQlJDanh1d3d3Ry9EQzl5STV5SjA3b0Qw
     NFl2S3pBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQXYzYXl3YTloc1pNNWQ5elY3
     MEdIVlA5cW1iRmxlcTRTWmJtUXpJQkROSE1DSVFEcUJ2V0lHOWF2Z3IwazZUcHdt
     emhvbU9UWTFIMEppZ3lHYVp6dXpCZTl5UT09Il0sImtpZCI6InFMZ1ZZQmY5bFo2
     M1FzRXowNHI5emI0Tk4zaVpuZjItZG5vYzJrMUdXYkEifQ.eyJpYXQiOjE3NzY3M
     Tk3NjEsImV4cCI6MTc3NjgwNjE2MSwiYXR0ZXN0ZWRfa2V5cyI6W3siY3J2IjoiU
     C0yNTYiLCJrdHkiOiJFQyIsIngiOiIxQW1WcjRHb0hkUGdrNDhMV2RTM1Q5bTZtM
     W1QNFZUY2o5dXNvU0JuQ1FrIiwieSI6InRlLVdJdVVJcTJ3OHRYbVh5ZGxFWDRwZ
     TlsTmUtUEJjb3pBOG43eThYVEUifV0sIm5vbmNlIjoiOGFSRW5VUExWSEpUMGdzd
     1Y4ZEQ5MVllVEJXRUthNFlDQWQySHBYY09ZdyJ9.CeDXPV9gfr2x92IHSZ5BcyFf
     RuTK2M5Y4JeHFgijfZeNBytz1QICaxnLOVTZjXYu-JlL21_xkPoODrWTSiDPLg"
}
{
  "iss": "trial_client",
  "aud": "https://trial.authlete.net",
  "iat": 1776720642,
  "nonce": "8aREnUPLVHJT0gswV8dD91YeTBWEKa4YCAd2HpXcOYw"
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `openid4vci-proof+jwt` である。
* `jwk` ヘッダパラメーターにクライアントの鍵 (`--key` オプションで指定したもの) が設定されている。
* `key_attestation` ヘッダパラメーターにキー・アテステーション (`--key-attestation` オプションで指定したもの) が設定されている。
* `iss` クレームにクライアント識別子 (`--client-id` オプションで指定したもの) が設定されている。
* `aud` クレームにクレデンシャル・イシュア識別子 (`--issuer` オプションで指定したもの) が設定されている。
* `nonce` クレームにノンス (`--nonce` オプションで指定したもの) が設定されている。

<br />

#### DPoP Proof JWT 生成

`-u` オプションにクレデンシャルエンドポイントの URL を指定して
`generate-dpop-proof` スクリプトを再実行し、DPoP
Proof JWT を再生成します。

なお、クレデンシャルリクエストでは DPoP Proof JWT
とアクセストークンを一緒に送信することになるので、DPoP Proof JWT
には `ath` クレームを含めなければなりません。
このため、`generate-dpop-proof`
スクリプトを実行する際、`-a` オプションを追加してください。

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

<br />

#### クレデンシャルリクエスト送信

鍵証明が用意できたので、クレデンシャルリクエストを送信します。
ここでは、`digital_credential`
スコープが指すクレデンシャル設定の識別子が `DigitalCredential`
であると想定しています。

```shell theme={null}
curl ${CREDENTIAL_ENDPOINT} \
  -H "Authorization: DPoP ${ACCESS_TOKEN}" \
  -H "DPoP: ${DPOP_PROOF}" \
  --json '{
  "credential_configuration_id": "DigitalCredential",
  "proofs": {
    "jwt": ["'${JWT_KEY_PROOF}'"]
  }
}'
```

このリクエストの要点は次の通りです。

| 項目                            | 説明                                                                                               |
| :---------------------------- | :----------------------------------------------------------------------------------------------- |
| アクセストークン                      | トークンエンドポイントから発行されたアクセストークンを `Authorization` HTTP ヘッダに設定します。 DPoP-bound なので、スキーム部には `DPoP` と書きます。 |
| 送信者限定                         | `DPoP` HTTP ヘッダに DPoP Proof JWT を設定します。                                                          |
| `credential_configuration_id` | クレデンシャルリクエストには `credential_configuration_id` または `credential_identifier` のどちらかが必須です。             |
| `proofs`                      | 鍵証明を指定します。                                                                                       |

上記のリクエストでは jwt Proof Type の鍵証明を用いたため、キー・アテステーションを別の
JWT に埋め込みました。
一方で、attestation Proof Type の鍵証明であれば、次のようにキー・アテステーションを直接鍵証明として用いることができます。

```shell theme={null}
curl ${CREDENTIAL_ENDPOINT} \
  -H "Authorization: DPoP ${ACCESS_TOKEN}" \
  -H "DPoP: ${DPOP_PROOF}" \
  --json '{
  "credential_configuration_id": "DigitalCredential",
  "proofs": {
    "attestation": ["'${KEY_ATTESTATION}'"]
  }
}'
```

下記はクレデンシャルレスポンスの例です。

```json theme={null}
{
  "credentials": [
    {
      "credential":
        "eyJ4NWMiOlsiTUlJQ1NEQ0NBZTZnQXdJQkFnSVVLSlM1R21Ram5mY0JrM1piL2VX
         K0loblFrOHN3Q2dZSUtvWkl6ajBFQXdJd1pURUxNQWtHQTFVRUJoTUNTbEF4RGpB
         TUJnTlZCQWdNQlZSdmEzbHZNUkF3RGdZRFZRUUhEQWREYUdsNWIyUmhNUmN3RlFZ
         RFZRUUtEQTVCZFhSb2JHVjBaU3dnU1c1akxqRWJNQmtHQTFVRUF3d1NkSEpwWVd3
         dVlYVjBhR3hsZEdVdWJtVjBNQ0FYRFRJMU1ESXlOVEExTXpJME9Wb1lEekl5T1Rn
         eE1qRXhNRFV6TWpRNVdqQmxNUXN3Q1FZRFZRUUdFd0pLVURFT01Bd0dBMVVFQ0F3
         RlZHOXJlVzh4RURBT0JnTlZCQWNNQjBOb2FYbHZaR0V4RnpBVkJnTlZCQW9NRGtG
         MWRHaHNaWFJsTENCSmJtTXVNUnN3R1FZRFZRUUREQkowY21saGJDNWhkWFJvYkdW
         MFpTNXVaWFF3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFPZDZU
         Q3ducG5tWHFwczhSUUhxK0s5Tm9vRmJyamIxeXlGeEpsSGs3V2ZUVk9yWkR1OU5x
         K0lPYzl5cm83eStHOXJUZjB6dDhPV0o1aS9XaWpqSUxUbzNvd2VEQWRCZ05WSFE0
         RUZnUVVQTVlhNmZRSlA2TTZ4NHRZTTFmYmYzL0UweE13SHdZRFZSMGpCQmd3Rm9B
         VVBNWWE2ZlFKUDZNNng0dFlNMWZiZjMvRTB4TXdEd1lEVlIwVEFRSC9CQVV3QXdF
         Qi96QWxCZ05WSFJFRUhqQWNoaHBvZEhSd2N6b3ZMM1J5YVdGc0xtRjFkR2hzWlhS
         bExtNWxkREFLQmdncWhrak9QUVFEQWdOSUFEQkZBaUVBeW8zQS9vUVgvTWU4bXlN
         V0wwMjVjVEJ3L2tlY2VIRUxmU1FIbWxlNVFBRUNJQzVnL3luT210L251a3NmSEFl
         TUFCZjd0bzUyelRSa1JkdXFRQ1pITzNlWSJdLCJraWQiOiJaWUdJT0hZdUE5SXBV
         aWpWd1FOdWwzbkU1MzZ4MUpTV0hpT2ZkUzdzYWRnIiwidHlwIjoiZGMrc2Qtand0
         IiwiYWxnIjoiRVMyNTYifQ.eyJfc2QiOlsiM005WU43VXk0RHI0OFdCNEFhNmFEQ
         2NudUhxdi1lRUw2RVFITjBMb3ExbyIsIks2UVZHUmVyOVFId2tDYkpoNW1PVUNLO
         UwtX0luM0pPX2o2eUlQNzVJaGMiLCJQQ1M5dFBvMXlrb2NmV09iYzd0LUVObXU1M
         HdzekY3UTNxZ0MyTFN3dmhRIiwiUS1tdllZWFpfVk9SZlc2ekhXSnhaeC1fNUxwM
         EtNbG1lbGJPSUQ5Z3NyNCIsIlFfTjRKOHJnTnV5QS1Oa2RTVmdNR3pvN0RVM3lrW
         Dk5dk1zVEJzcklLN28iLCJYcjF6RnFETU5kdXp2UDFBZFZqWFV4WlQ5T1RJRW9kd
         TlSRmZ1c2FFYUJJIiwiWVNrSUNPRXI1dzZCY3lEQmVwck5sLXhGMmdheExtOGRaZ
         lp1NVRUcFpiUSIsIll4LXFYdi10a3Babnd6MkJkN1pyOXhlaDBGOE05bnJzdUkxT
         DdvaGlTNEkiLCJkS1pEUDhwYzdLbXlXNkVwSER2TVIxRnd0aDNKN0xoeldNRWgyW
         kh3UXRRIiwiZUFPQ1l0VmN0bVllNnF6eEJvOUh4TE9panZaSlRKSjBBR2pHblJrW
         WdsTSJdLCJ2Y3QiOiJodHRwczovL2NyZWRlbnRpYWxzLmV4YW1wbGUuY29tL2RpZ
         2l0YWxfY3JlZGVudGlhbCIsIl9zZF9hbGciOiJzaGEtMjU2IiwiaXNzIjoiaHR0c
         HM6Ly90cmlhbC5hdXRobGV0ZS5uZXQiLCJjbmYiOnsiandrIjp7Imt0eSI6IkVDI
         iwiY3J2IjoiUC0yNTYiLCJraWQiOiJPUmduOXZ5S2ZKZnI2SmljN1dtaVRFV0pCb
         FRZa1QwZS1JSU9NU3l2SXRvIiwieCI6IjFBbVZyNEdvSGRQZ2s0OExXZFMzVDltN
         m0xbVA0VlRjajl1c29TQm5DUWsiLCJ5IjoidGUtV0l1VUlxMnc4dFhtWHlkbEVYN
         HBlOWxOZS1QQmNvekE4bjd5OFhURSJ9fSwiZXhwIjoxNzc5MzEzOTg5LCJpYXQiO
         jE3NzY3MjE5ODl9.k_BY_BMZVLgNRqutBakVGgpcfq5DbbQdgGsGnTvDWRqZX4KN
         wbzEJd6bHZhIC7Di5_3QS_sUvByHnDpa95NJTw~WyIwbHlrWHpiLTNZR0kwZndVa
         ktMZk5BIiwic3ViIiwiMTAwNCJd~WyJ3Vi04VWk0MUp3eEpmYzN3WnQyaFRRIiwi
         Z2l2ZW5fbmFtZSIsIkluZ2EiXQ~WyJFWlZRUGI0ZFJzY01xa1dheEJmel9nIiwiZ
         mFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd~WyJrT0ZrLVRFMzVlRlpRVzBrQnpR
         V3FnIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd~"
    }
  ]
}
```

`credentials` 配列の各要素は JSON オブジェクトであり、それらの `credential`
プロパティの値が発行された VC を表しています。
この例では発行された VC は一つのみで、そのフォーマットは [SD-JWT VC][SD_JWT_VC]
となっています。

<br />

#### SD-JWT VC

発行された [SD-JWT VC][SD_JWT_VC] の Issuer-signed JWT
部のヘッダとペイロードをデコードすると次のようになります。

```json theme={null}
{
  "x5c": [
    "MIICSDCCAe6gAwIBAgIUKJS5GmQjnfcBk3Zb/eW+IhnQk8swCgYIKoZIzj0EAwIw
     ZTELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdDaGl5b2Rh
     MRcwFQYDVQQKDA5BdXRobGV0ZSwgSW5jLjEbMBkGA1UEAwwSdHJpYWwuYXV0aGxl
     dGUubmV0MCAXDTI1MDIyNTA1MzI0OVoYDzIyOTgxMjExMDUzMjQ5WjBlMQswCQYD
     VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0NoaXlvZGExFzAVBgNV
     BAoMDkF1dGhsZXRlLCBJbmMuMRswGQYDVQQDDBJ0cmlhbC5hdXRobGV0ZS5uZXQw
     WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQOd6TCwnpnmXqps8RQHq+K9NooFbrj
     b1yyFxJlHk7WfTVOrZDu9Nq+IOc9yro7y+G9rTf0zt8OWJ5i/WijjILTo3oweDAd
     BgNVHQ4EFgQUPMYa6fQJP6M6x4tYM1fbf3/E0xMwHwYDVR0jBBgwFoAUPMYa6fQJ
     P6M6x4tYM1fbf3/E0xMwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAchhpodHRw
     czovL3RyaWFsLmF1dGhsZXRlLm5ldDAKBggqhkjOPQQDAgNIADBFAiEAyo3A/oQX
     /Me8myMWL025cTBw/keceHELfSQHmle5QAECIC5g/ynOmt/nuksfHAeMABf7to52
     zTRkRduqQCZHO3eY"
  ],
  "kid": "ZYGIOHYuA9IpUijVwQNul3nE536x1JSWHiOfdS7sadg",
  "typ": "dc+sd-jwt",
  "alg": "ES256"
}
{
  "_sd": [
    "3M9YN7Uy4Dr48WB4Aa6aDCcnuHqv-eEL6EQHN0Loq1o",
    "K6QVGRer9QHwkCbJh5mOUCK9L-_In3JO_j6yIP75Ihc",
    "PCS9tPo1ykocfWObc7t-ENmu50wszF7Q3qgC2LSwvhQ",
    "Q-mvYYXZ_VORfW6zHWJxZx-_5Lp0KMlmelbOID9gsr4",
    "Q_N4J8rgNuyA-NkdSVgMGzo7DU3ykX99vMsTBsrIK7o",
    "Xr1zFqDMNduzvP1AdVjXUxZT9OTIEodu9RFfusaEaBI",
    "YSkICOEr5w6BcyDBeprNl-xF2gaxLm8dZfZu5TTpZbQ",
    "Yx-qXv-tkpZnwz2Bd7Zr9xeh0F8M9nrsuI1L7ohiS4I",
    "dKZDP8pc7KmyW6EpHDvMR1Fwth3J7LhzWMEh2ZHwQtQ",
    "eAOCYtVctmYe6qzxBo9HxLOijvZJTJJ0AGjGnRkYglM"
  ],
  "vct": "https://credentials.example.com/digital_credential",
  "_sd_alg": "sha-256",
  "iss": "https://trial.authlete.net",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "kid": "ORgn9vyKfJfr6Jic7WmiTEWJBlTYkT0e-IIOMSyvIto",
      "x": "1AmVr4GoHdPgk48LWdS3T9m6m1mP4VTcj9usoSBnCQk",
      "y": "te-WIuUIq2w8tXmXydlEX4pe9lNe-PBcozA8n7y8XTE"
    }
  },
  "exp": 1779313989,
  "iat": 1776721989
}
```

次の点に注目してください。

* `typ` ヘッダパラメーターの値が `dc+sd-jwt` である。
* `_sd` クレームにディスクロージャ群の SHA-256 ダイジェスト値が列挙されている (ただし偽のダイジェスト値も含む)。
* `_sd_alg` クレームがディスクロージャ群のダイジェスト値の計算に用いたハッシュアルゴリズムを示している。
* SD-JWT VC では必須の `vct` クレームが含まれている。
* `cnf.jwk` クレームに、鍵証明で指定されたクライアント鍵が設定されている。

下記はディスクロージャ群の情報です。

| ディスクロージャ | `WyIwbHlrWHpiLTNZR0kwZndVaktMZk5BIiwic3ViIiwiMTAwNCJd` |
| :------- | :----------------------------------------------------- |
| ダイジェスト   | `eAOCYtVctmYe6qzxBo9HxLOijvZJTJJ0AGjGnRkYglM`          |
| ソルト      | `"0lykXzb-3YGI0fwUjKLfNA"`                             |
| クレーム名    | `"sub"`                                                |
| クレーム値    | `"1004"`                                               |

| ディスクロージャ | `WyJ3Vi04VWk0MUp3eEpmYzN3WnQyaFRRIiwiZ2l2ZW5fbmFtZSIsIkluZ2EiXQ` |
| :------- | :--------------------------------------------------------------- |
| ダイジェスト   | `3M9YN7Uy4Dr48WB4Aa6aDCcnuHqv-eEL6EQHN0Loq1o`                    |
| ソルト      | `"wV-8Ui41JwxJfc3wZt2hTQ"`                                       |
| クレーム名    | `"given_name"`                                                   |
| クレーム値    | `"Inga"`                                                         |

| ディスクロージャ | `WyJFWlZRUGI0ZFJzY01xa1dheEJmel9nIiwiZmFtaWx5X25hbWUiLCJTaWx2ZXJzdG9uZSJd` |
| :------- | :------------------------------------------------------------------------- |
| ダイジェスト   | `Q-mvYYXZ_VORfW6zHWJxZx-_5Lp0KMlmelbOID9gsr4`                              |
| ソルト      | `"EZVQPb4dRscMqkWaxBfz_g"`                                                 |
| クレーム名    | `"family_name"`                                                            |
| クレーム値    | `"Silverstone"`                                                            |

| ディスクロージャ | `WyJrT0ZrLVRFMzVlRlpRVzBrQnpRV3FnIiwiYmlydGhkYXRlIiwiMTk5MS0xMS0wNiJd` |
| :------- | :--------------------------------------------------------------------- |
| ダイジェスト   | `Yx-qXv-tkpZnwz2Bd7Zr9xeh0F8M9nrsuI1L7ohiS4I`                          |
| ソルト      | `"kOFk-TE35eFZQW0kBzQWqg"`                                             |
| クレーム名    | `"birthdate"`                                                          |
| クレーム値    | `"1991-11-06"`                                                         |

<br />

## 証明書チェーン検証

HAIP では、クライアント・アテステーションとキー・アテステーションは
`x5c` ヘッダパラメーターを含んでいなければなりません。
そのようなアテステーションを受け取った認可サーバーやクレデンシャル・イシュアは、`x5c`
ヘッダパラメーターで指定される証明書チェーンが信頼するルート証明書群のいずれかに繋がることを確認します。
ただし、この確認作業の際に用いるルート証明書群については、HAIP には指定がありません。

とはいえ、HAIP の策定作業が EUDI Wallet を想定して進められていることを鑑みると、HAIP
運用では EU の規制当局が指定するルート証明書を用いることを要求されるだろうことは容易に想像がつきます。
このような状況下では、汎用的な HAIP 実装は、検証に用いるルート証明書群を設定する機能を用意しておくのがよいでしょう。

そういうわけで、Authlete も次のようなプロパティ群をサービスに新設しました。

| プロパティ名                       | 説明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clientAttesterRoots`        | <a href="https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth/">OAuth 2.0 Attestation-Based Client Authentication</a> で定義されているクライアント・アテステーションが `x5c` ヘッダパラメーターを含んでいる場合、Authlete は指定された証明書チェーンを検証します。その検証の際、このプロパティ (`clientAttesterRoots`) で指定された X.509 証明書群を信頼済みのルート証明書群として利用します。ただし、これらの証明書群を利用すると明示的に設定されている場合に限ります。具体的には、`clientAttesterRootsEnabled` プロパティの値が `true` と設定されている場合に限ります。<br /><br />指定されたルート証明書群で検証をパスできなかった場合、システムにインストール済みのルート証明書群を用いて検証がおこなわれます。ただし、システムのルート証明書群を参照しないように設定されている場合、具体的には `clientAttesterRootsOnly` プロパティの値が `true` と設定されている場合、システムのルート証明書群は参照されません。<br /><br />このプロパティで設定する証明書のフォーマットは PEM としてください。ただし、PEM マーカー (`-----BEGIN CERTIFICATE-----` と `-----END CERTIFICATE-----`) は省略可能です。なお、Authlete API がこのプロパティの値を返す際は、たとえ設定時に PEM マーカーが省略されていたとしても、PEM マーカーが含まれます。<br /><br /><a href="https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth/">OAuth 2.0 Attestation-Based Client Authentication</a> はクライアント・アテステーションが `x5c` ヘッダパラメーターを含むことを要求しません。しかし、<a href="https://openid.net/specs/openid4vc-high-assurance-interoperability-profile-1_0.html">OpenID4VC High Assurance Interoperability Profile 1.0</a> では必須とされているので注意してください。サービスの `haipVersion` プロパティやクライアントの `haipVersion` プロパティに値が設定されていたり、`haip` 属性を持つスコープをリクエストに含めると、HAIP が有効になり、結果としてクライアント・アテステーションの `x5c` ヘッダパラメーターが必須となります。 |
| `clientAttesterRootsEnabled` | クライアント・アテステーション証明書チェーンの検証用ルート証明書群、具体的には `clientAttesterRoots` プロパティに設定された X.509 証明書群を、クライアント・アテステーションの `x5c` ヘッダパラメーターに指定された証明書チェーンを検証する際に利用するかどうかを設定します。このプロパティ (`clientAttesterRootsEnabled`) を明示的に有効化しないと (`true` を設定しないと)、たとえ `clientAttesterRoots` プロパティを設定しても、それらのルート証明書群は利用されません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `clientAttesterRootsOnly`    | クライアント・アテステーションの `x5c` ヘッダパラメーターに指定された証明書チェーンを検証する際に、それ専用に設定されたルート証明書群、具体的には `clientAttesterRoots` プロパティに設定された証明書群のみを用いて検証をおこなうかどうかを設定します。このプロパティ (`clientAttesterRootsOnly`) が有効になっていると (`true` が設定されていると)、システムにインストールされているルート証明書群は検証に利用されません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `keyAttesterRoots`           | <a href="https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-D">OpenID for Verifiable Credential Issuance 1.0, Appendix D. Key Attestations</a> で定義されているキー・アテステーションが `x5c` ヘッダパラメーターを含んでいる場合、Authlete は指定された証明書チェーンを検証します。その検証の際、このプロパティ (`keyAttesterRoots`) で指定された X.509 証明書群を信頼済みのルート証明書群として利用します。ただし、これらの証明書群を利用すると明示的に設定されている場合に限ります。具体的には、`keyAttesterRootsEnabled` プロパティの値が `true` と設定されている場合に限ります。<br /><br />指定されたルート証明書群で検証をパスできなかった場合、システムにインストール済みのルート証明書群を用いて検証がおこなわれます。ただし、システムのルート証明書群を参照しないように設定されている場合、具体的には `keyAttesterRootsOnly` プロパティの値が `true` と設定されている場合、システムのルート証明書群は参照されません。<br /><br />このプロパティで設定する証明書のフォーマットは PEM としてください。ただし、PEM マーカー (`-----BEGIN CERTIFICATE-----` と `-----END CERTIFICATE-----`) は省略可能です。なお、Authlete API がこのプロパティの値を返す際は、たとえ設定時に PEM マーカーが省略されていたとしても、PEM マーカーが含まれます。<br /><br /><a href="https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html">OpenID for Verifiable Credential Issuance 1.0</a> はキー・アテステーションが `x5c` ヘッダパラメーターを含むことを要求しません。しかし、<a href="https://openid.net/specs/openid4vc-high-assurance-interoperability-profile-1_0.html">OpenID4VC High Assurance Interoperability Profile 1.0</a> では必須とされているので注意してください。サービスの `haipVersion` プロパティやクライアントの `haipVersion` プロパティに値が設定されていたり、`haip` 属性を持つスコープをリクエストに含めると、HAIP が有効になり、結果としてキー・アテステーションの `x5c` ヘッダパラメーターが必須となります。   |
| `keyAttesterRootsEnabled`    | キー・アテステーション証明書チェーンの検証用ルート証明書群、具体的には `keyAttesterRoots` プロパティに設定された X.509 証明書群を、キー・アテステーションの `x5c` ヘッダパラメーターに指定された証明書チェーンを検証する際に利用するかどうかを設定します。このプロパティ (`keyAttesterRootsEnabled`) を明示的に有効化しないと (`true` を設定しないと)、たとえ `keyAttesterRoots` プロパティを設定しても、それらのルート証明書群は利用されません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `keyAttesterRootsOnly`       | キー・アテステーションの `x5c` ヘッダパラメーターに指定された証明書チェーンを検証する際に、それ専用に設定されたルート証明書群、具体的には `keyAttesterRoots` プロパティに設定された証明書群のみを用いて検証をおこなうかどうかを設定します。このプロパティ (`keyAttesterRootsOnly`) が有効になっていると (`true` が設定されていると)、システムにインストールされているルート証明書群は検証に利用されません。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

下記は、クライアント・アテステーションとキー・アテステーションの証明書チェーンの検証に用いるルート証明書群の設定例です。

```json theme={null}
{
  "clientAttesterRoots": [
    "-----BEGIN CERTIFICATE-----\n
     MIIBpTCCAUugAwIBAgIUUTw+Ep5ZOdplQAjzE/68Z9IUzzgwCgYIKoZIzj0EAwIw\n
     HzEdMBsGA1UEAwwUQ2xpZW50IEF0dGVzdGVyIFJvb3QwIBcNMjYwNDE0MTU0MzQ1\n
     WhgPNDc2NDAzMTExNTQzNDVaMB8xHTAbBgNVBAMMFENsaWVudCBBdHRlc3RlciBS\n
     b290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyRlNlUPzTt6jF5s0ltIjoGHx\n
     SFQu6GE+gZOMm5sOrNGmAaI6i48CSI6yrXpr/F0KV6t4IH9FcKsZWrpIA7evz6Nj\n
     MGEwHQYDVR0OBBYEFDmGsWAPAWFDwW4IlARNSXJ3amPSMB8GA1UdIwQYMBaAFDmG\n
     sWAPAWFDwW4IlARNSXJ3amPSMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD\n
     AgEGMAoGCCqGSM49BAMCA0gAMEUCIQCXxFHg356YWT2gEIdU0Vdm2znUMRwm7Wgb\n
     Jf9GbLDvggIgK98PHmvP8WRqPfQr1cNpSSBoogDhZhLcelvm/L0coLA=\n
     -----END CERTIFICATE-----"
  ],
  "clientAttesterRootsEnabled": true,
  "clientAttesterRootsOnly": false,
  "keyAttesterRoots": [
    "-----BEGIN CERTIFICATE-----\n
     MIIBoDCCAUWgAwIBAgIUWRZNOcKwPKKFYiMHguS6ZS81IPUwCgYIKoZIzj0EAwIw\n
     HDEaMBgGA1UEAwwRS2V5IEF0dGVzdGVyIFJvb3QwIBcNMjYwNDE0MTkwNzUxWhgP\n
     NDc2NDAzMTExOTA3NTFaMBwxGjAYBgNVBAMMEUtleSBBdHRlc3RlciBSb290MFkw\n
     EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7RNVRube8DDaZ1zYjBe3vPQFB8WVVqJ/\n
     AAIxUd2HdgLd+7x6EU1T7aHQ5r/ARQpLeYsqiou02jwQoDW+rtNozaNjMGEwHQYD\n
     VR0OBBYEFEKPG7DDAb8ML3IjnInTugPThi8rMB8GA1UdIwQYMBaAFEKPG7DDAb8M\n
     L3IjnInTugPThi8rMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoG\n
     CCqGSM49BAMCA0kAMEYCIQCtbIlRnFUs7QSuQZkv6NCxiK0Ui8V/P+gcq/70nWBk\n
     yQIhAOowEiHzVvY1iTGYJ2at2Z1UigC3rq2q/E2A70AS8gc5\n
     -----END CERTIFICATE-----"
  ],
  "keyAttesterRootsEnabled": true,
  "keyAttesterRootsOnly": false
}
```

<br />

## HAIP 有効化

認可サーバーやクレデンシャル・イシュアへのリクエストに対して HAIP
バリデーションを実行するかどうかを決める方法は、実装依存です。
Authlete は次の三つの方法を提供しています。

| 有効化方法                        | 説明                                                                                   |
| :--------------------------- | :----------------------------------------------------------------------------------- |
| サービスの `haipVersion` プロパティー   | サービスの `haipVersion` プロパティーに値が設定されている場合、そのサービスへのリクエストに対して常に HAIP バリデーションが実行されます。      |
| クライアントの `haipVersion` プロパティー | クライアントの `haipVersion` プロパティーに値が設定されている場合、そのクライアントからのリクエストに対して常に HAIP バリデーションが実行されます。 |
| スコープの `haip` 属性              | リクエストが、`haip` 属性に有効な値が設定されているスコープを含んでいる場合、そのリクエストに対して HAIP バリデーションが実行されます。           |

`haipVersion` プロパティーや `haip` 属性に設定することが可能な値は、現時点
(2026 年 4 月) の Authlete の実装では `1.0` (文字列) のみです。

<br />

## おわりに

[HAIP][HAIP] は VC 関連仕様の相互運用性とセキュリティを高めるためのプロファイルです。
この文書で紹介した HAIP 関連の機能は、Authlete バージョン 3.0.31 以降で利用可能です。
詳細については[コンタクトフォーム][CONTACT]からお問い合わせください。

[ABCA]: https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth/

[CONTACT]: https://www.authlete.com/ja/contact

[FAPI2SP]: https://openid.net/specs/fapi-security-profile-2_0.html

[HAIP]: https://openid.net/specs/openid4vc-high-assurance-interoperability-profile-1_0.html

[OID4VCI]: https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html

[OID4VCI_D]: https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-D

[OID4VCI_DEMO]: https://github.com/authlete/oid4vci-demo/

[OID4VCI_F1]: https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-F.1

[OID4VCI_F3]: https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-F.3

[RFC_7523]: https://www.rfc-editor.org/rfc/rfc7523.html

[RFC_7636]: https://www.rfc-editor.org/rfc/rfc7636.html

[RFC_8705]: https://www.rfc-editor.org/rfc/rfc8705.html

[RFC_9126]: https://www.rfc-editor.org/rfc/rfc9126.html

[RFC_9449]: https://www.rfc-editor.org/rfc/rfc9449.html

[RFC_9449_10_1]: https://www.rfc-editor.org/rfc/rfc9449.html#section-10.1

[SD_JWT_VC]: https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/
