以前、MSアカウントとAzureを使ったログインについて書きましたが、今回は Authenticatorの対応プラグインを作ったよ!というお話。
使ったのはNode.jsのライブラリでございます。ありがとう。末尾に載せます。
概要
プラグインは3つのアクションを設定しています。
secretKey
ユーザーアカウント(Email)、サービス名、暗号化用パスワードを引数で渡すと、シークレットを発行し、暗号化したものをレスポンスで返します。
otpauth_url
secretKeyで作成したシークレット(暗号化済み)、暗号化用パスワード、ユーザーアカウント(Email)、サービス名を引数で渡すと、QRコードに設定するtotp用のURLをレスポンスで返します。
generateCode
secretKeyで作成したシークレット(暗号化済み)、暗号化用パスワードを渡すと、現在時刻から計算した6桁のコードを返します。
この値がAuthenticatorで生成される値と同じになるはずですので、ワークフローでユーザーの入力値と比較して、同じであればログインを許可するようにします。
使い方
使い方がちょっと面倒です。全部Server Scriptで書いたので。。
サインアップ・ログインページ
まずサインアップ・ログインページを作ります。

サインアップのワークフローは、以下の流れです。
1. サインアップを実行し、サインアップ時に secretKey で利用するパスワードをrandom stringで作成し、ユーザーカラムに保存
2. プラグインの secretKey を利用し、シークレットを生成
3. シークレットをSlug等に保存
4. 6桁コードを入力するページに遷移


1. サインアップと暗号化用パスワードの生成
サインアップ時に、その後のsecretKeyで利用する暗号化用のパスワードを生成します。

2. プラグインの secretKey を利用し、シークレットを生成
email : ユーザーのEmail
servicename : サイト名など ※
cryptopass : サインアップ時に作成した暗号化用パスワード
※ 日本語は確認していないので、アルファベットでお願いします。

3. Slugに生成したシークレットを保存
ユーザーごとに異なる値を保存するため、Slugに保存しました。

4. 6桁コードを入力するページに遷移
コードのチェックを行うので、ログインをした時も同様に6桁コードを入力するページに遷移するワークフローを作ります。
コードの入力ページ
コードの入力ページを作ります。画面はレスポンシブエンジンを使っています。
上部のQRコードはプラグインを利用させていただきました。
流れとして、Userテーブルに「auth」というカラム(yes/no)を作り、デフォルトは no にしておき、初回6桁コードの認証後は yes にして、no のときはQRコードを表示する、 yes のときは 6桁の入力欄を表示しています。


Group FirstAuth には QRコードとボタンを配置しています。

Group FirstAuth は Userテーブルのauth = no のとき表示させています。

QRコードはこちらのプラグインを利用しています。
urlには、Custom Stateを作り、それを表示するように設定しました。

ボタンを配置します。
このボタンをクリックするとGroup FirstAuthを非表示にし、6桁の入力欄(Group CodeAuth)を表示します。

6桁の入力欄(input)と認証ボタンを設定します。

Group CodeAuthは、Userテーブルのauth = yes のとき表示させます。
QRコード読み込みをして、アプリにアカウントを登録し、一度でもコード認証を行ったあとはQRコードを表示させないようにしています。

コード入力欄は、先頭0がありえるのでTextで。文字数は6桁にします。

認証用のボタンを設置します。
コード入力ページのワークフローは以下の流れです。
1. ページロード時
1-1. otpauth_url を実行し、QRコードの内容のURLを生成
1-2. QRコードプラグインのurlに渡すCustom Stateに URL をセット
2. QRコード下のコード認証ボタンのクリック時
2-1. QRコードを含むグループ Group FirstAuth を非表示
2-2. 入力欄を含むグループ Group CodeAuth を表示
3. コード入力欄下の認証ボタンクリック時
3-1. generateCode で6桁コードを生成
3-2. 入力されたコード = 3-1.のコードの時、Userテーブルの auth = yes にする
3-3. 入力されたコード = 3-1.のコードの時、ログイン後のページに遷移


1-1. プラグインのotpauth_urlを実行
secret : User’s Slug = シークレット
cryptopass : 暗号化用のパスワード
account : ユーザーアカウント(Email)
servicename : サービス名、サイト名など(英語で!)
レスポンスで、QRコードに埋め込むURLを生成します。

1-2. QRコードプラグインのurlに渡すCustom Stateにセット
ここでは Body グループに Custom State を作り、設定しています。
QRコードプラグインでは、urlをBody’s urlに設定していました。


2-1. QRコードを含むグループを非表示

2-2. 認証コード入力欄を含むグループを表示


3-1. プラグインのgenerateCodeを実行
secret : User’s Slug = シークレット
cryptopass : 暗号化用のパスワード
レスポンスで、6桁の認証コードを生成します。
この値がユーザーの入力値と同じかどうかをチェックします。

3-2. コードが一致した場合、Userテーブルの auth = yes にする
Only When に 3-1.のレスポンス code = ユーザーの入力値 と入力します。
入力値とプラグインで生成した6桁の数字が同じになった場合=認証成功時、これ以降QRコードを表示しないようにしています。

3-3. コードが一致した場合、ログイン後のページに遷移
ここではとりあえず success ページに遷移させています。
出来上がり
では、これで実行してみましょう!

若干QRコードが表示されるのがおそいですが・・・。
QRコードをMicrosoft Authenticatorで読み込み、表示された6桁の数字を入力しています。
参考 Thanks a lot!!
QRコードを表示してくれるエレメント系のプラグイン
bubble.io plugin
speakeasy npm
node.jsの2段階認証のシークレットやURL、コード生成、コードのチェックをしてくれるライブラリ
npm
node.jsの暗号化標準ライブラリ
Node.js