LoginSignup
10

More than 1 year has passed since last update.

【SwiftUI】iOSの生体認証について

Posted at

はじめに

こちらの記事ではiOSにおける生体認証についてをまとめてみました。
動作確認ができている環境は以下の通りです。(2021/12時点)
- Xcode : 13.1
- Swift : 5.5.1

生体認証について

iPhone5s以降から指紋認証を始めとした生体認証を利用することができます。
今回はiOSの生体認証の実装方法についてをまとめてみました。

使用するライブラリ

LocalAuthenticationというライブラリを利用しなければ始まりません。
使用するクラスの先頭に必ずインポート文を書きましょう。

import LocalAuthentication

FaceID

最新機種であれば搭載されている顔認証(FaceID)を利用する方法です。

ContentView.swift
import SwiftUI

struct ContentView: View {
    // 結果メッセージ
    @State var message = "Hello, world!"

    // 認証クラスを生成
    let face:FaceAuth = FaceAuth()

    var body: some View {
        Text("\(message)")
            .onAppear {
                // 実行
                exec()
            }
    }

    // 認証処理
    func exec() {
        // クロージャで非同期実行
        face.auth { result in
            // 結果をメッセージに格納
            message = result
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

FaceAuth.swift
import Foundation
import LocalAuthentication

class FaceAuth {

    // 生体認証を管理クラスを生成
    var context: LAContext = LAContext()
    // 認証ポップアップに表示するメッセージ
    let reason = "パスワードを入力してください"

    // 顔認証処理
    func auth(complation:@escaping(String) -> Void) {
        // 顔認証が利用できるかチェック
        if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) {
            // 認証処理の実行
            context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
                if success {
                    DispatchQueue.main.async {
                        complation("認証が成功しました")
                    }
                } else if let laError = error as? LAError {
                    switch laError.code {
                    case .authenticationFailed:
                        complation("認証に失敗しました")
                        break
                    case .userCancel:
                        complation("認証がキャンセルされました")
                        break
                    case .userFallback:
                        complation("認証に失敗しました")
                        break
                    case .systemCancel:
                        complation("認証が自動キャンセルされました")
                        break
                    case .passcodeNotSet:
                        complation("パスコードが入力されませんでした")
                        break
                    case .touchIDNotAvailable:
                        complation("指紋認証の失敗上限に達しました")
                        break
                    case .touchIDNotEnrolled:
                        complation("指紋認証が許可されていません")
                        break
                    case .touchIDLockout:
                        complation("指紋が登録されていません")
                        break
                    case .appCancel:
                        complation("アプリ側でキャンセルされました")
                        break
                    case .invalidContext:
                        complation("不明なエラー")
                        break
                    case .notInteractive:
                        complation("システムエラーが発生しました")
                        break
                    @unknown default:
                        // 何もしない
                        break
                    }
                }
            }
        } else {
            // 生体認証ができない場合の認証画面表示など
        }
    }
}

info.plistの編集

StoryBoardので作成する場合は、info.plistが作成されるのですが、SwiftUIの場合はそのようなファイルが見当たりません。
以下の画像を参考に設定項目を表示してみましょう。
スクリーンショット 2021-12-08 23.51.00.png

+ボタンから項目を作成して、Privacy - Face ID Usage Descriptionを選択してください。
ezgif-7-a6a65b2bced6.gif

ValueはFaceID許可画面に表示されるメッセージになります。
上から2つ目のように設定してみてください。
スクリーンショット 2021-12-09 0.04.47.png

実行イメージ
ezgif-7-1e7108734476.gif

ポイント

LAContextについて

アプリと生体認証を管理している Secure Enclave(セキュリティプロセッサー)との仲介役のことらしいです。
canEvaluatePolicyメソッドで利用可能かチェックしており、evaluatePolicyで認証を実行しています。

canEvaluatePolicyメソッドについて

context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) {

第一引数ですが2種類指定可能です。
.deviceOwnerAuthenticationは、パスコード入力に戻ることを許す
deviceOwnerAuthenticationWithBiometricsは、パスコード入力に戻ることを許さない
アプリの特性を考えて実装してみましょう。

クロージャについて

認証とは直接関係ない話ですが。。。
モバイルアプリでは常に画面描画とロジック処理を一つのスレッドで実行できません。
例)APIアクセス時画面はぐるぐるが表示されつつ、裏ではレスポンスを待機しているなど

上記の場合には、メソッドの定義方法に工夫が必要になります。

呼び出し先
func auth(クロージャ名:@escaping(戻り値) -> Void) {
   // 非同期処理

   クロージャ名(戻り値)
}
呼び出し元
クラス名.auth { result in  // resultに戻り値が返ってくる
    // 何かの処理
}

まとめ

今回はSwiftUIでFaceIDの実行方法についてまとめてみました。
次はTouchIDの方法でも書きます。。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
10