7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AutifyAdvent Calendar 2021

Day 13

Autifyで2FAが絡むテストの自動化を実現させた話

Posted at

この記事は Autify アドベントカレンダー2021 の13日目のエントリです。

こんにちは、Autifyの近澤です。最近はCEO業が忙しくコードが全く書けておらず、Ruby製のKPI集計スクリプトのメンテが、僕のエンジニアリングの最後の砦になっています。(おそらく来年の頭には僕の手から離れるでしょう:cry:

しかしAdvent Calendarに参加した手前、何か技術的なことを書かなければいけません。というわけで、ちょっと前に2FAが絡むテストをAutifyで実現できるように実装した話を書きます。Autifyでどのように実現するかは こちらのドキュメント に書いてありますのでぜひご覧ください。

本エントリではどのように実装したか書きます。

背景

とあるアメリカのお客さんから、「ユーザーログインにAuth0を使っており、Authenticator Appを使わないとログインできない設定となっているため、これを突破できないとログイン後のテストができないので辛い」という話が来ました。

当時アメリカのセールスは僕一人でやっていたので、自分でどうにかしようと思い、Authenticator Appが生成するTOTP (Time-Based One-Time Password)であれば、生成してくれるライブラリがあるんじゃないかと思い調査しました。

実装

調査したところ、totp-generatorという、まさしくなnpm を見つけました。

AutifyにはJavaScriptステップという、任意のJavaScriptコードが実行できる機能がありますが、これはブラウザ上で動くためnpmモジュールを動かすには難があります。というわけでTOTPを返してくれる簡単なREST APIを作ることにしました。

REST APIの実装

expressを使って下記のように実装します。RequestにSecret Keyを渡すとTOTPが返ってきます。

const express = require('express')
const totp = require('totp-generator')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
const port = process.env.PORT || 8080

app.use(bodyParser.urlencoded({
    extended: true
}))
app.use(bodyParser.json())
app.use(cors())

app.post('/totp', (req, res) => {
  try {
    let otp = totp(req.body.key)
    res.send(otp)
  } catch(e) {
    res.sendStatus(500).send(e)
  }
})

app.listen(port, () => {
  console.log(`Autify util api has started running`)
})

めちゃくちゃ簡単にできました。Herokuにデプロイして動作を確認します。

curl -X POST -H "Content-Type: application/json" -d '{"key":"YOUR SECRET"}' https://autify-jsstep-util-apis.herokuapp.com/totp

きちんとTOTPが返ってくることが確認できました。次にこれを呼び出すAutifyのJSステップを組みます。
上記のコードはこちらのリポジトリにありますので、是非ご活用ください。

JSステップの構築

まずユーザー登録のように、Secret Keyが固定されない場合はページから取得する必要があります。
AutifyにてSecret Keyが表示されているページにて下記のようなJSステップを実行し、Secret Keyを return します。return した値は別のステップで利用できるので、後続のAPI呼び出しを行うJSステップで利用します。

return document.querySelector(".auth0-mfa-code-otp-input").value

Screenshot for grabbing a secret key

次に return したSecret Keyを使って先ほど実装したAPIを呼び出すJSステップを作ります。

var url = "https://autify-jsstep-util-apis.herokuapp.com/totp";
var xhr = new XMLHttpRequest();
var otp = null;

xhr.onerror = function() {
  throw new Error("Network Error");
};

xhr.onload = function() {
  otp = xhr.response;
};

xhr.open("POST", url, false);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("key=" + secret);

return otp;

下記のスクリーンショットにあるように、JSステップの引数に先ほどのステップの返却値を設定します。JSステップにおける引数の使い方は、こちらの「1.4. 「引数機能」を使う」をご参考ください。

Screenshot for calling REST API

最後に

MFAをE2Eでどう突破するかは多くの人が困っている問題ですが、Authenticator Appを使ったものであれば簡単に突破できることが分かりました。Autifyではメールを用いた2段階認証も可能ですので、そのうちSMSを使ったものを突破できるようにしたいと思います。

前述の通り、徐々にCEOがコードを書いている場合ではない規模になってきてしまい悲しい限りですが、技術力の研鑽は行っていきたい所存です。

7
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?