アプリ部の中澤です。
iOSの生体認証の仕様について、iOS 11.2現在のAppleの公式ドキュメントに一部誤りがある事を知ったので、その詳細を共有します。
あるiOS端末が何の生体認証に対応しているかを知る為には、LAContextクラスのbiometryTypeというプロパティを見ます。このプロパティにはiOS 11.2現在、none, touchID, faceIDのいずれかが入ります。
OS 11.2現在の公式ドキュメントによると、このbiometryTypeは以下のように説明されています。
This property is only set when canEvaluatePolicy(_:error:) succeeds for a biometric policy
つまり、生体認証が使える場合に限り正しい値がセットされるということです。
しかしそうなると、以下の場合も取得出来ず、困ってしまいます。
- 生体認証に対応しているが指紋や顔が未登録である場合
- 複数回の認証失敗により生体認証の使用自体がOSによりロックされている場合
例えば生体認証の使用がOSによってロックされてる時、
「Touch IDでの認証がロックされています。設定アプリにある「Touch ID とパスコード」 を確認してください。」
などというメッセージをユーザーに出したい場合があるとします。この時、「Touch ID」で良いのか「Face ID」と表示すべきなのか分からないという状況が起こります。
この挙動についてAppleに問い合わせたところ、前述のドキュメントの記述は実は間違っているという回答をもらいました。
つまり、ロックされていようが指紋が未登録であろうが関係なく、canEvaluatePolicy(_:error:)を実行すれば常にbiometryTypeがセットされるのが仕様上正しいという事です。
実際ほぼ全てのiOS 11端末でそのような挙動となることを確認できました。
このドキュメントの間違いは、iOS 11.3時点で訂正される予定とのことです。
ただし一部端末ではそうならない
残念ながら、iOS 11.0.xが載った一部端末では、そうなってくれないバグがあります。
例えばiOS 11.0.3が載ったiPhone 8やiPhone 8 Plusでそのバグを確認できました。他にもあるかもしれません。
Appleによると、このバグはiOS 11.1時点で既に修正済みとのことです。
また、iOS 11.0でbiometryTypeを呼び出すとクラッシュする場合があるとのことです。
ここまでの詳しい経緯は以下に載せてあります。
https://openradar.appspot.com/radar?id=5061720007507968
回避策
前述の2件のバグを回避する為には、既にそれぞれ修正されているiOS 11.1以上をDeployment Targetにするのが理想的です。
ただ、事情あってそれが出来ない場合もあると思います。その場合は、canEvaluatePolicy(_:error:) のエラー内容とiPhone Xかどうかを材料に、正しいbiometryTypeの値を導出するという手があるかと思います。今回それを以下としてライブラリ化してみました。参考になれば幸いです。
https://github.com/mshibanami/BiometryTypeBugWorkaround