September 10, 2021

OTP as a Service

前回の投稿「One-Time Password(OTP)にまつわる仕様] でOTPの仕様を取り上げました。今回はOTPの中でもTOTPを使ったサービスを提供する際に必要なことをを紹介したいと思います。

バリデーターの設計

以下のような項目を設計する必要があります。

  • Issuer: 発行元の組織の名前
  • Account Name: メールアドレスなど同時に紐づくジェネレーターごとの名前 (例: email addressなど)
  • Period: OTPの生成間隔
  • Secret Size: シークレットのビット長
  • Digits: OTPの桁数

これらはジェネレーターにも渡す情報で、非常に重要です。サービスの簡単な実装について見ていきましょう。

1. 端末(ユーザー)の登録

まずOTPの規定の通り、共通鍵を生成する必要があります。この生成鍵は端末ごとに異なるべきなのでマッピングは必要となります。

Markdown TableでERDを模倣してみます。

Field 備考
Public ID PK
Secret Base32でエンコードされた共通鍵

主キーにはPublic IDを端末のIDとして指定しました。これはYubico社の実装を参考にしています。

もしWeb APIを提供するなら以下のようなAPIで登録できるようにします。

$ curl -X POST https://<API_ENDPOINT>/users -d '{"email":"xxx@hoge.com"}'

レスポンスにはOTPのURLがなにかした返ってくるはずです。

1.1 Secretの精製方法

Secretの生成方法はRFCでは規定されていないのですがいくつかのOTPに関するパッケージを見ると、ランダムな数字で作成されていることが多いようです。

1.2 共通鍵の渡し方

Google Authenticatorを仕様に則ると、otpauth://TYPE/LABEL?PARAMETERSで渡してあげるほうが良さそうです。 今回の場合だと以下のようになります。

otpauth://totp/email%20address?secret=XXXXXX&issuer=Keke

多くの場合は、QRコードによってジェネレータ側に渡されています。

2. ジェネレータの設定

生成されたURLをもととにジェネレータを設定します。重要なのは以下の項目です。

  • バリデーターと同じアルゴリズムを使用すること
  • 共通鍵を受けておること

3. OTPを作成しバリデータに渡します

2.で設定した情報をもとにOTPを作成します。そしてOTPをバリデータに送って、次のステップで検証をします。

4. バリデータで検証をする

クライアントから取得したOTPとPublic IDをもとに検証をします。

参考文献

© KeisukeYamashita 2021