[Auth0] MFA APIを使ったメールMFAの初回登録をLambdaで自動化できないか検証してみる

2020.01.10

こんにちは、わたしです。

以前、Auth0のメールMFAを初回から使用できないか検証するブログを書きましたが、これを自動化できるところまで持っていけないか考える機会がありましたのでやってみようと思います。

[小ネタ] Auth0で初回からメールをMFAファクターとして利用できないか検証してみる

ユースケース

自前で持っているユーザー情報をAuth0のDBに移行するケースで考えてみようと思います。 DataSpider Cloudなどの製品を使ってETL処理をする段階で実行。

このようなイメージです。

前提

  • 初期パスワード(Auth0にログインする)は付与ずみの状態でユーザーはAuth0に登録されている前提とします
  • MFAはAuth0ダッシュボードで有効になっている
  • アプリケーションは、リソース所有者パスワード付与を実行するように構成する
  • LambdaではNode.jsの12.xを使用します(Auth0のサンプルが豊富なため)

フロー

ETLの製品(DataSpider Cloudなど)でLambda Functionを実行する流れになります。

Lambda

環境変数で、以下を追加しておきます。

  • api_domain: テナントのドメイン
  • audience: リソース所有者パスワード付与(ROPG)フローで使うAPIの識別子
  • client_id: アプリケーションのID
  • client_secret: アプリケーションのSecret(暗号化します)
  • scope: リソース所有者パスワード付与(ROPG)フローで使うAPIで作成したscope

MFAトークンを取得する処理

認証APIを使用し、MFAトークンを取得します。

var request = require("request");

function mfaReq(userinfo) {
var options = { method: 'POST',
url: 'https://' + api_domain + '/oauth/token',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
form:
{ grant_type: 'password',
username: userinfo.username,
password: userinfo.password,
audience: audience,
scope: scope,
client_id: client_id,
client_secret: decrypted_client_secret }
};

return new Promise((resolve, reject) => {
request(options, function (error, response, body) {
if (error) throw new Error(error);
body = JSON.parse(body);

if (body.error == 'mfa_required') {
console.log('mfa_required');
resolve( body.mfa_token);
} else {
console.error('Something went wrong');
reject(body)
}
});
});
}

認証システムの関連付けを要求する処理

MFA APIを使い、Emailをオーセンティケーターとして関連付けるようにします。

function mfaAssociate(mfa_token, userinfo) {
var options = { method: 'POST',
url: 'https://' + api_domain + '/mfa/associate',
headers: { 'content-type': 'application/json', 'authorization': 'Bearer ' + mfa_token },
body:
{
"authenticator_types": ["oob"],
"oob_channels": ["email"],
"email": userinfo.username
},
json: true };

return new Promise((resolve, reject) => {
request(options, function (error, response, body) {
if (error) throw new Error(error);

if (body.authenticator_type === 'oob') {
if (body.binding_method === 'prompt' && body.oob_channel === 'email') {
resolve(body);
} else {
console.error('Unsupported binding_method');
reject(body);
}
} else {
console.error('Something went wrong');
reject(body);
}
});
});
}

検証したLambda関数

検証に使用したLambda関数はこちらにあります。

https://gist.github.com/y-o-u/3d61a9a5dd5730ea618efbcb746b88e6

まとめ

メールMFAを関連付けするところまでは自動化することは可能だと思います(実装方法は様々、シェルスクリプトでも可能)。 ここからは[小ネタ] Auth0で初回からメールをMFAファクターとして利用できないか検証してみるで行なったとおり、

  • 1度メールを確認し、MFAコードを取得
  • MFAコードを使って認証

といったフローが必要になってきます。

現状の仕様では、これを行わないと、初回認証時にWebUIでメールMFAを使用することができません。 現状、他のMFA要素のバックアップとしてメールMFAがあるので、他のMFA要素と共に使うのがベストだと思われます。 メールアドレスを明示的に登録するのは、Auth0に登録しているものとは別のアドレスを使いたいといったときに有効な方法ではないでしょうか。

参考