Xcode
iOS
Swift
FaceID
LocalAuthentication

【iOS 11】LocalAuthenticationでFace IDとTouch IDの認証を実装する

More than 1 year has passed since last update.

はじめに

(開発者泣かせの)iPhone X が発売されましたねー
生体認証として iPhone 5s から慣れ親しんだ Touch ID による
指紋認証に加え,Face ID による 顔認証も増えました。
ただ使えるのは iPhone X だけですね。
今後他の iOS 端末や MacBook にも広がる可能性は大いにありそうです。

今回は,Face ID や Touch ID を用いた認証の実装をやってみたので書きます。
結論から言うと,今まで Touch ID による認証を用いていた場合は,
enum の追加分の条件分岐が増えるくらいであまりいらない感じです。

サンプルコード

サンプルコードを GitHub にアップしましたので,
気になる方がいらっしゃいましたらみてみてください。

GitHub

https://github.com/MilanistaDev/AuthenticationTest

開発環境

macOS Sierra 10.12.6
Xcode 9.1, 9.2 beta
Swift 4.0
Target iOS 11.0 以降

スクショ等は Xcode 9.1 で実行したものを使用しています。
もっとこう書いた方が良い,ここは間違っているなど気軽にご教示お願いいたします。

実装

1. Info.plist に NSFaceIDUsageDescription を追加

NSFaceIDUsageDescription で許可を求めるようにする。

NSFaceIDUsageDescription.png

顔認証が使える場合は認証が必要な際に
下記のいつものダイアログが表示されます。

許可.png

書かない場合の差異については下記記事が詳しいです。
https://qiita.com/Hackenbacker/items/765db49b2a6f46287713

2. LocalAuthentication Framework を import

昔やってたような Xcode の framework の追加の作業は不要でした。

ViewController.swift
import LocalAuthentication // 追加

3. 認証のコードを実装

認証だけなら最低書くコードは下記です。
Face ID と Touch ID が共存しているデバイスはないので
どちらか,あるいはどちらもできないかになりそれぞれ場合分けする感じですかね。

ViewController.swift
// viewDidLoad など適切な場所で
let context = LAContext()
var error: NSError?
let description: String = "認証"

// Touch ID・Face IDが利用できるデバイスか確認する
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
    // 利用できる場合は指紋・顔認証を要求する
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: description, reply: {success, evaluateError in
        if (success) {
            // 認証成功時の処理を書く
            print("認証成功")
        } else {
            // 認証失敗時の処理を書く
            print("認証失敗")
        }
    })
} else {
    // Touch ID・Face IDが利用できない場合の処理
    let errorDescription = error?.userInfo["NSLocalizedDescription"] ?? ""
    print(errorDescription) // Biometry is not available on this device.
}

4. Touch ID か Face ID かを判別する

iOS 11 から LocalAuthentication Framework に
LABiometryType が追加されています。
Xcode 9 以降じゃないと警告になるので注意。
下記のように enum で定義されており,nonetypeTouchIDtypeFaceID の 3 種類。

LAContext.h
// Xcode 9.1
@available(iOS 11.0, *)
public enum LABiometryType : Int {

    /// The device does not support biometry.
    case none

    /// The device supports Touch ID.
    case typeTouchID

    /// The device supports Face ID.
    case typeFaceID
}

※ Xcode 9.2 beta ではもっと Swift らしい値になっています。
個人的にはこちらの方がしっくりきます。

@available(iOS 11.0, *)
public enum LABiometryType : Int {

    /// The device does not support biometry.
    @available(iOS 11.2, *)
    case none

    /// The device does not support biometry.
    @available(iOS, introduced: 11.0, deprecated: 11.2, renamed: "LABiometryType.none")
    public static var LABiometryNone: LABiometryType { get }

    /// The device supports Touch ID.
    case touchID

    /// The device supports Face ID.
    case faceID
}

そこで,認証時に出すメッセージをそれぞれの値で出し入れできるようにしてみました。
Touch ID・Face ID が利用できるデバイスか確認した後に下記コードを実装します。

ViewController.swift
switch context.biometryType {
case .typeFaceID: // Xcode 9.2 以上は .faceID
    description = "アカウント情報を閲覧するためにFace IDを認証として用います。"
    break
case .typeTouchID: // Xcode 9.2 以上は .touchID
    description = "アカウント情報を閲覧するためにTouch IDを認証として用います。"
    break
case .none:
    description = "アカウント情報を閲覧するためにログインしてください。"
    break
}

サンプルコードでは,認証ができない場合は
ログイン認証もどきのアラートを表示するようにしています。
Face ID ではシミュレータ以外で動作確認できていませんが
ドキュメント見る限りではこの実装で良さそうです。
(不備があったら教えてください)

シミュレータによる動作確認

デフォルトでビルドした場合は,Face ID は無効になっています。
シミュレータのメニューで Hardware -> Face ID と辿り,

Hardware -> FaceID.png

Enrolled をタップするとチェックが入ります。
これで Face ID が有効になります。
その下の 2 項目はもう分かりますよね。

Enrolled.png

サンプルコードを実行して Enrolled にチェックを入れた場合,
ボタン押下で許可を求めるダイアログが出ます。

first_dialog.png

OK ボタンを押すと,実機だと多分 Finder アイコンチックな Face ID のロゴ付きの
ダイアログがおそらく表示されると思うのですが,シミュレータでは寂しいものが出てきます。

faceid_wait.png

この状態で Enrolled の下の Matching Face を選択してみると・・・

matchingface.png

当然ながら認証に成功しました。

success.png

逆に Non-matching Face を選んでみると・・・

notmatching.png

認証失敗してしまいますね。

failed.png

追記 2017.11.06

実機を手に入れたので動作確認してみました。Face ID ちゃんがやはり出るようです。

ボタンを押して 1 回で認証成功

successFirstTry.gif

ボタンを押して 1 回失敗し次で認証成功

ダイアログがでてそのダイアログ内で Face ID ちゃんがぐるぐる。緑になる。
success_at_twice.gif

失敗時

failed.gif

おわりに

今回は,LocalAuthentication での Face ID・Touch ID 認証について書きました。
iPhone X の顔認証って実際認証速度や精度ってどんな感じなんでしょうね。
enum の定義的に今後どちらの認証にも対応した端末出ないってことなのかな?
出た場合はどちらかを認証として用いるという項目作ってユーザに選んでもらうのもありかも。

私の現場ではこういう書き方してるよーとか,
実機で動作確認できていないのでここうまく動かないよ?とか
ここは間違ってるよ?とかあればご指摘いただければ嬉しいです。

ここまでご覧いただきありがとうございました。

この記事は前に書いたブログを新しい情報を加えて Qiita 用に書き換えたものです。

参考