LocalAuthentication iOSで生体認証(Face ID, Touch ID)のまとめ

はじめに

KeyHolderにFace IDやTouch ID等の、生体認証を導入したので、その際の備忘録を纏めます。

実装方法

info.plist修正 NSFaceIDUsageDescriptionを追加

info.plistにNSFaceIDUsageDescriptionを追加します。
これは、FaceIDの利用をユーザに許諾してもらうために追記します。
KeyHolderでは以下の様に記載しています。

f:id:project-unknown:20180104043302p:plain

LocalAuthenticationをimport

LocalAuthenticationをimportします。

import LocalAuthentication

認証用コードの実装

以下のコードの様に記載することで、Face IDもしくはTouch IDが使える端末且つ、利用を許可されている場合は、認証を行うことが出来ます。
また、認証が通った場合は、それがFace IDなのか、Touch IDはcontextの中身を見れば取れる様になっています。

    let context = LAContext()
    var error: NSError?
    let description: String = "認証します"
    // Face ID, Touch IDが利用できるデバイスか確認する
    if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
        // Face ID, Touch IDが利用できる場合は認証用ダイアログを表示
        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: description, reply: {success, evaluateError in
            if (success) {
                // 認証成功
                switch context.biometryType {
                case .faceID:
                    // Face IDが利用出来る
                    break
                case .touchID:
                    // Touch IDが利用できる
                    break
                case .none:
                    // Face ID, Touch IDの利用が出来ない (この場合、この条件には入ってこないはず)
            } else {
                // 認証失敗
            }
        })
    } else {
        // Face ID, Touch IDが利用出来ない
    }

簡単な例ですが、どの認証が扱えるのかのクラスメソッドを用意しました。
それぞれFaceID、Touch IDが利用出来るかをチェックする為のメソッドです。
また、引数に、NSErrorを渡す事で、利用できない場合のエラー内容が返却されます。
エラー内容については、後述で記載しています。

    /**
     Face IDが利用出来るかチェックします
     
     - returns Bool: true 利用可能 / false 利用不可
     */
    class func canUseFaceID(error: inout NSError?) -> Bool {
        if #available(iOS 11.0, *) {
            let context = LAContext()
            if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
                if context.biometryType == .faceID {
                    return true
                }
            }
        }
        
        return false
    }
    
    /**
     Touch IDが利用できるかチェックします
     
     - returns Bool: true 利用可能 / false 利用不可
     */
    class func canUseTouchID(error: inout NSError?) -> Bool {
        let context = LAContext()
        
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            if #available(iOS 11.0, *) {
                if context.biometryType == .touchID {
                    return true
                }
            } else if #available(iOS 8.0, *) {
                return true
            }
        }
        
        return false
    }

使い方は以下のような感じで

var error: NSError?
if クラス名.canUseFaceID(error: &error) == false && クラス名.canUseTouchID(error: &error) == false {
    print ("生体認証が利用できません!!!")
}

エラーコード (LAError.Code)

LocalAuthenticationのエラーは、LAErrorで定義されています。

エラーのドメインは以下の通りです。

com.apple.LocalAuthentication 

以下はエラーコードごとの種別です。
Appleのドキュメントでは、TouchIDが主に言及されていますが、Face IDの場合はTouch IDをFace IDに置き換えて読んで問題なさそうです。
(例えば、Face IDを許可していなかったら-6が返ってくる為) (翻訳はGoogle翻訳を、そのまま使っている所もあります)

LAError.Code種別 エラーコード 説明
authenticationFailed -1 ユーザーが生体認証を利用するにあたり必要な情報を獲得できなかった為、認証に失敗
appCancel -9 アプリ側でキャンセルが掛かった
invalidContext -10 何かしらのエラー
notInteractive -1004 インタラクティブではない?
passcodeNotSet -5 端末にパスコードがセットされていない
systemCancel -4 システムで認証がキャンセルされた
touchIDLockout -8 Face ID/Touch IDがロックアウトされた
touchIDNotAvailable -6 端末でFace ID/Touch IDを使用できない為、認証できなかった
touchIDNotEnrolled -7 指紋認証に失敗
userCancel -2 認証ダイアログでユーザがキャンセルボタンを押した
userFallback -3 ユーザが認証ダイアログでFallbackしたが、認証ポリシーにFallbackが使用できなかった。

最後に

iPhone Xが出て、Face IDが登場してから認証周りのユーザ利便性が非常に上がってきましたね。
何だかんだでずっと対応していなかったKeyHolderでも、やっと対応し、近日中にリリース予定ですので、是非この機会にお試しください!