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

> アクセストークンを調べることで、ユーザーが多要素認証でログインしたかどうかを API が確認する方法を学びます。

# API のステップアップ認証を設定する

ステップアップ認証を使用すると、異なる種類のリソースへのアクセスを許可するアプリケーションで、機密情報にアクセスしたり特定の取引を実行したりする際に、より強力な方法での認証をユーザーに要求できます。

たとえば、銀行アプリのユーザーは、<Tooltip tip="多要素認証 (MFA): SMS で送信されるコードなど、ユーザー名とパスワードに加えた認証要素を使用するユーザー認証プロセス。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=multi-factor+authentication">多要素認証</Tooltip> (MFA) で本人確認を済ませた場合にのみ、口座間の送金を許可されることがあります。

<Tooltip tip="オーディエンス: 発行されたトークンの audience を表す一意の識別子。トークン内では aud という名前で表され、その値には ID Token の場合は application (クライアント ID)、Access Token の場合は API (API Identifier) の ID が含まれます。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=audience">オーディエンス</Tooltip> が API の場合、Auth0 ではスコープ、<Tooltip tip="アクセストークン: API へのアクセスに使用される、不透明な文字列または JWT 形式の認可資格情報。" cta="用語集を表示" href="/docs/ja-jp/glossary?term=access+tokens">アクセストークン</Tooltip>、および [Actions](/docs/ja-jp/customize/actions) を使ってステップアップ認証を実装できます。アプリケーションが API の保護されたリソースにアクセスするには、アクセストークンを提示する必要があります。アクセスできるリソースは、アクセストークンに含まれる権限によって決まります。これらの権限は [scopes](/docs/ja-jp/get-started/apis/scopes/api-scopes) として定義されます。

<div id="validate-access-tokens-for-mfa">
  ## MFA 用のアクセストークンを検証する
</div>

スコープの確認に加えて、API では次のために[アクセストークンを検証](/docs/ja-jp/secure/tokens/access-tokens/validate-access-tokens)する必要があります。

* トークンの署名を検証する。これにより、トークンの送信者が名乗っている本人であることを確認し、送信中にメッセージが改ざんされていないことを確かめます。
* 標準クレームを検証する。

| クレーム  | 説明            |
| ----- | ------------- |
| `exp` | トークンの有効期限     |
| `iss` | トークンの発行者      |
| `aud` | トークンの想定された受信者 |

<div id="scenario-bank-transactions-with-push-notifications">
  ## シナリオ: プッシュ通知を使用する銀行取引
</div>

次のシナリオでは、アプリケーションがユーザー名とパスワードでユーザーを認証し、その後、口座残高をリクエストします。口座残高情報を取得する前に、ユーザーは Guardian のプッシュ認証要素で認証する必要があります。

銀行の API では、2 つの異なる認可レベルを受け付けることができます。1 つは口座残高の表示 (scope `view:balance`) 、もう 1 つは資金の振替 (scope `transfer:funds`) です。アプリケーションが API にユーザーの残高の取得をリクエストする場合、アクセストークンには `view:balance` スコープが含まれている必要があります。別の口座に送金する場合、アクセストークンには `transfer:funds` スコープが含まれている必要があります。

<div id="workflow">
  ### ワークフロー
</div>

1. ユーザーは、ユーザー名とパスワードによる認証を使ってアプリケーションにログインします。通常のログインでは、ユーザーは API とやり取りして残高を取得できます。つまり、ユーザーの認証後にアプリが受け取る アクセストークン には、`view:balance` スコープが含まれています。
2. アプリケーションは、アクセストークン を credentials として使用し、残高を取得するための request を API に送信します。
3. API は token を検証し、ユーザーが残高を確認できるよう、その情報をアプリケーションに返します。
4. ユーザーは、ある口座から別の口座に資金を振り替えたいと考えています。これは高額な transaction と見なされるため、`transfer:funds` スコープが必要です。アプリケーションは、同じ アクセストークン を使用して request を API に送信します。
5. API は token を検証しますが、token に必要な `transfer:funds` スコープが含まれていないため、アクセスを拒否します。
6. アプリケーションは Auth0 にリダイレクトされます。ここでは Action を使用して、高権限のスコープが要求されたため、ユーザーに MFA による認証を求めます。ユーザーが MFA での認証に成功すると、正しいスコープを含む新しい アクセストークン が生成され、response の一部としてアプリケーションに送信されます。
7. アプリケーションは、今度は `transfer:funds` スコープを含む新しい アクセストークン を使用して、再度資金振替の request を送信します。
8. API は token を検証し、それを破棄して処理を続行します。

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

このシナリオでは、Auth0 Dashboard で次の項目を設定する必要があります。

* [Single-Page Web App を登録する](/docs/ja-jp/get-started/auth0-overview/create-applications/single-page-web-apps)。
* [データベース接続を作成する](https://manage.auth0.com/#/connections/database)。
* [API を登録する](/docs/ja-jp/get-started/auth0-overview/set-up-apis)。`view:balance` と `transfer:funds` の 2 つのスコープを作成します。
* プッシュ通知を使用するには、[MFA を有効にする](/docs/ja-jp/secure/multi-factor-authentication/enable-mfa)。

<div id="create-an-action">
  ### Action を作成する
</div>

`transfer:funds` scope が要求されたときに、ユーザーに MFA 認証を求める Action を作成します。[Auth0 Dashboard > Actions > Flows](https://manage.auth0.com/#/actions/flows) に移動し、次の内容を含む Action を作成します。

```javascript theme={null}
{
exports.onExecutePostLogin = async (event, api) => {
  const CLIENTS_WITH_MFA = ['REPLACE_WITH_{yourClientId}'];
  // 指定されたクライアントに対してのみ実行する
  if (CLIENTS_WITH_MFA.includes(event.client.client_id)) {
    // transfer:funds スコープがリクエストされた場合にのみMFAを要求する
    if (event.transaction.requested_scopes.indexOf('transfer:funds') > -1)
      api.multifactor.enable('any', { allowRememberBrowser: false });
    }
  }
},
```

* `CLIENTS_WITH_MFA` 変数には、この Action を適用するアプリケーションの <Tooltip tip="クライアントID: Auth0 から登録済みリソースに付与される識別子。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=client+IDs">クライアントID</Tooltip> が含まれます。不要な場合は、これ (およびその後の `if` 条件文) を削除できます。
* `event.transaction.requested_scopes` プロパティには、認証リクエストで要求されたすべてのスコープが含まれます。ここに `transfer:funds` が含まれている場合は、`context.multifactor` プロパティを適切な値に設定して MFA を要求します。この例では、[push](/docs/ja-jp/secure/multi-factor-authentication/multi-factor-authentication-factors/configure-push-notifications-for-mfa) を使用して MFA を要求しています。

<div id="configure-app">
  ### アプリを設定する
</div>

ユーザーが資金移動という高額取引を実行しようとしているかどうかに応じて、アプリが API に適切な認証リクエストを送信するよう設定します。2 つの認証リクエスト (MFA あり / なし) の違いは、スコープ だけであることに注目してください。

* MFA あり:

  export const codeExample1 = ` https://{yourDomain}/authorize?
  audience=https://my-banking-api&
  scope=openid%20view:balance%20transfer:funds&
  response_type=id_token%20token&
  client_id={yourClientId}&
  redirect_uri={https://yourApp/callback}&
  nonce=NONCE&
  state=OPAQUE_VALUE`;

<AuthCodeBlock children={codeExample1} language="text" />

* MFA なし:

  export const codeExample2 = ` https://{yourDomain}/authorize?
  audience=https://my-banking-api&
  scope=openid%20view:balance&
  response_type=id_token%20token&
  client_id={yourClientId}&
  redirect_uri={https://yourApp/callback}&
  nonce=NONCE&
  state=OPAQUE_VALUE`;

<AuthCodeBlock children={codeExample2} language="text" />

| パラメーター          | 設定                                                                                                                                                                                                                                                        |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `audience`      | API の**識別子**に設定します ([API Settings](https://manage.auth0.com/#/apis/) で確認できます) 。ここでは `https://my-banking-api` を設定しています。                                                                                                                                    |
| `response_type` | レスポンスで ID Token と アクセストークン の両方を取得できるよう、`id_token token` に設定します。                                                                                                                                                                                           |
| `client_id`     | アプリケーションの クライアント ID に設定します ([Application Settings](https://manage.auth0.com/#/applications/\{yourClientId}/settings) で確認できます) 。                                                                                                                           |
| `redirect_uri`  | 認証後に Auth0 がリダイレクトする、アプリケーション内の URL に設定します ([Application Settings](https://manage.auth0.com/#/applications/\{yourClientId}/settings) で確認できます) 。                                                                                                           |
| `nonce`         | Auth0 からのレスポンスに含まれる、安全な文字列値に設定します。これは[トークンのリプレイ攻撃を防ぐために使用されます](/docs/ja-jp/get-started/authentication-and-authorization-flow/implicit-flow-with-form-post/mitigate-replay-attacks-when-using-the-implicit-flow)。また、`response_type=id_token token` では必須です。 |
| `state`         | Auth0 がアプリケーションにリダイレクトして戻す際に含める、不透明な値に設定します。この値は、CSRF 攻撃を防ぐためにアプリケーションで使用する必要があります。                                                                                                                                                                       |

<div id="configure-api">
  ### API を設定する
</div>

受信したトークンを検証し、認可された権限を確認できるように API を設定します。

1. API に 2 つのエンドポイントを設定します。
   `GET /balance`: 現在の残高を取得する
   `POST /transfer`: 資金を送金する
2. `Node.js` といくつかのモジュールを使用します。

   1. [express](https://expressjs.com/): Express Web アプリケーションフレームワークを追加します。
   2. [jwks-rsa](https://github.com/auth0/node-jwks-rsa): **JWKS** (JSON Web Key Set) endpoint から RSA 署名鍵を取得します。`expressJwtSecret` を使用すると、JWT header の `kid` に基づいて適切な署名鍵を `express-jwt` に渡す secret provider を生成できます。
   3. [express-jwt](https://github.com/auth0/express-jwt): `Node.js` アプリケーションで JWT token を使って HTTP request を認証できます。JWT を扱いやすくするさまざまな関数が用意されています。
   4. [express-jwt-authz](https://github.com/auth0/express-jwt-authz): アクセストークンに特定のスコープが含まれているかどうかを確認します。
3. dependencies をインストールします。
   `npm install express express-jwt jwks-rsa express-jwt-authz --save`
4. API endpoint を定義し、アクセストークンを検証するミドルウェア関数を作成して、そのミドルウェアで endpoint を保護します。`server.js` ファイルのコードは、次のサンプルスクリプトのようになります。

export const codeExample3 = `   // 依存関係を設定
    const express = require('express');
    const app = express();
    const jwt = require('express-jwt');
    const jwksRsa = require('jwks-rsa');
    const jwtAuthz = require('express-jwt-authz');

    // JWT を検証するためのミドルウェアを作成
    const checkJwt = jwt({
      // header 内の kid と、JWKS endpoint から提供される署名鍵に基づいて、署名鍵を動的に取得
      secret: jwksRsa.expressJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: \`https://{yourDomain}/.well-known/jwks.json\`
      }),

      // audience と issuer を検証
      audience: 'https://my-banking-api', // ご自身の API の audience に置き換えてください。Auth0 Dashboard > APIs で確認できます
      issuer: 'https://{yourDomain}/',
      algorithms: [ 'RS256' ] // token の署名には RS256 を使用します
    });

    // 残高取得用 endpoint を作成
    app.get('/balance', checkJwt, jwtAuthz(['view:balance']), function (req, res) {
      // ユーザーの残高を取得し、呼び出し元のアプリに返すコード
      res.status(201).send({message: "これは GET /balance endpoint です"});
    });


    // 資金送金用 endpoint を作成
    app.post('/transfer', checkJwt, jwtAuthz(['transfer:funds']), function (req, res) {
      // ある口座から別の口座へ資金を送金するコード
      res.status(201).send({message: "これは POST /transfer endpoint です"});
    });

    // localhost:8080 で API Server を起動
    app.listen(8080);
    console.log('http://localhost:8080 で待ち受けています');
`;

<AuthCodeBlock children={codeExample3} language="javascript" />

APIがリクエストを受け取るたびに、次の処理が行われます。

1. エンドポイントが `checkJwt` ミドルウェアを呼び出します。
   2\. `express-jwt` がトークンをデコードし、request、header、payload を `jwksRsa.expressJwtSecret` に渡します。
   3\. `jwks-rsa` が JWKS エンドポイントからすべての署名鍵をダウンロードし、その中にアクセストークンの header 内の `kid` と一致するものがあるかどうかを確認します。受信した `kid` に一致する署名鍵が1つもない場合は、エラーがスローされます。一致するものがあれば、適切な署名鍵を `express-jwt` に渡します。
   4\. `express-jwt` はその後の独自のロジックに従って、トークンの署名、有効期限、audience、issuer を検証します。
   5\. `jwtAuthz` は、エンドポイントが必要とする スコープ がアクセストークンに含まれているかどうかを確認します。指定された スコープ がアクセストークンに含まれていない場合、リクエストは 403 エラーで拒否されます。

<div id="learn-more">
  ## 詳しく見る
</div>

* [アクセストークン](/docs/ja-jp/secure/tokens/access-tokens)
* [アクセストークンを検証する](/docs/ja-jp/secure/tokens/access-tokens/validate-access-tokens)
* [Actionのユースケース](/docs/ja-jp/customize/actions/use-cases)
* [APIスコープ](/docs/ja-jp/get-started/apis/scopes/api-scopes)
* [Webアプリのステップアップ認証を設定する](/docs/ja-jp/secure/multi-factor-authentication/step-up-authentication/configure-step-up-authentication-for-web-apps)
