l08084のブログ

技術記事の執筆は、祈りに近い

iOSのFace ID, Touch IDを使用したログイン機能を設計する

業務でFace ID, Touch IDを使ったログイン機能を実装することになったので色々と調べた。

作成予定のシステム

  • Ionic(JavaScript, Angular)で作成されたハイブリットモバイルアプリケーション
  • サーバーサイドはJava(Spring)
  • 通常のログインには、メールアドレスとパスワードを使用
  • Face ID, Touch IDによる認証が成功した時には、メールアドレス/パスワード の入力をスキップした状態でログインできる

Face ID, Touch IDに対する誤解について

Face ID, Touch IDによる認証が成功すると、認証した人を特定できるユニークなIDを発行してくれるイメージを勝手に持っていたが、そんな機能はなかった。Face ID, Touch ID のAPIが提供する情報は、あくまで認証が「成功したかどうか」のみでIDを発行したりはしない。

処理詳細

過去に類似の実装経験がある人に話を聞いた結果、下記のイメージで実装する予定。

初回ログイン

  1. UDIDを発行して、iOSデバイスのキーチェーンに格納
  2. ユーザーがログイン画面にメールアドレスとパスワードを入力してログイン
  3. この時、発行したUDIDもサーバーに送る
  4. 「UDID」と「メールアドレス・パスワード」を関連付けてDBに保存
  5. これで次回以降は、Face ID, Touch IDによる認証が有効になる

Face ID, Touch IDによるログイン

  1. Face ID or Touch IDを実行して成功する
  2. iOSデバイスのキーチェーンからUDIDを取り出す
  3. UDID+固定文字列をHMAC-SHA256形式でハッシュ化
  4. ハッシュと現在時刻を連結させたものを、AES256で暗号化、暗号化した結果をBASE64Encodeするこれをシグネチャとする
  5. シグネチャをサーバーに送る
  6. サーバー側でBASE64Decode、AES復号化、送られてきた現在時刻から10分以上経過していないことを確認する
  7. ハッシュが一致することを確認する
  8. UDIDが正しく登録されているか確認する
  9. 認証処置完了、認証トークンを発行する

Appleのレビューガイドライン

Appleのレビューガイドラインで、Face IDについての記載があったので転載する。

https://developer.apple.com/jp/app-store/review/guidelines/

2.5.13 顔認証でアカウントを認証するアプリケーションには、ARKitやその他の顔認証テクノロジーではなく、必ずLocalAuthenticationを使用する必要があります。また、13歳未満のユーザーに対しては、必ず代替の認証方法を用意する必要があります。

考えた点・補足

  • 端末のKeychainに直接メールアドレスとパスワードを保管するのは避けた
  • シグネチャは、改ざん防止ではなく、認証のために利用している
  • 顔・指紋認証に3回失敗すると、通常ログインに切り替える〜みたいな処理は、API(ライブラリ)側で勝手にやってくれる

結局違う設計にしました。この記事参照