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

> Auth0 で Demonstrating Proof-of-Possession (DPoP) を使用してアクセストークンに送信者制約を適用する方法を学びます。

# Demonstrating Proof-of-Possession (DPoP)

Demonstrating Proof-of-Possession (DPoP) は、非対称暗号方式とアプリケーション層の <Tooltip tip="Access Token: API へのアクセスに使用される、不透明な文字列または JWT 形式の認可資格情報。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=access+tokens">アクセストークン</Tooltip>、および <Tooltip tip="Access Token: API へのアクセスに使用される、不透明な文字列または JWT 形式の認可資格情報。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=JSON+Web+Tokens">JSON Web Tokens</Tooltip> (JWT) を使用して、<Tooltip tip="Access Token: API へのアクセスに使用される、不透明な文字列または JWT 形式の認可資格情報。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=access+tokens">アクセストークン</Tooltip>をクライアントに結び付ける、つまり [送信者制約](/docs/ja-jp/secure/sender-constraining) を適用するための [OAuth 2.0 framework extension](https://datatracker.ietf.org/doc/draft-ietf-oauth-dpop/) です。DPoP により、秘密キーを保持する、アクセストークンを要求したクライアントアプリケーションのみがそのトークンを使用できるようになります。これにより、盗まれたトークンの悪用を防止します。

DPoP は公開鍵/秘密鍵を使用して、署名付き JSON Web トークン (JWT) として DPoP Proof を作成します。DPoP Proof には次のものが含まれます。

* クライアントの公開鍵 (`jwk`) 。
* メソッド (`htm`) と URI (`htu`) を含む、アクセストークンrequestを参照するpayload。
* クライアントの秘密キーを使用して作成された署名。
* リプレイ防止のための一意の ID (`jti`) 。
* API request ごとに含まれる、アクセストークンの base64url エンコードされた SHA-256 ハッシュ (`ath`) 。
* 任意: <Tooltip tip="Public Client: 資格情報を安全に保持できないクライアント（アプリケーション）。例としては、ネイティブのデスクトップまたはモバイルアプリケーション、ならびに JavaScript ベースのクライアント側 Web アプリケーション（シングルページアプリケーション（SPA）など）があります。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=public+clients">public clients</Tooltip> の場合、クライアントアプリケーションが最近 DPoP Proof JWT を生成したことを保証するための `nonce` claim。

クライアントアプリケーションは、アクセストークンrequestで DPoP Proof JWT を Auth0 の <Tooltip tip="Authorization Server: ユーザーアクセスの境界の定義に関与する集中管理サーバー。たとえば、認可サーバーはユーザーが利用できるデータ、タスク、機能を制御できます。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Authorization+Server">認可サーバー</Tooltip> に送信します。Auth0 Authorization Server が DPoP Proof JWT をvalidateした後、発行されたアクセストークンをクライアントの公開鍵に結び付けます。

<div id="common-use-cases">
  ## 一般的な利用例
</div>

代表的な DPoP の利用例をいくつか紹介します。

* **Single Page Applications (SPAs) and mobile applications:** 公開クライアントである SPA やモバイルアプリケーションには、バックエンドサーバーのような、<Tooltip tip="Client Secret: クライアント（アプリケーション）が認可サーバーに対して認証を行うために使用する Secret です。これはクライアントと認可サーバーだけが知っている必要があり、推測されないよう十分にランダムでなければなりません。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=client+secrets">クライアントシークレット</Tooltip> を安全に保存できる信頼された機密環境がありません。そのため、トークン盗難に対して脆弱です。DPoP は、アクセストークンをクライアントアプリケーションの公開キーに結び付けて DPoP Proof JWT を作成することで、このセキュリティ脆弱性に対処します。クライアントアプリケーションは、自身の秘密キーで DPoP Proof JWT に署名し、認可リクエストで送信します。Auth0 Authorization Server は DPoP Proof JWT を検証し、有効であれば、発行するアクセストークンをクライアントの公開キーに結び付けます。
* **Third-party API integrations:** クライアントアプリケーションと連携した AI エージェントが、ユーザーに代わって DPoP Proof JWT を使用してサードパーティ API を呼び出す場合、<Tooltip tip="Resource Server: 保護されたリソースをホストするサーバーです。リソースサーバーは、保護されたリソースへのリクエストを受け入れ、それに応答します。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=resource+server">リソースサーバー</Tooltip> は、そのリクエストが権限のない第三者ではなく AI エージェントから送信されたものであることを、暗号学的に検証できます。

<div id="supported-application-grant-types">
  ## サポートされているアプリケーションのグラントタイプ
</div>

Auth0 は、DPoP を使用した送信者拘束向けに、次の[アプリケーションのグラントタイプ](/docs/ja-jp/get-started/applications/application-grant-types)をサポートしています。

| グラントタイプ                                               | 説明                                             |
| ----------------------------------------------------- | ---------------------------------------------- |
| `authorization_code`                                  | 認可コードグラント                                      |
| `client_credentials`                                  | クライアントクレデンシャルグラント                              |
| `password`                                            | リソース所有者パスワードグラント                               |
| `refresh_token`                                       | リフレッシュトークングラント                                 |
| `urn:ietf:params:oauth:grant-type:device_code`        | デバイス認可グラント                                     |
| `http://auth0.com/oauth/grant-type/password-realm`    | 特定のレルムを指定できる、リソース所有者パスワードグラントに類似した拡張グラントを使用します |
| `http://auth0.com/oauth/grant-type/passwordless/otp`  | パスワードレスグラントリクエスト                               |
| `http://auth0.com/oauth/grant-type/mfa-oob`           | 多要素認証アウトオブバンドグラントリクエスト                         |
| `http://auth0.com/oauth/grant-type/mfa-otp`           | 多要素認証 OTP グラントリクエスト                            |
| `http://auth0.com/oauth/grant-type/mfa-recovery-code` | 多要素認証リカバリーコードグラントリクエスト                         |
| `urn:ietf:params:oauth:grant-type:token-exchange`     | カスタムトークン交換グラントリクエスト                            |
| `urn:okta:params:oauth:grant-type:webauthn`           | WebAuthn グラントリクエスト                             |

<div id="how-it-works">
  ## 仕組み
</div>

次のシーケンス図は、Auth0 DPoP フローの概要を示しています。

<Frame>
  <img src="https://mintcdn.com/translations/mMSz-RNYLuOm2GmQ/docs/images/cdy7uua7fh8z/XoEV4y12QtnGwBPCiFbep/6744ab830ab2119664463f8c52fe6b02/Screenshot_2025-07-28_at_11.15.42_AM.png?fit=max&auto=format&n=mMSz-RNYLuOm2GmQ&q=85&s=c75e773654d080a4fc99cf1a6b0e0ebe" alt="" width="1256" height="600" data-path="docs/images/cdy7uua7fh8z/XoEV4y12QtnGwBPCiFbep/6744ab830ab2119664463f8c52fe6b02/Screenshot_2025-07-28_at_11.15.42_AM.png" />
</Frame>

1. Auth0 Authorization Server にアクセストークンをリクエストする際、クライアントアプリケーションは一意の暗号鍵ペアを生成し、公開キーを使って対応する秘密キーを保有していることを証明します。
2. クライアントアプリケーションは DPoP Proof JWT を生成し、それを Auth0 Authorization Server の /token エンドポイントに送信します。
3. Auth0 Authorization Server は DPoP Proof JWT を検証し、有効であればアクセストークンを発行して、クライアントの公開キーに紐付けます。
4. Customer API を呼び出す前に、クライアントアプリケーションは新しい DPoP Proof JWT を生成し、トークンに紐付けられた秘密キーを保有していることを証明します。クライアントアプリケーションは、DPoP Proof JWT と sender-constrained アクセストークンをリソースサーバーに送信します。
5. リソースサーバーは DPoP Proof JWT を検証し、トークンの正当な所有者、つまり元のクライアントアプリケーションだけが、それを使って保護されたリソースに正常にアクセスできることを確認します。リフレッシュトークンからアクセストークンをリクエストする場合、クライアントアプリケーションは新しい DPoP Proof JWT を生成し、リフレッシュトークンがクライアントの公開キーに紐付けられるようにします。

<div id="sender-constrain-tokens-using-dpop-in-auth0">
  ## Auth0 で DPoP を使用してトークンに送信者拘束を適用する
</div>

次の図は、Auth0 で DPoP を使用してトークンに送信者拘束を適用するエンドツーエンドのフローを示しています。

<Frame>
  <img src="https://mintcdn.com/translations/c0RQ9V0YAcT0-8l5/docs/images/cdy7uua7fh8z/7sonusMpvBMP0fDS6OkXSA/7cd0d50ffc44167f52f7e29d7f723d4a/Screenshot_2025-07-28_at_11.17.43_AM.png?fit=max&auto=format&n=c0RQ9V0YAcT0-8l5&q=85&s=5a29d50e0213083c972c089629ca9b2f" alt="" width="1272" height="806" data-path="docs/images/cdy7uua7fh8z/7sonusMpvBMP0fDS6OkXSA/7cd0d50ffc44167f52f7e29d7f723d4a/Screenshot_2025-07-28_at_11.17.43_AM.png" />
</Frame>

以下のセクションでは、実装用のコードサンプルとともに、Auth0 での DPoP フローを順を追って説明します。

* [前提条件](#prerequisites)
* [ステップ 1: クライアントアプリケーションが DPoP キーペアを生成する](#step-1-client-application-generates-a-dpop-key-pair)
* [ステップ 2: クライアントアプリケーションが DPoP Proof JWT を作成する](#step-2-client-application-creates-a-dpop-proof-jwt)
* [ステップ 3: クライアントアプリケーションが DPoP にバインドされたトークンを要求する](#step-3-client-application-requests-a-dpop-bound-token)
* [ステップ 4: Auth0 Authorization Server が DPoP Proof JWT を検証する](#step-4-auth0-authorization-server-validates-the-dpop-proof-jwt)
* [ステップ 5: クライアントアプリケーションが DPoP にバインドされたトークンと DPoP Proof JWT を使って API を呼び出す](#step-5-client-application-calls-api-with-the-dpop-bound-token-and-dpop-proof-jwt)
* [ステップ 6: DPoP を使用したトークンのリフレッシュを処理する](#step-6-handle-token-refresh-with-dpop)

<div id="prerequisites">
  ## 前提条件
</div>

開始する前に、次の点を確認してください。

* クライアントアプリケーションとリソースサーバーに対して、[送信者拘束を設定](/docs/ja-jp/secure/sender-constraining/configure-sender-constraining)していること。

<div id="step-1-client-application-generates-a-dpop-key-pair">
  ## ステップ1: クライアントアプリケーションがDPoPキーペアを生成する
</div>

DPoPでは、クライアントアプリケーションは非対称暗号のキーペアを生成する必要があります。Auth0は、ES256キーなどの楕円曲線暗号の使用をサポートしています。このキーペアはクライアントアプリケーションごとに固有のもので、たとえばハードウェアで保護されたキーストアに安全に保管する必要があります。

クライアントアプリケーションは秘密鍵を厳重に保持しつつ、[ステップ2](#step-2-client-application-creates-a-dpop-proof-jwt)で「Proof of Possession」として機能するDPoP Proof JSON Web トークン (JWT) に公開鍵を含めます。

<div id="step-2-client-application-creates-a-dpop-proof-jwt">
  ## ステップ 2: クライアントアプリケーションが DPoP Proof JWT を作成する
</div>

Auth0 Authorization Server の `/token` エンドポイントに DPoP にバインドされたアクセストークンをリクエストする前に、クライアントアプリケーションは DPoP Proof JWT を作成する必要があります。DPoP Proof JWT は、クライアントの秘密キーで署名された JSON Web トークン (JWT) で、「Proof of Possession (所持証明) 」として機能します。

DPoP Proof JWT は、JWT ヘッダーと、トークンリクエストに関連する[クレーム](/docs/ja-jp/secure/tokens/json-web-tokens/json-web-token-claims)を含むペイロードで構成されます。

<div id="jwt-header-claims">
  ### JWTヘッダーのクレーム
</div>

| DPoP Proof JWT クレーム | 説明                                    |
| ------------------- | ------------------------------------- |
| `typ`               | `dpop+jwt` に設定します。                    |
| `alg`               | `RS256` や `ES256` などの非対称署名アルゴリズムです。   |
| `jwk`               | クライアントの公開キーを表す JSON Web Key (JWK) です。 |

<div id="jwt-payload-claims">
  ### JWT ペイロードクレーム
</div>

| DPoP Proof JWT クレーム | 説明                                                                                                                                                         |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jti`               | リプレイ攻撃を防ぐための、JWT の一意の識別子です。                                                                                                                                |
| `htm`               | DPoP 証明の対象となるリクエストの HTTP メソッドです。たとえば、トークンリクエストでは `POST`、API 呼び出しでは `GET` です。                                                                               |
| `htu`               | DPoP Proof JWT の対象となるリクエストの HTTP URI です。フラグメントとクエリパラメータは含みません。たとえば、`https://api.example.com/data?param=1#section1` は `https://api.example.com/data` になります。 |
| `iat`               | JWT の作成時刻を表すタイムスタンプです。                                                                                                                                     |
| `ath`               | アクセストークンを使用する API 呼び出しでは、アクセストークンの SHA-256 ハッシュを base64url エンコードした値です。                                                                                     |
| `nonce`             | `nonce` を必要とするパブリッククライアントでは、サーバーから提供される `nonce` 値です。                                                                                                       |

クライアントアプリケーションで DPoP Proof JWT を作成したら、[Step 1](#step-1-client-application-generates-a-dpop-key-pair) で生成した秘密キーを使って DPoP Proof JWT に署名します。

以下のコードサンプルは、クライアントアプリケーションで DPoP Proof JWT を作成して署名する方法を示しています。

```jsx lines theme={null}
import { generateKeyPairSync, randomBytes } from 'node:crypto';
import jwt from 'jsonwebtoken';

// DPoP キーペアを生成する
const keyPair = generateKeyPairSync('ec', {
  namedCurve: 'P-256',
});

// トークンリクエスト用の DPoP Proof JWT を構築する
const jti = randomBytes(16).toString('base64url');
const jwk = keyPair.publicKey.export({ format: 'jwk' });
const dpopHeader = jwt.sign({
    jti,
    htm: 'POST',
    htu: 'https://[TENANT]/oauth/token',
    iat: Date.now() / 1000,
  },
  keyPair.privateKey,
  {
    algorithm: 'ES256',
    header: {
      typ: 'dpop+jwt',
      jwk,
    },
  });
```

<div id="step-3-client-application-requests-a-dpop-bound-token">
  ## ステップ 3: クライアントアプリケーションが DPoP-bound token をリクエストする
</div>

クライアントアプリケーションが Auth0 Authorization Server の `/token` エンドポイントに access token をリクエストする際は、リクエストの HTTP ヘッダーに DPoP Proof JWT を含めます。

```http lines theme={null}
DPoP: {DPoP_proof_JWT_value}
```

以下は、DPoP Proof JWT が設定された DPoP HTTPヘッダーを含むアクセストークンリクエストの例です。

```http lines theme={null}
POST /oauth/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: {DPoP Proof JWT}
Authorization: Basic Y2xpZW50MTIzOm15c2VjcmV0
Cache-Control: no-cache
grant_type=client_credentials&client_id=client123
```

クライアントアプリケーションで DPoP バインド アクセストークンをリクエストする方法を実装するには、次のコードサンプルを使用します。このサンプルでは、以下を行います。

1. 署名付き DPoP Proof JWT を使用して、DPoP HTTP ヘッダーに値を設定します。
2. 署名付き DPoP Proof JWT を含む DPoP HTTP ヘッダーを、`/token` エンドポイントへのアクセストークンリクエストで送信します。
3. Auth0 認可サーバーからのレスポンスを処理します。

```javascript lines theme={null}
// /oauth/token エンドポイントにリクエストを送信する
// [...] を実際の grant_type、client_id、テナント URL に置き換えてください
const response = await fetch('https://[TENANT]/oauth/token', {
    method: 'POST',
    body: new URLSearchParams({
      grant_type: '...',
      client_id: '...',
      // その他のボディパラメータをここに記述
    }),
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      // DPoP ヘッダーを追加する
      dpop: dpopHeader
    }
  });

// Auth0 認可サーバーからのレスポンスを処理する
const result = await response.json();
console.log('Initial token request result:', result);
```

<div id="public-clients">
  ### パブリッククライアント
</div>

シングルページアプリケーション (SPA) やモバイルアプリなどのパブリッククライアントが DPoP にバインドされたアクセストークンをリクエストする場合、`client secret` やその他のクライアント認証パラメーターは使用できません。この場合、[RFC 9449](https://datatracker.ietf.org/doc/html/rfc9449#section-8) に従い、Auth0 はクライアントアプリケーションが DPoP Proof JWT を直近で生成したことを確認するため、DPoP HTTP `header` に <Tooltip tip="Nonce: リプレイ攻撃を検出して防ぐために、認証プロトコルで一度だけ発行される任意の数値。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=nonce">nonce</Tooltip> 値が含まれていることを求めます。これは想定どおりの動作であり、認可サーバーが DPoP proof の新しさを確認し、その proof を使用できる時間を限定できるようにするためです。

パブリッククライアントが `/token` `request` を行う際に、DPoP HTTP `header` に `nonce` 値を含めない場合、Auth0 は `HTTP 400` コードと、次のようなエラーメッセージを返します。

```js lines theme={null}
{
  error: 'use_dpop_nonce',
  error_description: '認証サーバーはDPoP証明にnonceを要求しています'
}
```

Auth0 は、レスポンスヘッダーに `DPoP-Nonce` ヘッダーを含めます。これは、[DPoP specification](https://datatracker.ietf.org/doc/html/rfc9449) で定義されている標準の「challenge-response」フローに従ったものです。`DPoP-Nonce` ヘッダーの値を使用して DPoP proof を再生成し ([Step 2](#step-2-client-application-creates-a-dpop-proof-jwt) と同様) 、その値を含む `nonce` クレームを追加したうえで、`/token` エンドポイントへのリクエストを再送信する必要があります。

次のコードサンプルは、パブリッククライアントから `nonce` クレームを含む `/token` リクエストを送信し、その後再試行する際のエンドツーエンドのフローを示しています。

```jsx lines expandable theme={null}
import { generateKeyPairSync, randomBytes } from 'node:crypto';
import jwt from 'jsonwebtoken';

// DPoP キーペアを生成する
const keyPair = generateKeyPairSync('ec', {
  namedCurve: 'P-256',
});

/**
 * DPoP Proof JWT を生成するヘルパー関数。
 * @param {string} method - HTTP メソッド（例: 'POST', 'GET'）。
 * @param {string} url - リクエストの完全な URL。
 * @param {string} [nonce] - サーバーから取得するオプションの DPoP-Nonce 値。
 * @param {string} [accessToken] - 'ath' クレームのハッシュ化に使用するオプションのアクセストークン。
 * @returns {string} 署名済みの DPoP Proof JWT。
 */
function generateDPoPHeader(method, url, nonce) {
  const jti = randomBytes(16).toString('base64url');
  const jwk = keyPair.publicKey.export({ format: 'jwk' });
  return jwt.sign({
      jti,
      htm: method,
      htu: url,
      iat: Date.now() / 1000,
      nonce
    },
    keyPair.privateKey,
    {
      algorithm: 'ES256',
      header: {
        typ: 'dpop+jwt',
        jwk,
      },
    });
  }

// 最初はノンスなしでアクセストークンをリクエストする 
async function getTokens(nonce) {
  const response = await fetch('https://[TENANT]/oauth/token', {
      method: 'POST',
      body: new URLSearchParams({
        grant_type: '...',
        client_id: '...',
        // その他のボディパラメータをここに記述
      }),
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        dpop: generateDPoPHeader('POST', 'https://[TENANT]/oauth/token', nonce),
      }
    });

  const result = await response.json();
  return { response, result };
}

// 最初のトークンリクエスト時はノンスがない
let { response, result } = await getTokens(); 
console.log('Initial token request result:', result);

if (response.status === 400 && result.error === 'use_dpop_nonce') {
  const nonce = response.headers.get('dpop-nonce');

  console.log('Received nonce:', nonce);

  // ノンスを使用して再試行する
  ({ response, result } = await getTokens(nonce)); 

  console.log('Tokens received:', result);
}
```

<div id="step-4-auth0-authorization-server-validates-the-dpop-proof-jwt">
  ## ステップ 4: Auth0 Authorization Server が DPoP Proof JWT を検証する
</div>

Auth0 Authorization Server はトークンリクエストを受信すると、次の処理を行います。

* DPoP Proof JWT、その公開キー、署名を抽出します。
* 提供された公開キーを使用して署名を検証します。
* `htm`、`htu`、`jti,`、`iat` の各クレームを検証します。
* 有効であれば、アクセストークンを発行します。Auth0 Authorization Server は、確認用クレーム `cnf` をアクセストークンに含めます。`cnf` クレームには、DPoP Proof JWT から取得した公開キーの thumbprint (ハッシュ) が含まれます。これをアクセストークンに含めることで、Auth0 Authorization Server はそのアクセストークンを特定の公開キーに関連付けます。つまり、アクセストークンを “sender-constrains” します。
* トークンレスポンスでは、`Authorization` ヘッダーの `token_type` を `Bearer` ではなく `DPoP` に設定します。通常、アクセストークンを `Authorization` ヘッダーで渡す場合、`token_type` は `Bearer` に設定されます。しかし、ここでは DPoP を使用して公開キーに関連付けられたアクセストークンを渡すため、代わりに `DPoP` に設定されます。
* その後、Auth0 Authorization Server は DPoP sender-constrained アクセストークンをクライアントアプリケーションに発行します。

<div id="step-5-client-application-calls-api-with-the-dpop-bound-token-and-dpop-proof-jwt">
  ## ステップ 5: クライアントアプリケーションが DPoP-bound token と DPoP Proof JWT を使用して API を呼び出す
</div>

DPoP を強制するリソースサーバーに対する API 呼び出しごとに、クライアントアプリケーションは DPoP-bound access token と新しい DPoP Proof JWT の両方を提示する必要があります。

DPoP は、すべての API リクエストで DPoP Proof JWT を必須にすることで、秘密キーを保持するクライアントアプリケーションだけがアクセストークンを使用できるようにします。

新しい API リクエストでは、クライアントアプリケーションは次のことを行います。

1. 次のクレームを含む新しい DPoP Proof JWT を生成します。

* `htm` クレームは、`GET` や `POST` などの API リクエストの `HTTP` メソッドです。
* `htu` クレームは、API リクエストの URI です。
* `ath` クレームは、[ステップ 3](#step-3-client-application-requests-a-dpop-bound-token) で受け取った DPoP-bound access token の base64url エンコードされた SHA-256 ハッシュです。

2. クライアントの秘密キーを使って、新しい DPoP Proof JWT に暗号学的に署名します。

3. `DPoP` 認証スキームを使用して、`Authorization` ヘッダーに DPoP-bound access token を含めます。

```javascript lines theme={null}
// DPoP スキームは認可サーバーから受け取った token_type に合わせます
Authorization: DPoP {access_token}
```

4. 新たに生成した DPoP Proof JWT を `DPoP` HTTP ヘッダーに含めます:

```http lines theme={null}
DPoP: {new_dpop_proof_jwt}
```

`DPoP` HTTPヘッダーには、追加の`ath`クレームを含める必要があります。`ath`クレームは、発行されたアクセストークンのSHA256ハッシュをbase64urlエンコードしたものです。

リソースサーバーは次の処理を行います。

* APIリクエストを受信し、アクセストークン、DPoP Proof JWT、公開キー、署名を抽出します。
* `jwk`ヘッダー内の公開キーを使用して、DPoP Proof JWTの署名を検証します。
* `htm`、`htu`、`jti`、`iat`、`ath`の各クレームを検証します。
* DPoP Proof JWTの`jwk`ヘッダーで示された公開キーが、アクセストークン内の`cnf.jkt`クレームによってアクセストークンに関連付けられた公開キーと一致することを検証します。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  `jti`のリプレイ保護の実装はリソースサーバーの責任です。すべてのAuth0 SDKsがデフォルトで`jti`のリプレイ保護を強制するわけではありません。
</Callout>

すべてのチェックに成功した場合、リソースサーバーはリクエストを認可します。そうでない場合は、リクエストを拒否し、アクセスを拒否します。

次のコードサンプルでは、DPoPを使用してAuth0からアクセストークンをリクエストし、その後、DPoPにバインドされたアクセストークンを使用して`/userinfo`エンドポイントを呼び出します。

```jsx lines expandable theme={null}
import { generateKeyPairSync, randomBytes, createHash } from 'node:crypto';
import jwt from 'jsonwebtoken';

const keyPair = generateKeyPairSync('ec', {
  namedCurve: 'P-256',
});

function hashToken(token) {
  return createHash('sha256').update(token).digest('base64url');
}

function generateDPoPHeader(method, url, nonce, accessToken) {
  const jti = randomBytes(16).toString('base64url');
  const jwk = keyPair.publicKey.export({ format: 'jwk' });
  return jwt.sign({
      jti,
      htm: method,
      htu: url,
      iat: Date.now() / 1000,
      nonce,

      // 必要に応じて、アクセストークンのハッシュを含む `ath` クレームを追加する
      ...(accessToken ? { ath: hashToken(accessToken) } : {}),
    },
    keyPair.privateKey,
    {
      algorithm: 'ES256',
      header: {
        typ: 'dpop+jwt',
        jwk,
      },
    });
  }

async function getTokens(nonce) {
  const response = await fetch('https://[TENANT]/oauth/token', {
      method: 'POST',
      body: new URLSearchParams({
        grant_type: '...',
        client_id: '...',
        // その他のボディパラメータをここに記述
      }),
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        dpop: generateDPoPHeader('POST', 'https://test1.local.dev.auth0.com/oauth/token', nonce),
      }
    });

  const result = await response.json();
  return { response, result };
}

// 初回実行時はnonceを持っていない
let { response, result } = await getTokens(); 
console.log('Initial token request result:', result);

if (response.status === 400 && result.error === 'use_dpop_nonce') {
  const nonce = response.headers.get('dpop-nonce');
  console.log('Received nonce:', nonce);
  ({ response, result } = await getTokens(nonce)); // nonceを使って再試行
  console.log('Tokens received:', result);
}

// DPoPを使って /userinfo を呼び出す
const userInfoResponse = await fetch('https://[TENANT]/userinfo', {
  method: 'GET',
  headers: {
    // DPoP認可スキームを使ってアクセストークンを渡す
    Authorization: `DPoP ${result.access_token}`,

    // DPoPヘッダーを含める（今回はアクセストークンのハッシュ付き）
    dpop: generateDPoPHeader('GET', 'https://[TENANT]/userinfo', nonce, result.access_token),
  },
});

console.log('User info response status:', userInfoResponse.status);
console.log('User info result:', await userInfoResponse.json());
```

<div id="step-6-handle-token-refresh-with-dpop">
  ## ステップ 6: DPoP を使用してトークンの更新を処理する
</div>

DPoP にバインドされたアクセストークンの有効期限が切れた場合は、新しいアクセストークンを取得するために <Tooltip tip="リフレッシュトークン: ユーザーに再度ログインを求めることなく、新しいアクセストークンを取得するために使用されるトークン。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=refresh+token">リフレッシュトークン</Tooltip> を使用できます。リフレッシュトークンのリクエストには、元のトークンリクエストで使用したものと同じキーペアで生成した DPoP Proof JWT が必要です。

以下では、Auth0 における DPoP を使用したリフレッシュトークンのフローについて説明します。

クライアントアプリケーションは次を行います。

* Auth0 認可サーバーの `/token` エンドポイントに、リフレッシュトークンのリクエストを送信します。
* リフレッシュトークンのリクエスト用に DPoP Proof JWT を生成します ([ステップ 2](#step-2-client-application-creates-a-dpop-proof-jwt) と同様ですが、`htm` は `POST`、`htu` は <Tooltip tip="トークンエンドポイント: プログラムによってトークンをリクエストするために認可サーバーで使用されるエンドポイント。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=token+endpoint">トークンエンドポイント</Tooltip> の URI です) 。
* `DPoP` HTTP ヘッダーに DPoP Proof JWT を含めます。

Auth0 認可サーバーは次を行います。

* DPoP Proof JWT を検証し ([ステップ 4](#step-4-auth0-authorization-server-validates-the-dpop-proof-jwt) と同様) 、新しい DPoP バインドアクセストークンを発行します。

<div id="important-considerations">
  ## 重要な考慮事項
</div>

クライアントアプリケーションに DPoP を実装する際は、次の点を考慮してください。

* **秘密キーのセキュリティ:** DPoP 実装の安全性はクライアントの秘密キーの安全性に依存するため、不正アクセスから保護する必要があります。秘密キーは、ハードウェアに裏打ちされた領域で生成および保管し、エクスポート不可に設定する必要があります。
* **リプレイ保護 (**`jti`\*\* と **`dpop-nonce`**):\*\* DPoP Proof JWT の `jti` クレームは、[`/userinfo`](https://auth0.com/docs/api/authentication/user-profile/get-user-info) エンドポイントなどの保護されたリソースに対するリプレイ攻撃の防止に役立ちます。Auth0 Authorization Server はレスポンスで `DPoP-Nonce` HTTP ヘッダーを返し、公開クライアントはリプレイ保護を強化するために、後続の DPoP Proof JWT にこれを `nonce` クレームとして含める必要があります。
* **レート制限:** DPoP のチャレンジレスポンスフローでは、最初のリクエストの後にサーバーから提供された nonce を使って再試行が必要になる場合があるため、各やり取りは実質的に [Auth0 テナントのレート制限](https://auth0.com/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy) に対して 2 回のリクエストとしてカウントされます。アプリケーションのリクエスト量がこのオーバーヘッドを考慮していることを確認してください。
* **エラー処理:** `invalid_dpop_proof` や `use_dpop_nonce` など、Auth0 Authorization Server またはリソースサーバーから返される DPoP 固有のエラーを処理するロジックは、お客様側で実装する必要があります。
* **クライアントの種類:** クライアントシークレットを安全に保管できない Single Page Applications (SPAs) やモバイルアプリなどの公開クライアントには DPoP を使用してください。<Tooltip tip="Confidential Client: 信頼できるバックエンドサーバーを使用して資格情報を安全に保持できるクライアント（アプリケーション）です。例としては、安全なバックエンドを備えた web app や、machine-to-machine (M2M) アプリケーションがあります。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=confidential+clients">機密クライアント</Tooltip>には、クライアントシークレットを持つバックエンドサービスなどが含まれます。DPoP はセキュリティをさらに強化しますが、これらにはすでに他の sender-constraining の仕組みがあります。
* **パフォーマンス:** API 呼び出しごとに DPoP Proof JWT を生成して署名すると、わずかなオーバーヘッドが追加されるため、クライアントアプリケーションの暗号処理が効率的であることを確認してください。
* **キーのローテーション:** セキュリティを強化するために、DPoP のキー ペアをローテーションする strategy を実装してください。同じセッションでは必ず同じキー ペアを使用してください。
* **永続化:** セッションを維持し、DPoP-bound access token を再利用する必要があるクライアントアプリケーション (長期間利用される SPA など) では、アプリケーションの再読み込み後も、最初に生成したキー ペアを安全に保存し、再取得できるようにしてください。新しいキー ペアが生成されたり、別のキー ペアが使用されたりすると、DPoP-bound access token は元のペアの公開キーに暗号学的に結び付けられているため無効になります。たとえば、ブラウザーの `IndexedDB` やモバイルアプリの安全なストレージにキー ペアを保存できます。

<div id="learn-more">
  ## 詳細はこちら
</div>

* [送信者制約を設定する](/docs/ja-jp/secure/sender-constraining/configure-sender-constraining)
