FaceID/TouchIDでの認証を実装した際に,ちょこちょこつまづいた点があったので記録.
基本
生体認証の利用可否をチェック
func checkIfBiometricAuthenticationAvailable() -> Bool {
let context = LAContext()
var error: NSError?
// 生体認証の利用可否チェック
let isAvailable = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
// MEMO: iOS11以降は認証方式を判別可
let type: BiometricAuthenticationType
if #available(iOS 11.0, *) {
switch context.biometryType {
case .faceID:
print("FaceID")
case .touchID:
print("TouchID")
case .none:
break
}
if let e = error else {
// Error handling…
print(e)
}
return isAvailable
}
生体認証の実行
func authenticate() {
let context = LAContext()
let reason = "TouchID でロックを解除"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { (success, error) in
guard error == nil else {
// Error handling…
return
}
if success {
// 認証成功
} else {
// 認証失敗
}
}
}
つまづいた点
LABiometryType
の取得
取得できるのはLAContext.canEvaluatePolicy()
実行後のみ.
仕様なので仕方はないが,生体認証方式を知るにも多少手数がかかるのでなんとも言えない気持ちになる.
生体認証方式の判定
標準で用意されている LABiometryType
もあるが,多少冗長でも独自のEnumを使った方が良さげ.
理由
- 利用可能なOSバージョン
-
LABiometryType
はiOS11.0 ~ のため,それ以前のOSをサポートしている場合,ラップしておいた方が楽
-
- FaceIDのアクセス不許可時もまとめてハンドリングできる
- FaceID対応端末の場合,生体認証のアクセス許可を変更できる.そのため,FaceID対応端末については許可状態もまとめて管理できるようにすると,より細やかな出し分けができる
- e.g. 設定画面においてFaceID/TouchIDでラベル・アイコンの出し分けを行い,かつFaceIDのアクセスが許可されていない場合にメッセージを表示する場合
- FaceID対応端末の場合,生体認証のアクセス許可を変更できる.そのため,FaceID対応端末については許可状態もまとめて管理できるようにすると,より細やかな出し分けができる
実装例
enum BiometricAuthenticationType {
case faceID(permitted: Bool) // FaceID端末は設定アプリ上でアクセスを不許可にできるので許可状態も把握できるようにしておく
case touchID // TouchID端末はアクセス許可を変更できないので種別のみ判定できればOK
case none
}
認証に使用するLAContext
一度認証に成功すると evaluatePolicy
の結果は常にtrueを返すので都度生成する必要がある.
LAContext.canEvaluatePolicy
のエラーコード
iOS11 とそれ以前とで違うので, iOS10以前もサポートしている場合に 生体認証の利用が許可されていない
ケースをハンドリングする場合は以下のようにする必要がある.
var error: NSError?
let isAvailable = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
// 生体認証の利用が許可されていない場合に返ってくるエラーコード
let biometricAuthenticationNotAvailableErrorCode: Int
if #available(iOS 11.0, *) {
biometricAuthenticationNotAvailableErrorCode = LAError.biometryNotAvailable.rawValue
} else {
biometricAuthenticationNotAvailableErrorCode = LAError.touchIDNotAvailable.rawValue
}
if error?.code == biometricAuthenticationNotAvailableErrorCode {
// 生体認証の利用が許可されていない場合の処理
}
…
LAContext.evaluatePolicy()
の localizedReason
空文字を指定するとクラッシュする.
- 空文字にしなければいいだけだが,ローカライズのキーだけ設定して英語の.stringsファイルは暫定的に空文字にしていたらクラッシュしてハマった.
雑感
iOS10以前をサポートしなければ,ここで書いたことの半分くらいは気にしなくても済むので,早くサポートを切りたい.
おまけ
Gistにまとめました.