TOTP 認証を提供する際に考慮すべき otpauth URI のフォーマット

uzuki2段階認証アプリ,otpauth,TOTP

開発グループの卯月です。

最近(といっても半年程前ですが)、私が担当しているプロダクトに TOTP (RFC 6238) で2要素認証を導入しました。
TOTP を扱うライブラリや技術的な資料は複数存在しますが、TOTP に対応した2段階認証アプリの仕様にあわせた otpauth URI 生成方法について、イメージが掴みやすい HowTo 記事が無かったので、その辺りを書いていきたいと思います。

なお、TOTP 認証の実装方法や技術的な解説は本記事では紹介しませんのでご了承ください。

※本記事は2017年6月8日時点での情報を元に作成しています。

どの2段階認証アプリをサポートするか

利用者は基本的にスマホの2段階認証アプリを利用するかと思います。
2段階認証アプリは無料アプリとして無数に存在しているので、内製するよりかは既存アプリを利用した方が良いです。

本記事では、下記2つのアプリで利用可能な otpauth URI のフォーマットについて紹介します。

そもそも otpauth URI って何?

TOTP の設定を2段階認証アプリ側に読み込ませるための URI です。
サーバ側で otpauth URI を生成し、QR コードで表示→スマホで読み込ませ2段階認証アプリに保存する流れになるかと思います。
なお、この otpauth URI には秘密鍵が含まれますので、傍受の危険性のある経路での送信や不必要に保存させることはやめましょう。(例:非暗号化経路でのメール送信等)
QRコードで読み込ませる場合であれば比較的傍受され難いですし、キャッシュは除き2段階認証アプリ以外には保存されないのでお勧めです。

詳しい仕様は下記をご覧ください。

otpauth URI はどう生成すれば良いの?

結論から言うと下記フォーマットに準拠していれば、Google Authenticator / IIJ SmartKey をサポートできます。
otpauth://totp/[issuer]:[accountname]?secret=[secret]&issuer=[issuer]&algorithm=SHA1&digits=6&period=30

では何故このフォーマットで Google Authenticator / IIJ SmartKey がサポートできるのかを説明します。

ベースとなる URI は Google Authenticator / IIJ SmartKey 共通です。
otpauth://[TYPE]/[LABEL]?[PARAMETERS]

TYPE

Google Authenticator では hotp / totp どちらとも対応しています。
IIJ SmartKey では totp のみ対応しています。

今回は TOTP 認証を行いたいので、[TYPE] には「totp」を指定します。

LABEL

Google Authenticator では、accountname のみ または issuer と accountname をコロン(:)で連結したものが利用できます。
IIJ SmartKey では、issuer と accountname をコロン(:)で連結したものが利用できます。

IIJ SmartKey の方が制限きついので、[LABEL] には「[issuer]:[accountname]」を指定します。

issuer(発行者)
Google Authenticator / IIJ SmartKey 共に、値は URL エンコード (ABNF) する必要があります。
基本的にはサービス名にすると良いでしょう。

accountname(アカウント名)
Google Authenticator / IIJ SmartKey 共に、値は URL エンコード (ABNF) する必要があります。
基本的には利用者のアカウント名やログイン ID にすると良いでしょう。

PARAMETERS

secret(秘密鍵)
Google Authenticator / IIJ SmartKey 共に指定必須であり、値は秘密鍵を Base32 エンコードした文字列で指定する必要があります。

これは共通仕様なので、そのまま指定します。

issuer(発行者)
Google Authenticator / IIJ SmartKey 共に、値は LABEL で指定した issuer を指定する必要があります。
Google Authenticator では強く推奨しているだけですが、IIJ SmartKey では指定必須です。

IIJ SmartKey で指定必須なので、必ず指定するようにします。
なお、[LABEL] 内の issuer と同じ値を指定するよう気を付けましょう。

algorithm(ハッシュアルゴリズム)
Google Authenticator / IIJ SmartKey 共に指定は任意(デフォルト値は SHA1)です。
Google Authenticator では、値に SHA1 / SHA256 / SHA512 が指定できますが無視されます。
IIJ SmartKey では、値に SHA1 / SHA256 / SHA512 / MD5 が指定できます。

Google Authenticator では指定しても無視されデフォルト値である「SHA1」が利用されます。
今後デフォルト値が変更となる可能性もなくはないので、念のため「SHA1」を指定しておきましょう。

digits(表示されるトークンの表示桁数)
Google Authenticator / IIJ SmartKey 共に指定は任意(デフォルト値は 6)です。
Google Authenticator では、値に 6 / 8 が指定できますが無視されます。
IIJ SmartKey では、値に 6 / 8 が指定できます。

Google Authenticator では指定しても無視されデフォルト値である「6」が利用されます。
今後デフォルト値が変更となる可能性もなくはないので、念のため「6」を指定しておきましょう。

period(更新間隔(秒))
Google Authenticator / IIJ SmartKey 共に指定は任意(デフォルト値は 30)です。
Google Authenticator では、値に数値が指定できますが無視されます。
IIJ SmartKey では、値に数値が指定できます。

Google Authenticator では指定しても無視されデフォルト値である「30」が利用されます。
今後デフォルト値が変更となる可能性もなくはないので、念のため「30」を指定しておきましょう。

counter
Google Authenticator の TYPE が hotp の時に指定するパラメータなので今回は指定しません。

icon
IIJ SmartKey のオプションパラメータなので今回は指定しません。

まとめ

どのアプリも otpauth URI の仕様は大枠では共通ですが、細かい箇所が結構異なっていますので、サポートしたいアプリの仕様はちゃんと確認することをお勧めします。

再掲しますが、Google Authenticator / IIJ SmartKey は下記フォーマットでサポートできます!
otpauth://totp/[issuer]:[accountname]?secret=[secret]&issuer=[issuer]&algorithm=SHA1&digits=6&period=30

uzuki2段階認証アプリ,otpauth,TOTP

Posted by uzuki