SMSを使った二要素認証のやり方


いろいろなWebサービスで、ユーザIDとパスワードが流出し、アカウントが乗っ取られて不正に利用されるという問題が多発しています。 このような問題を防ぐ手段として、ユーザーの携帯番号を確認するのが一般的になってきました。 仮にIDとパスワードが盗まれても、それだけではアカウントは使えず、なにか追加の手段で、利用者が本当に登録した本当であるかどうか確認しようとするのが、 二要素認証の考え方です。XOXZOのテレフォニーAPIの使われ方の中で、最も多いものの一つも二要素認証です。

Webサービスで、SMSを使った二要素認証を導入するとすれば、その流れは、おおよそ次のようになるでしょう。

  1. ユーザのアカウント登録時には、あらかじめ本人の携帯番号を登録してもらう。
  2. Webサービスにユーザーがログインしようとする。
  3. Webサービス内で、4桁から6桁程度のランダムな暗証番号を生成する。
  4. ユーザーが登録している電話番号へSMSでその暗証番号を送る。
  5. Webサービスで、暗証番号を入力してもらう。

暗証番号が一致すれば、たしかにログインしようとしているユーザーは、本人の携帯電話を所持していることになりますでの、ログインを許可することになります。 逆に、正しい暗証番号が入力されなければ、そのユーザーが本人であるか怪しいので、ログインを拒否することになります。

暗証番号をSMSで送信するPython1のコード例を次に示します。

import os
import secrets
from xoxzo.cloudpy import XoxzoClient

# 2要素認証をSMSで行うためのサンプルコード

# 4桁のランダムな暗証番号を生成します
secret_key = secrets.randbelow(10000)
message = "こちらはXOXZOです。あなたの暗証番号は %04d です" % secret_key

# APIを呼び出すための秘密鍵は、環境変数に保存されているものとします
# SIDとTOKENは https://www.xoxzo.com/ からサインアップして入手してください
sid = os.getenv('XOXZO_API_SID')
auth_token = os.getenv('XOXZO_API_AUTH_TOKEN')

# SMSの送信
xc = XoxzoClient(sid=sid, auth_token=auth_token)
result = xc.send_sms(message=message, recipient="+818054695209", sender="XOXZO")

このコードを実行すると、次のようなSMSがユーザーの携帯電話に届くはずです。




SMS PIN

この後、ユーザーに暗証番号の入力を求めるフォームを表示して、それが secret_key と一致すれば認証成功です。

まとめ

以上、簡単なSMS二要素認証の紹介をしました。 この方式を導入すると、例えば一人の人間が複数のアカウントを作り、目的に応じて使い分けるといった裏アカウントを防ぐこともできます。


  1. Python3.6以降の利用を想定しています。それよりも前のPythonには標準では secrets パッケージがないので、 適当な乱数生成ライブラリを使う必要があります。 

野中 哲

エンジニア・エバンジェリスト

2016年3月に入社。NECで衛星通信の制御用ソフト開発、アップルでMacOSのローカリゼーション、AppleShareファイルサーバの開発等に従事。プライベートではRuby,Haskellなどのプログラミングとラグビー観戦を好む。最近の興味はSwiftでiOSアプリを開発すること。FAA自家用パイロットライセンス所有。