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

# Webアプリにステップアップ認証を設定する

> 多要素認証（MFA）を使用してユーザーがWebアプリにログインしたかどうかを、IDトークンを検証することで確認する方法を学びましょう。

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

ステップアップ認証を使うと、さまざまなタイプのリソースへのアクセスを許可するアプリケーションが、機密情報にアクセスしたり特定のトランザクションを実行したりするユーザーに、より強力なメカニズムを使用して認証するよう要求できます。

例えば、ユーザーは、多要素認証（<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=multifactor-authentication" tip="多要素認証（MFA）: ユーザー名とパスワードに加えて、SMS経由のコードなどの要素を使用するユーザー認証プロセス。" cta="用語集の表示">MFA</Tooltip>）を使用して本人確認を行った後でなければ、機密データを含むビューへのアクセスやパスワードのリセットが許可されない場合があります。

Webアプリでステップアップ認証を実行するには、Webアプリが要求した際にユーザーにMFAによる認証を求めるアクションを作成し、ユーザーが制限されたページにアクセスしようとした際にMFAに対するIDトークンクレームをチェックし、MFAがそのクレームに含まれていない場合はユーザーにチャレンジを送信するようにします。

## MFAのIDトークンを検証する

ユーザーがログインすると、ユーザーのセッションに関連する情報が含まれた[IDトークン](/docs/ja-jp/secure/tokens/id-tokens/get-id-tokens)がクレームとして渡されます。関連するクレームは、ログイン時に使用された認証方法を表す文字列のJSON配列である`amr`（認証方法参照）です。これはIDトークンのペイロードに示され、値`mfa`を含んでいる必要があります。

その値には、事前に定義された[認証方法参照値](https://tools.ietf.org/html/rfc8176)が含まれることがあります。この値には`mfa`以外のクレームを含めることができるため、検証時には、その存在をテストするとともに、`mfa`の値が含まれているか内容を調べる必要があります。

制限されたページにユーザーがアクセスしようとし、トークンが、ユーザーがMFAで認証されていないことを示した場合、アクションを使用してMFAをトリガーするように設定した認証を再トリガーすることができます。ユーザーが2つ目の要素を入力すると、`amr`クレームを含む新しいIDトークンが生成され、アプリに送信されます。

1. [IDトークンを取得します](/docs/ja-jp/secure/tokens/id-tokens/get-id-tokens)。
2. このトークンの署名を検証します。これは、トークンの送信者が自称のとおりであることを検証し、メッセージが途中で変更されていないことを保証するために使用されます。
3. 以下のクレームを検証します。

   | クレーム  | 説明                                                                                                         |
   | ----- | ---------------------------------------------------------------------------------------------------------- |
   | `exp` | トークンの有効期限                                                                                                  |
   | `iss` | トークン発行者                                                                                                    |
   | `aud` | トークンの意図された受信者                                                                                              |
   | `amr` | `amr`がペイロードに存在しないか、`mfa`という値を含まない場合、ユーザーはMFAでログインしませんでした。`amr`がペイロードに存在し、`mfa`という値を含む場合、ユーザーはMFAでログインしました。 |

#### AMRクレームの例外

次の使用例を除き、`amr`クレームは必須です。

1. ホスト型ログインフローでは、ユーザーがMFAチャレンジに合格した場合にのみ、`amr`クレームがIDトークンに挿入されます。アプリがサイレント認証を使用しているか、または新たに発行されたIDトークン用のリフレッシュトークンを使用している場合、ユーザーが事前にMFAによるログインを完了しているため、`amr`クレームは存在しません。
2. MFA APIが発行したトークンに`amr`クレームは含まれていません。`amr`クレームは、ユーザーがIDトークンを受け取る際に使用された認証方法にフラグを設定します。MFA API認証プロセスでは、アプリケーションが認証フローを制御し、必要に応じてMFAを強制できます。

以下の例では、ユーザーがMFAで認証した場合とそうでない場合のIDトークンのペイロードに含まれる可能性のある値を比較できます。

### 例：MFAを使った値

export const codeExample1 = `{
    "iss": "https://{yourDomain}/",
    "sub": "auth0|1a2b3c4d5e6f7g8h9i",
    "aud": "{yourClientId}",
    "iat": 1522838054,
    "exp": 1522874054,
    "acr": "http://schemas.openid.net/pape/policies/2007/06/multi-factor",
    "amr": [
        "mfa"
    ]
}`;

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

### 例：MFAを使っていない値

export const codeExample2 = `{
    "iss": "https://{yourDomain}/",
    "sub": "auth0|1a2b3c4d5e6f7g8h9i",
    "aud": "{yourClientId}",
    "iat": 1522838054,
    "exp": 1522874054
}`;

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

## シナリオ：プッシュ通知付きの給与データ

次のシナリオでは、Webアプリがユーザー名とパスワードでユーザーを認証します。給与データを表示する特定の画面にアクセスしたいユーザーは、Guardianのプッシュ認証で認証を受ける必要があります。

### 前提条件

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

* [Webアプリを登録する](/docs/ja-jp/get-started/auth0-overview/create-applications/regular-web-apps)。
* [データベース接続を作成する](https://manage.auth0.com/#/connections/database)。
* [MFAを有効](/docs/ja-jp/secure/multi-factor-authentication/enable-mfa)にしてプッシュ通知を使用する。

### アクションを作成する

Webアプリが要求した際に、MFAによる認証のチャレンジをユーザーに送信するアクションを作成します。[［Dashboard］ > ［Actions（アクション）］ > ［Flows（フロー）］](https://manage.auth0.com/#/actions/flows)に移動し、以下の内容を含むアクションを作成します。

```javascript lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
 const CLIENTS_WITH_MFA = ['REPLACE_WITH_{yourClientId}'];
 // run only for the specified clients
 if (CLIENTS_WITH_MFA.includes(event.client.client_id)) {
 // ask for MFA only if the web app said so in the authentication request
 if (event.transaction?.acr_values.includes('http://schemas.openid.net/pape/policies/2007/06/multi-factor')) {
 api.multifactor.enable('any', { allowRememberBrowser: false });
 }
 }
}
```

* `CLIENTS_WITH_MFA`変数には、このアクションを適用するアプリケーションのクライアントIDが含まれています。必要なければ、この変数（および、その後の`if`条件文）は削除できます。
* `event.transaction.acr_values`プロパティは、認証コンテキストクラス参照（`acr`）を含む文字列の配列です。これはオプションのプロパティで、アプリケーションが認可サーバーへの認証要求に含める場合にのみ存在します。この例では、当社のWebアプリは認証要求にこのプロパティを含めますが、MFAでまだ認証されていないユーザーが給与情報にアクセスを試みた場合に限られます。当社のWebアプリにこれが含まれている場合、`http://schemas.openid.net/pape/policies/2007/06/multi-factor`の値が設定されます。これは、認可サーバーにMFAを要求することを示しており、コードで設定されている`api.multifactor`プロパティの値により、テナントで構成されている利用可能な方法のいずれかを使用してユーザーにMFAチャレンジを送信します。`api.multifactor.enable()`に関する詳細については、「[アクションのトリガー：ログイン後のAPIオブジェクト](/docs/ja-jp/customize/actions/explore-triggers/password-reset-triggers/post-challenge-trigger/post-challenge-api-object)」をお読みください。
* `http://schemas.openid.net/pape/policies/2007/06/multi-factor`ポリシーでは、エンドユーザーが複数の認証要素（MFA）を提供することで<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=openid" tip="OpenID: アプリケーションがログイン情報を収集および保存することなくにユーザーのIDを検証できるようにする認証用のオープン標準。" cta="用語集の表示">OpenID</Tooltip>プロバイダーに認証を行う認証メカニズムを定義しています。詳細については、[OpenIDプロバイダー認証ポリシー拡張機能1.0](https://openid.net/specs/openid-provider-authentication-policy-extension-1_0.html)をお読みください。

### アプリを構成

ユーザーが制限付きの給与情報ページにアクセスしようとした際に、MFAを使用して認証済みであることを確認するようにアプリを設定します。（ユーザーがMFAで認証済みの場合、IDトークンのクレームには、値が`mfa`である`amr`クレームが含まれます）。ユーザーがすでにMFAで認証済みの場合、Webアプリは制限付きのページを表示します。そうでない場合Webアプリは、`acr_values`パラメーターを含む新しい認証要求を送信します。このパラメーターの値は
`http://schemas.openid.net/pape/policies/2007/06/multi-factorで、`これによってアクションがトリガーされます。

このシナリオにおけるWebアプリは認証に[認可コードフロー](/docs/ja-jp/get-started/authentication-and-authorization-flow/authorization-code-flow)を使用するため、要求は以下のようになります。

export const codeExample3 = `https://{yourDomain}/authorize?
        audience=https://{yourDomain}/userinfo&
        scope=openid&
        response_type=code&
        client_id={yourClientId}&
        redirect_uri={https://yourApp/callback}&
        state={yourOpaqueValue}&
        acr_values=http://schemas.openid.net/pape/policies/2007/06/multi-factor`;

<AuthCodeBlock children={codeExample3} language="text" lines />

ユーザーがMFAで認証すると、Webアプリは認可コードを受け取ります。この認可コードは、新しいIDトークンと交換する必要があります。このIDトークンには、値が`mfa`の`amr`クレームが含まれているはずです。IDトークン用のコードを交換する方法については、「[認可コードフローを使用してログインを追加する](/docs/ja-jp/get-started/authentication-and-authorization-flow/authorization-code-flow/add-login-auth-code-flow)」をお読みください。

### IDトークンを検証する

このシナリオでは、トークンの署名（`jwt.verify`）を検証し、トークンをデコードし、ペイロードに`amr`が含まれているかどうかを確認し、含まれている場合は結果をコンソールにログ出力する[JSON Webトークンサンプルコード](https://github.com/auth0/node-jsonwebtoken)を使用して検証を実行します。

export const codeExample4 = `const AUTH0_CLIENT_SECRET = '{yourClientSecret}';
const jwt = require('jsonwebtoken');

jwt.verify(id_token, AUTH0_CLIENT_SECRET, { algorithms: ['HS256'] }, function(err, decoded) {
  if (err) {
    console.log('invalid token');
    return;
  }

  if (Array.isArray(decoded.amr) && decoded.amr.indexOf('mfa') >= 0) {
    console.log('You used mfa');
    return;
  }

  console.log('you are not using mfa');
});`;

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

## もっと詳しく

* [IDトークン](/docs/ja-jp/secure/tokens/id-tokens)
* [ルールのユースケース](/docs/ja-jp/customize/rules/use-cases)
* [JSON Webトークン](/docs/ja-jp/secure/tokens/json-web-tokens)
* [APIのステップアップ認証を構成する](/docs/ja-jp/secure/multi-factor-authentication/step-up-authentication/configure-step-up-authentication-for-apis)
