Auth0のActionsを使って一部のユーザー向けにMFAをカスタマイズ

2021.08.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Auth0では、MFAをカスタマイズして、テナント内の特定のアプリケーションに対して認証を行っているユーザーに対してのみ実行する、 MFAを使用するようにマークされているユーザーに対してのみ実行する、 特定のメールアドレスやリクエスト元のIPアドレスに対しては実行しない などの処理を行えます。

本記事では、 Actions を使ってカスタマイズを行ってみようと思います。

MFAをカスタマイズするActions作成

アクションを作成する を参考にし、アクションを作ります。

今回はログインフローにアクションを追加するので、フロー選択の画面ではLoginを選択します。 MFAは、ログイン完了後に動くためです。

作成が終わると、以下のようなエディタの画面が表示されます。

一部のユーザー向けにカスタマイズ

ログイン後のフローに呼び出される処理をカスタムするので、onExecutePostLogin ハンドラーに処理を追加します。

特定のメールアドレスの場合はMFAを実行しない

exports.onExecutePostLogin = async (event, api) => {
  // 特定のメールアドレスはMFAをスキップする
  if(event.user.email === "xxxxxxxxxx@classmethod.jp") {
    console.log(event.user.email);
    return;
  }
  
  ~~~~~~~~ 以降の処理 ~~~~~~~~
};

特定のIPアドレスの場合はMFAを実行しない

exports.onExecutePostLogin = async (event, api) => {
  if(event.request.ip === "xxx.xxx.xxx.xx") {
    console.log(event.request.ip);
    return;
  }
  
  ~~~~~~~~ 以降の処理 ~~~~~~~~
};

event.request.ipは、IPv4、IPv6両方OKです。

特定のネットワークのアクセスはMFAを実行しない

exports.onExecutePostLogin = async (event, api) => {
  // 特定のネットワークのアクセスはMFAをスキップする
  const ipaddr = require('ipaddr.js');
  const corp_network = "xxx.xxx.xxx.xx/xx";
  const current_ip = ipaddr.parse(event.request.ip);
  if (current_ip.match(ipaddr.parseCIDR(corp_network))) {
    console.log(current_ip);
    return;
  }
  
  ~~~~~~~~ 以降の処理 ~~~~~~~~
};

ipaddr.jsというモジュールを追加しています。

ActionsではNPM上のNode.jsモジュールを追加できます。

依存関係の追加について

MFAを実行する

exports.onExecutePostLogin = async (event, api) => {
  // provider
  //   any: Use any of the configured challenges.
  //   duo: Use the Duo mutlifactor provider.
  //   google-authenticator: Use the Google Authenticator provider.
  //   guardian: Use the Guardian provider.
  api.multifactor.enable("any", {"allowRememberBrowser": false});
};

API Objectのmultifactorを使うことでMFAを実行できます。

使用したコード一式

Actionsに使ったコードです。

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  // 特定のメールアドレスはMFAをスキップする
  if(event.user.email === "<<メールアドレス>>") {
    console.log(event.user.email);
    return;
  }

  // 特定のIPアドレスはMFAをスキップする
  if(event.request.ip === "<<IPアドレス>>") {
    console.log(event.request.ip);
    return;
  }

  // 特定のネットワークのアクセスはMFAをスキップする
  const ipaddr = require('ipaddr.js');
  const corp_network = "<<CIDR>>";
  const current_ip = ipaddr.parse(event.request.ip);
  if (current_ip.match(ipaddr.parseCIDR(corp_network))) {
    console.log(current_ip);
    return;
  }

  // provider
  //   any: Use any of the configured challenges.
  //   duo: Use the Duo mutlifactor provider.
  //   google-authenticator: Use the Google Authenticator provider.
  //   guardian: Use the Guardian provider.
  api.multifactor.enable("any", {"allowRememberBrowser": false});
};


/**
* Handler that will be invoked when this action is resuming after an external redirect. If your
* onExecutePostLogin function does not perform a redirect, this function can be safely ignored.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
// exports.onContinuePostLogin = async (event, api) => {
// };

MFAを一部のユーザー向けにカスタマイズするときの注意点

今回のように一部のユーザーはMFAをスキップする、そのほかは実行する といったカスタムをする場合は、

MFAの設定画面にあるDefine policies -> Require Multi-factor Auth の設定値を Never にしておきましょう。

Flowに組み込む

アクションを作成したら、それをログインフローに組み込みます。

ダッシュボードのLoginフローのページで、作ったアクションを選択してドロップします。

※ 作成したアクションは、既存の拡張機能であるRulesの後に動きます

ログインフローを試す

アクションを組み込んだ後、実際にログインして試してみましょう。

指定したメアドやIPからのアクセスではMFAは実行されないはずです。

Loginフローに組み込んだアクションが実行されると、Auth0のログから内容を確認できます。

ログイン成功したときのログ

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

今回はメールアドレスとIPアドレスで判断してMFAを実行しないようにしてみましたが、 user metadataにMFAを実行するかしないかの情報を入れておいて判定するといったこともActionsでは可能です。

Eventオブジェクトにユーザーに関するコンテキスト情報が入っていますので、色々と試していこうかと思います。