メインコンテンツへスキップ
認証トランザクションの前に、ログイン後のアクションを使ってユーザーをリダイレクトすることができます。カスタム認証フローを実装して、標準のログインフォームにはない追加のユーザー操作に対応できるようになります。 リダイレクトは、Auth0でカスタムの多要素認証(MFA)を実行するためによく使用されますが、以下の目的にも使用できます。
  • カスタムのプライバシーポリシーへの同意、利用規約、データ開示のフォームを使用できるようにする
  • 追加で必要なプロファイルデータを安全に一度だけ収集する
  • Microsoft Entra IDのリモートユーザーがパスワードを変更できるようにする
  • ユーザーが未知の場所からログインする際に、追加で検証を求める
  • サインアップ時にユーザーが提供したよりも多くのユーザー情報を集める

概要

リダイレクトのアクションは通常、以下のように動作します。
  1. アクションがURLへリダイレクトを送信します。
  2. そのアクションの実行が完了すると、Actionsパイプラインが中断されます。
  3. ユーザーがstateパラメーターとURLともににリダイレクトされます。
  4. 外部フローが終了すると、外部サイトがstateパラメーターとともにユーザーを/continueエンドポイントにリダイレクトします。
  5. リダイレクトを行った同じアクションからActionsパイプラインが再開します。

リダイレクトを開始する

以下のようにapi.redirect.sendUserTo()機能を呼び出します。
Actionsがこのアクションの実行を終了し、Actionsパイプラインを一時停止してユーザーをhttps://my-app.exampleco.comに送信します。つまり、このリダイレクトを行ったアクションの後にログイン後トリガーが実行される場合、そのログイン後トリガーにバインドされているアクションはすべて、認証フローが再開するまで実行されないことになります。リダイレクトのルールに慣れているのであれば、リダイレクトのアクションとリダイレクトのルールがこの点で大きく違うことに注意してください。
リダイレクトアクションは、リダイレクトルールとは異なり、リダイレクトが発行された時点でActionsパイプラインを中断します。認証フローが続行された場合は、リダイレクトを発行したアクションでパイプラインを再開します。
アクションの実行が完了すると、Auth0がユーザーをapi.redirect.sendUserTo()関数でURL指定された場所にリダイレクトします。Auth0はそのURLにstateパラメーターも渡します。例: https://my-app.exampleco.com/?state=abc123 リダイレクトURLはstateパラメーターを抽出し、それをAuth0に送り返して認証トランザクションを再開する必要があります。状態は不透明な値で、クロスサイトリクエストフォージェリ(CSRF)攻撃を防ぐために使用されます。

認証フローを再開する

リダイレクト後にユーザーを/continueエンドポイントにリダイレクトし、URLで受信したstateパラメーターを含めることで認証を再開します。元の状態を/continueエンドポイントに送り返さないと、Auth0はログイントランザクションのコンテキストを失い、invalid_requestエラーのためにユーザーがログインできなくなります。 例: https://{yourAuth0Domain}/continue?state=THE_ORIGINAL_STATE この例では、THE_ORIGINAL_STATEはAuth0が生成し、リダイレクトURLに送信した値です。たとえば、アクションがhttps://my-app.exampleco.com/にリダイレクトすると、Auth0はhttps://my-app.exampleco.com/?state=abc123と同様にリダイレクトURLを使用し、abc123THE_ORIGINAL_STATEにします。認証トランザクションを再開するには、以下にリダイレクトします。 https://{yourAuth0Domain}/continue?state=abc123 ユーザーが/continueエンドポイントにリダイレクトされると、ActionsパイプラインがonContinuePostLogin関数を呼び出して、リダイレクトの呼び出しと同じアクションで再開します。リダイレクトが正しく動作するには、リダイレクトを行った同じアクションに以下の署名を含む関数が必要です。

データを外部のサイトへ渡す

データを外部サイトに渡す場合は、そのデータを署名済みのJWTでエンコードすることをお勧めします。そうすれば、アプリケーションは送信中にデータが改ざんされていないことを確信できます。Actionsではapi.redirect.encodeTokenおよびapi.redirect.sendUserTo関数を使用してこれを実行できます。
上のコードは、リダイレクトで使用されるURLにsession_tokenクエリ文字列パラメーターを(Auth0が自動的に追加するstateパラメーターに加えて)追加します。このトークンには以下が含まれます。

トークンが改ざんされていないことを確認する

外部のシステムは、このトークンが送信中に改ざんされていないことを検証しなければなりません。これを実現するために、リモートシステムはトークンの署名が有効であることを確認し、該当する場合は、外部システム内のセッションがトークンのsubクレームで渡される同じAuth0ユーザーに属していることを確認しなければなりません。

データをAuth0へ戻す

ユーザーが外部サイトでカスタムフローを完了すると、/continueエンドポイントにリダイレクトされます。状況によっては、データをAuth0に戻して、そのユーザーの認証フローや認可フロー(たとえば、CAPTCHA認証やカスタムなど)に影響を与える必要があるかもしれません。

できるだけアプリのメタデータを使用する

可能であれば、リモートシステムはAuth0 Management APIを使用して、カスタム情報をAuth0ユーザープロファイルのアプリケーションメタデータとして保管する必要があります。Auth0アクションフローが再開されると、この情報はevent.user.app_metadataオブジェクトで利用できるようになります。この方法では、機密情報をフロントチャネルでAuth0に渡す必要がなくなります。

Auth0のユーザープロファイルにはデータを選択して保管する

Auth0のプロファイルに保管するデータは多すぎないようにします。このデータは認証および認可の目的で使用されるものです。Auth0のメタデータや検索機能は、マーケティング調査などのように、頻繁に検索や更新されることを想定して設計されたものではありません。Auth0をそのような目的で使用すると、ほぼ確実にシステムの拡張性や性能に問題が生じます。 アプリケーションにかなりの量のユーザーデータが必要な場合には、データを外部システムに保管して、Auth0に外部キー(ユーザーID)を保管すると、バックエンドシステムが必要に応じてデータを取得できるようになります。

データをフロントチャネルに送信する

情報をフロントチャネルでやり取りすると、悪意のある行為者の攻撃対象になる領域を広げることになります。情報をフロントチャネルに送信しなければならない場合には、以下のガイダンスを考慮してください。

情報をアクションへ戻す

機密情報をAuth0に送信して戻すには、必ず署名済みのセッショントークンを使用します。このトークンは、アクション内で以下のコードを使って手軽に検証することができます。
トークンは以下を確実にするために検証されます。
  • 署名が有効である
  • トークンの有効期限が切れていない
  • トークン内のstateクレームは、リダイレクトの一部として使用されるstateパラメーターと一致します。
リプレイ攻撃を回避するには、/continueエンドポイントにPOST要求を行って、トークンをAuth0に送り返す必要があります。コード内のtokenParameterNameオプションを使用すると、トークンを含むフィールドの名前を指定できます。

カスタム認証方式

ログインパイプラインでリダイレクトに成功したら、アクションはカスタム認証方法のイベントをユーザーセッションに記録することができます。event.authentication.methods配列には、ユーザーのブラウザーセッションが継続する間、カスタム認証方法のエントリが含まれます。この配列の各エントリーには、認証方法が記録された日時を示すタイムスタンプがあります。 必要なカスタム認証方法がevent.authentication.methods配列にない場合、またはエントリが古すぎる場合には、カスタムアクションによってリダイレクトがトリガーされることがあります。 api.redirect.sendUserTo()を使用して、カスタム認証方法を実装するページにユーザーを送信できます。exports.onContinuePostLoginハンドラーでapi.authentication.recordMethod()を使用して、完了した認証方法の記録をユーザーのセッションに保管できます。 event.authentication.methods配列に保管されるレコードには、api.authentication.recordMethod()で選択されたURLと一致するnameプロパティが含まれます。ここでキャプチャされたURLによって、現在のトランザクションで完了された認証方法を検索し、カスタム認証方法がすでに完了されているかを判断できます。 ワークフローで、ユーザーセッションの有効期間中にカスタム認証方法の定期的な再実行が必要になるかもしれません。たとえば、カスタムMFAの使用では、指定された時間が経過すると、ユーザーの再検証が必要になることがあります。 以下の例では、カスタム認証方法を返す契機を決めるために、既存のレコードのタイムスタンプを照合します。
api.authentication.recordMethod() APIは、exports.onContinuePostLoginハンドラーでのみ使用できます。リダイレクトの完了後にカスタム認証方法が記録されるため、ログインが悪用される可能性が軽減されます。

制約と制限

リダイレクトのアクションは以下では動作しません。

リソース所有者のエンドポイント

リソース所有者パスワードフローでAuthentication APIのトークン取得エンドポイントを呼び出す場合、リダイレクトアクションは使用できません。そもそもユーザーがリダイレクトフローにいないため、アクションでリダイレクトできるユーザーもいません。

prompt=noneのフロー

prompt=noneの目的は、ユーザーに入力を求めるシナリオを回避することであるため、リダイレクトするとerror=interaction_requiredが発生します。 アクションは認証セッションの作成後に実行されるため、特定の条件下でトークンへのアクセスをブロックしようとするリダイレクトルールがある場合(カスタムMFA、ログイン時のCAPTCHAなど)、prompt=noneは使用できません。 prompt=noneの場合、トークンアクセスをブロックしてリダイレクトアクションをバイパスするリダイレクトフローを作成することはできません。これは、アクションが最初に失敗した場合でも認証セッションが作成されているため、試行が失敗した後、ユーザーがprompt=noneで再度呼び出してトークンを取得できるためです。

リフレッシュトークン

リフレッシュトークンを使用するには、Authentication APIのトークン取得エンドポイントへのバックチャネル呼び出しが必要であるため、リダイレクトしようとするとこれも失敗します。 ログインに関するどのような制約も、適用されたかを安全に検証することは困難です。MFAチャレンジに成功したユーザーなど、セッションに関する情報を集めるのに使用可能なコンテキストでは、恒常的なセッションIDはありません。したがって、prompt=noneを使用できません。 アクションでapi.redirect.sendUserTo()が呼び出されるときに、prompt=noneが渡された場合、error=interaction_requiredで認可が失敗しますが、アクションが失敗してもユーザーのセッションが作成されるため、ユーザーがリダイレクトチャレンジに合格したことを信頼できず、トークンを取得する方法としてprompt=noneを使用することはできません。 この特有なケースには、リフレッシュトークンの排他的な使用をお勧めします。リフレッシュトークンの生成にチャレンジが必要な場合に、ユーザーがチャレンジに成功したことを確認できるからです。

もっと詳しく