Amazon SNSをAuth0のMFA SMSプロバイダーとして設定する

2020.09.03

Auth0でSMSを送信する際、3つのプロバイダータイプを選択できます。

※ SMSは、多要素認証、パスワードレス認証時に使用します

  • Auth0
    • デフォルトで、100メッセージに制限されています。評価やテストを目的とした時に使用することが多いです
  • Twilio
    • SMS用のTwilio Programmable SMS APIまたは音声用のTwilio Programmable Voice APIを使用してメッセージを送信します。本番環境ではこれを使うことが多いかと思います。Auth0と統合されている唯一のプロバイダーです。
  • Custom
    • Auth0と統合されていないプロバイダーを使用してメッセージを送信したい時に使用します。Send Phone Message Hookという機能を使います

Amazon Simple Notification Service(SNS)を使ってSMSを送信したいという要望があったため、今回のきじではCustomプロバイダータイプを選択して設定してこうと思います。

前提

  • AWSのアカウントにサインアップ済み
    • AmazonSNSFullAccessロールを持つ新しいAmazon IAMユーザーを作成しておきます

Send Phone Message Hookの作成

Hookとは、Auth0プラットフォームの選択された拡張ポイントに対して実行されたときのAuth0の動作をカスタマイズできる、安全な自己完結型の機能です。Auth0は実行時にHookを呼び出して、カスタムNode.jsコードを実行します。

Auth0ダッシュボードにログインし、左メニューのHooksをクリックします。遷移したページ下部にSend Phone Messageの項目があるので、Create New Hookをクリックします。

名前を入力し、CREATEボタンを押します。

作成が完了すると、Hookの一覧ページに戻るので、作ったHookを編集していきます。

Hook Secretを作成します。 ここには、以下のキーで対応する値を設定します。

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION

3つ追加できたことを確認しましょう。

追加した後は、SMS経由で確認コードを送信するためにAWS SNSを呼び出すコードを追加していきます。 エディタに書かれているコードを以下のものに全て置き換えます。

// Load the SDK
var AWS = require("aws-sdk");

/**
@param {string} recipient - phone number
@param {string} text - message body
@param {object} context - additional authorization context
@param {string} context.factor_type - 'first' or 'second'
@param {string} context.message_type - 'sms' or 'voice'
@param {string} context.action - 'enrollment' or 'authentication'
@param {string} context.language - language used by login flow
@param {string} context.code - one-time password
@param {string} context.ip - ip address
@param {string} context.user_agent - user agent making the authentication request
@param {string} context.client_id - to send different messages depending on the client id
@param {string} context.name - to include it in the SMS message
@param {object} context.client_metadata - metadata from client
@param {object} context.user - To customize messages for the user
@param {function} cb - function (error, response)
*/
module.exports = function(recipient, text, context, cb) {
  process.env.AWS_ACCESS_KEY_ID = context.webtask.secrets.AWS_ACCESS_KEY_ID;
  process.env.AWS_SECRET_ACCESS_KEY = context.webtask.secrets.AWS_SECRET_ACCESS_KEY;
  process.env.AWS_REGION = context.webtask.secrets.AWS_REGION;

  var params = { Message: text, PhoneNumber: recipient };

  var publishTextPromise = new AWS.SNS({ apiVersion: "2010-03-31" })
    .publish(params)
    .promise();

  publishTextPromise
    .then(function() {
      cb(null, {});
    })
    .catch(function(err) {
      cb(err);
    });
};

保存した後にエディタを確認すると、上記のようにaws-sdkのパッケージがないと警告が表示されていますので、このパッケージをフックに含める必要があります。

スパナのマークをクリックし、npm modulesをクリックしますと、モジュールを追加するエリアが表示されるので,ここから追加します(Add Module)

検索ボックスにaws-sdkと入力して追加します

実行テスト

右上のRunアイコンをクリックして、フックをテストします。パラメータを編集してSMSを受信する電話番号を指定し、Runボタンをクリックします。

recipientに受信する番号を設定

リクエストが成功すると、200OKが返ってきます。 指定した電話番号にもメッセージが届いているはずです。

実際のログインフローで試してみる

テスト実行が終わったので、実際のアプリケーションを使ってログインを行いSMSが送信されるのか確認します。

Multi-factor Authenticationの画面で、Phone Messageのトグルがオンになっていることを確認しましょう。

Phone Messageの設定では、Choose Delivery ProviderをCustomに変更します。

全て設定が終わったあと、アプリケーションからログインを実行し、SMSが機能しているか確認しましょう。

テキストメッセージが届かない場合はログを確認します。

トラブルシューティング

最後に

Amazon SNSを使ってAuth0からテキストメッセージを送ってみました。

統合されているTwilio以外を使うということになった時はPhone Message Hookを使うことで可能になるので是非試してみてください。

Auth0のドキュメントには Infobip,TeleSign, Vonage, Esendex,Mittoといったサービスをプロバイダーとする方法も記載されていますので、これらを使いたい時は参照してください。

参考