9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FlutterでGoogle Authenticatorを自作した👨‍💻

Last updated at Posted at 2022-01-05

サマリ 📖

年末年始にまとまった時間が取れたのでFlutterの勉強を兼ねて自作ワンタイムパスワードアプリ1(Google Authenticatorもどき)を作りました。
下記GIFのように、2段階認証用のQRコードを読み取って、ワンタイムパスワードを取得することができます。
現状Googleにしか対応していませんが、QRコードを読み取り正しいワンタイムパスワードを発行し、Googleログイン時の2段階認証を通過できます。

output.gif
(GIF中で使っているQRコードはダミーです。qrencodeで適当に作りました)

概要編 👨‍🏫

ワンタイムパスワードの仕組み

基本的にGoogle Authenticator等のワンタイムパスワードを発行するサービスは、TOTP(Time-based One-time Password)アルゴリズムに従っています。

TOTPアルゴリズムはRFC6238で定義されたアルゴリズムで、サーバとクライアントが共有する秘密鍵および現在時刻から確認用のコードを生成するものです。

TOTPを実装する

仕組みは非常にシンプルで分かりやすいです。

- QRコードには秘密鍵が含まれている
- クライアントはQRコードを読み取り秘密鍵を入手
- 秘密鍵 + 現在時刻をもとにパスコードを算出。サーバに送信
- サーバも同様の秘密鍵を持っているのでパスコードを算出し一致を確認する

つまり、TOTPはざっくり言うと現在時刻(unix時間)と秘密鍵で決まる関数2です。
そのため、秘密鍵(と各種設定値)さえサーバとクライアントで共有できれば全く同じコードを生成できます。
下記の図が非常に分かりやすかったです。

image.png

AWSのMFAの仕組みを実装して読み解いてみた

例えばGoogleサービスの場合だとQRコードを読み取ると下記のような文字列が取得できます3

otpauth://totp/Google:{user_name}@{service_name}?secret={secret_base32}&issuer=Google

secret部分がbase32でエンコードされた秘密鍵を表しています。
こちらと現在時刻を組み合わせてパスコードを算出します。

正確なアルゴリズムの内容については前述のリンク先等が詳しいです。

実装編 👨‍💻

TOTPアルゴリズム

自身で実装しても良かったのですが、便利なパッケージ(dart-otp)があったので利用しました。
興味ある方は自前実装するのもアリだと思います。ロジック自体はDartコードで100-200行くらいで実装できます。

QRコード読み取り

下記を参考に実装しました。

QRコード関連パッケージにはbarcode_scanqr_code_scanner等があります。
前者は開発が止まっているようですが、monoさんがbarcode_scan2として復活させている模様。
今回は実装した後にbarcode_scan2の存在を知ったためqr_code_scannerを使っています。

実装する上で特に手詰まりはありませんでしたが、強いて言うなら、QRコードが表示されている間、無限に読み取りのコールバックが呼ばれる問題がありました。
公式のIssueの通り、一度読み取った時点でfirstDetectionフラグを立て、後続のコールバックを止めるようにしました。

アニメーション

アニメーションはトップ画面のカウントダウンタイマー的な部分で使っています。
当初Flutterアニメーションの理解が非常に弱かったのですが、itomeさんの記事を読んでかなり理解が深まりました。
メチャクチャ分かりやすかったです。

また、Flutterを書き進めるとなるべくStatefulWidgetを廃したい力学が働いてきます(?)が、アニメーションについては素直にStatefulWidgetで実装しても良い気がしました(今回もStatefulWigetで実装しています)。

サークルの描画自体の実装はこちらを参考にしました。

余談:Flutterのキャッチアップ方法

完全にFlutter初見だったので、まずは下記、社の先輩が書いた記事を参考にさせていただき、ざっくりとFlutterの全体感を掴みました。

contextやWidgetツリー等の各種ツリー、Riverpodの裏側の理解はこちらの記事(有料ですが)が非常に分かりやすかったです。

その他参考

GIFを作るのに参考にさせていただきました。

  1. Googleのワンタイムパスワードが発行できることは確認していますが、飽くまで勉強を兼ねて作ったオモチャプロダクトです。実用には不向きです

  2. 他にも必要な定数はありますが

  3. どのアプリもotpauth URIの仕様は大枠では共通ですが、細かい箇所が異なっています

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?