Twilio VerifyとSendGridを使ったメール認証機能の実装

SendGridサポートチームの青木です。
今回は、Twilioのブログ「Email Verification with Twilio Verify and Twilio Sendgrid with Node.js」で取り上げられた、Twilio VerifyとSendGridを使ったメール認証機能の実装方法について紹介します!
今回実装するメール認証システムについて
Twilio Verifyは、音声、SMS、メールを用いた二要素認証の仕組みをWebアプリケーションに実装することができる機能です。今回は、Twilio VerifyとSendGridを用いて、ユーザ登録フォームにメールを用いた認証機能を実装していきます!
構築する登録フォームの詳細を下の図に示します。

- ユーザ名、メールアドレス、パスワードをユーザ登録画面に入力する。
- Twilio Verifyから認証コードがメールで通知され、登録画面から検証ページに遷移する。
- ユーザが検証ページで認証コードを入力する。
- 検証ページで入力されたコードをTwilio Verifyが検証する。間違ったコードが入力された場合、認証に失敗した旨が画面上に表示される。
- 認証に成功すると、ユーザの一覧ページが表示される。
必要なもの
- Twilioアカウント
- SendGridアカウント
- SendGrid APIキー(必要な権限についてはこちらを参照)
- Git
- Node.js
- npm(Node.jsに同梱)
SendGridはFreeプランのアカウント、Twilioは無料トライアルアカウントで構いません。なお、今回の記事ではNode.js 14.16.0を使いました。対応しているバージョンはこちらからご確認ください。
手順
Step 1: メールテンプレートの作成
まずは、認証コードを送るメールをDynamic Templateで作成しましょう。
今回は以下のHTMLコードを用います。
HTMLコード内の{{twilio_code}}に、Twilio Verifyが発行した認証コードが格納されます。
<html>
<head>
<style type="text/css">
body, p, div {
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
}
a {
text-decoration: none;
}
</style>
<title></title>
</head>
<body>
<center>
<p>
The verification code is: <strong>{{twilio_code}}</strong>
</p>
<p><a href="https://sendgrid.com/blog/open-source-transactional-email-templates/">Check out more templates</a></p>
<span style="font-size: 10px;"><a href=".">Email preferences</a></span>
</center>
</body>
</html>
続いて、SendGridダッシュボードに移動し、Create a Dynamic Templateをクリックしてください。

Dynamic Templateの名前を入力したら、Createを押してください。今回は、テンプレート名を「Email-Verification」としました。

Dynamic Templates設定画面に移動したら、下の画面のAdd Versionを押します。

Your Email DesignsのBlank Templateを選択し、次に現れる画面でCode Editorを選択してください。


Dynamic Templateの編集画面が表示されたら、先ほどのHTMLコードをコードエディタに入力しましょう。メールのSubjectは、画面左側のSettingsから設定できます。今回は、Subjectを「Twilio Verify」としました。


以上の設定が完了したら、Saveを押して、画面左上の「←」からDynamic Templates設定画面に戻ってください。
下の画面に表示されている、作成したDynamic TemplateのTemplate IDをメモに控えておきましょう。このTemplate IDは次のStepで使用します。

Step 2: Twilio VerifyとSendGridの連携設定
Twilio Verify Serviceを作成し、二要素認証コードの生成と認証確認機能の設定を行います。Twilio Verifyのコンソール画面に移動し、新しいServiceを作成してください。

Serviceを新規作成すると、作成したServiceのSettings画面が表示されます。後で必要になるので、下の画面のSERVICE SIDをメモに控えておきましょう。

Twilio VerifyからSendGridを介してメール通知するための設定を行います。Email Integration設定画面に移動し、Create Email Integrationを押してください。

以下の画面がポップアップ表示されるので、作成するEmail Integrationの名前を入力し、Continueを押してください。今回は、「Daisuke’s Email Verification」としました。

作成するEmail Integrationの設定画面が表示されるので、以下の情報を入力してください。
- SENDGRID API KEY:SendGridのAPIキー
- *DEFAULT TEMPLATE ID:Step 1で作成したDynamic TemplateのTemplate ID
- *DEFAULT FROM EMAIL:検証メールのヘッダFromに表示されるメールアドレス(お好きなアドレスで構いません)
- *DEFAULT FROM NAME:メール送信元の名前

メール機能を連携させるVerify Serviceをチェックボックスで選択したら、最後は忘れずにSaveを押しましょう。
Step 3: 動作確認
認証コードの発行
ローカル環境にテスト用のフォルダを作成し、Node.jsのTwilio helper libraryをインストールしましょう。
作成したフォルダに移動し、ターミナル上で次のコマンドを実行してください。
npm init npm install twilio touch index.js
index.jsに以下のスクリプトを入力しましょう。
重要な認証情報などはスクリプト内に直接書き込まず、環境変数を用いて呼び出すようにします。環境変数の設定方法の詳細は、こちらの記事を参考にしてください。
//環境変数からTwilioのAccount SIDとAuth Tokenを取得する
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const twilioClient = require("twilio")(accountSid, authToken);
twilioClient.verify
.services("VAXXXXXXXXXXX") //Service SIDをここに入力
.verifications.create({to: "yourtestemail@example.com", channel: "email"})
.then(verification => {
console.log(verification.sid);
});
9行目のverifications.create()では、toで認証コードの通知先、channelで通知方法を指定します。toにはメールアドレスまたは電話番号が入ります。channelにはemail, sms, callが指定可能で、それぞれメール、SMS、音声通知を表します。
今回はメールで通知するため、toにメールアドレスを、channelにemailを指定してください。
ターミナルに戻ったら、次のコマンドでindex.jsを実行してください。
node index
上手く実行できれば、今回用いたTwilio Verifyのリソースを識別するverification SIDがターミナル上に表示され、メールボックスに以下のようなメールが届くはずです。

認証コードの確認
先ほどのスクリプトを実行することで、認証コードが発行されました。続いて認証コードを検証する機能を試してみましょう。実行したスクリプトから、認証コードを生成する9~12行目をコメントアウトし、以下のスクリプトをindex.jsに追加してください。
twilioClient.verify
.services("VAXXXXXXXXXXX") //Service SIDをここに入力
.verificationChecks.create({ to: "yourtestemail@example.com", code: "123456" })
.then(verification_check => console.log(verification_check.status));
verificationChecks.create()は、認証コードを検証するためのメソッドです。
toとcodeに入力されたメールアドレスと認証コードの組み合わせが、verifications.create()で生成した認証コードに一致するかどうかをTwilio Verifyが確認します。
試しに、3行目のcodeに間違った認証コードを入力してindex.jsを実行してみましょう。そうすると、ターミナル上にpendingの文字が表示されるはずです。正しい認証コードが入力されるまでは、ステータスとしてpendingが返ります。
次に、メールで受け取った正しい認証コードを試してみてください。
今度は、ターミナル上にapprovedのステータスが表示されるはずです。
以上でTwilio Verifyの動作確認は終了です!
次のステップでは、実際のアプリケーションの実装に移ります。
Step 4: アプリケーションの実装
Twilio Verifyの機能をユーザ登録画面に組み込んでみましょう。今回は、GitHubにあるサンプルアプリケーションを用いて実装していきます。
ターミナル上で以下のコマンドを実行して、サンプルアプリケーションのインストールおよび依存関係の解決を行ってください。
git clone https://github.com/nokenwa/verify-Starter.git cd verify-Starter npm install
次のコマンドで.envファイルを作成し、Twilio Account SIDとAuth Token、Twilio Verify SIDを作成した.envファイルに記入しましょう。
cp .env.sample .env
以下のコマンドを実行すると、Webサーバが立ち上がります。
npm start
ブラウザ上でlocalhost:3000にアクセスすると、下のようなユーザ登録ページが表示されるはずです。

このユーザ登録ページは、スクリプトで実装した簡易的なデータベースを用いて構築しています。
index.jsの中でユーザ情報を取得してデータベースに格納し、検証メールを送信する部分を下に抜粋します。
検証メールを送信したら/verify(検証ページ)にリダイレクトして、検証コードの入力を求めます。このとき、ユーザのメールアドレスをURLのクエリパラメータとして渡します。これはセッション変数を用いた方法で書いても構いません。
//New User Created
app.post("/", (req, res) => {
const email = req.body.email;
database.addUser({
username: req.body.username,
email: email,
password: req.body.password,
verified: "Not Verified"
});
//CREATE A NEW VERIFICATION HERE
twilioClient.verify
.services(verificationSID)
.verifications.create({ to: email, channel: "email" })
.then(verification => {
console.log("Verification email sent");
res.redirect(`/verify?email=${email}`);
})
.catch(error => {
console.log(error);
});
// res.redirect("/users");
});
以上で、新しいユーザが追加されるたびに、検証メールの送信および/verifyへのリダイレクトが行われるようになりました!
続いて、検証情報を/verifyにPOSTする部分を見てみましょう。
この部分では、ユーザのメールアドレスとコードの組み合わせを確認しています。approvedが検証結果として返った場合は、コードが承認されたことを表示し、ユーザの一覧ページにリダイレクトします。approvedが返らなかった場合は、検証が失敗したことを示すメッセージを表示します。
//Verification Code submission
app.post("/verify", (req, res) => {
const userCode = req.body.code;
const email = req.body.email;
console.log(`Code: ${userCode}`);
console.log(`Email: ${email}`);
//CHECK YOUR VERIFICATION CODE HERE
twilioClient.verify
.services("VAXXXXXXXXXX")
.verificationChecks.create({ to: email, code: userCode })
.then(verification_check => {
if (verification_check.status === "approved") {
database.verifyUser(email);
res.redirect("users");
} else {
res.render("verify", {
email: email,
message: "Verification Failed. Please enter the code from your email"
});
}
})
.catch(error => {
console.log(error);
res.render("verify", {
email: email,
message: "Verification Failed. Please enter the code from your email"
});
});
});
結果
それではブラウザに戻って、実際にユーザ登録を進めてみましょう。
ユーザ名とメールアドレス、パスワードを入力してSign Upを押すと、認証コードがメールで送られました。


ブラウザ上では検証ページが表示されるので、メールで受け取ったコードを入力してVerifyを押します。

認証に成功し、今回検証したユーザ情報がユーザリストに追加されていることを確認しました!

まとめ
今回は、Twilio VerifyとSendGridを使ったメール認証システムの構築について紹介しました。
ユーザ登録時のメール認証や二要素認証の一連の手続きは、認証コードの生成、通知、検証など多くの手順を含んでおり大変複雑です。しかし、Twilio Verifyを用いることでこれらの手順を簡単に済ませることができます。二要素認証の重要性が増している昨今では、重宝される機能なのではないかと思います。ぜひ皆さんも、この機会にTwilio Verifyに触れてみてはいかがでしょうか。


