【Swift】LocalAuthenticationでTouch IDやFace IDでの認証機能を実装する方法!

この記事からわかること
- SwiftのLocalAuthenticationフレームワークとは
- iOSアプリに生体認証を実装する方法
- Touch IDやFace IDで認証する方法
- LAContextクラスの使い方
- canEvaluatePolicyやevaluatePolicyの使い方
index
[open]
\ アプリをリリースしました /
環境
- Xcode:15.0.1
- iOS:17.1
- Swift:5.9
- macOS:Sonoma 14.1
Touch IDやFace IDでの認証機能
Apple製品のデバイスに備わっているTouch IDやFace IDを使用した生体認証機能はロックを解除する際だけでなく、アプリのインストール時の認証や購入時などこれまでパスワードを入力していた場面に置き換わり使用者としても欠かせない機能の1つになっています。
iOSアプリを開発する際もアプリにロックをかける場合がある場合があり、その際にTouch IDやFace IDを使用した認証機能を導入してみたので実装方法や注意点などをまとめていきます。

Apple製品の生体認証はSecure Enclave(セキュアエンクレーブ)と呼ばれるセキュリティプロセッサによって管理されています。このSecure EnclaveはOSからもアクセスできない場所でデータを管理しているため強固なセキュリティを実現しているようです。Swiftでも実際のデータ自体にアクセスはできませんがLocalAuthentication
というフレームワークが仲介として様々な機能を提供してくれています。
LocalAuthenticationフレームワーク
公式リファレンス:LocalAuthentication Framework
SwiftでTouch IDやFace IDを使用した認証機能を実装するためにはLocalAuthentication
フレームワークを使用します。このフレームワークでは生体認証(Touch IDやFace ID)、登録済みのパスフレーズ(パスワード)で認証をできるAPIを提供しています。このフレームワークではセキュリティ面が考慮され、認証機能の基盤である指紋情報や顔情報などにはアクセスできないようになっています。
公式サイトに実装サンプルが用意されていたのでこれを元に実装していきたいと思います。
公式リファレンス:Logging a User into Your App with Face ID or Touch ID
実装方法
実装の手順
- NSFaceIDUsageDescriptionキーの追加
- 生体認証管理クラスを作成
NSFaceIDUsageDescriptionキーの追加
アプリから生体認証機能を利用するためには「info.plist」にキーを追加し使用する理由を明記する必要があります。
Key:NSFaceIDUsageDescription
Value:アプリのログイン機能に認証機能を利用するため
生体認証管理クラスを作成
アプリ内で利用しやすいように生体認証管理クラスを作成していきます。生体認証を利用するために重要になるのがLAContext
クラスです。詳細は後述しますがこのクラスから生体認証に関する処理を呼び出していきます。完成したコードは以下の通りです。
class BiometricAuthManager: ObservableObject {
@Published private(set) var isLogin = false
private var context: LAContext = LAContext()
/// 生体認証でログイン処理をリクエスト
public func requestBiometrics() {
// コンテキストは都度リセットしないと何度も認証なしでログインできてしまう
context = LAContext()
var error: NSError?
// 生体認証を利用可能かどうか識別
guard context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) else {
print(error?.localizedDescription ?? "生体認証をサポートしていないデバイスです")
return
}
// キャンセルボタンの文言を指定
context.localizedCancelTitle = "キャンセル"
Task {
do {
// ユーザーに生体認証をリクエスト
try await context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "生体認証を利用してアプリにログインできます。")
isLogin = true
} catch {
print(error.localizedDescription)
}
}
}
/// ログアウト
public func logout() {
isLogin = false
}
}
UI部分は以下のように実装できます。
struct ContentView: View {
@StateObject private var biometricAuthManager = BiometricAuthManager()
var body: some View {
VStack {
Text(biometricAuthManager.isLogin ? "ログイン中" : "ログアウト中")
Button {
if biometricAuthManager.isLogin {
biometricAuthManager.logout()
} else {
biometricAuthManager.requestBiometrics()
}
} label: {
Text(biometricAuthManager.isLogin ? "ログアウト" : "認証する")
}
}
.padding()
}
}
シミュレーターでも動作確認自体は可能ですが指紋や顔認証はできないので以下のようなパスワードを求められるだけになります。

LAContextクラス
LAContext
クラスは生体認証などSecure Enclaveへのインターフェイスとして機能するクラスで、アプリから指定した認証ポリシーを評価(アクセスや認証の可否)しています。
canEvaluatePolicyメソッド
func canEvaluatePolicy(
_ policy: LAPolicy,
error: NSErrorPointer
) -> Bool
canEvaluatePolicy
は指定した認証ポリシーが利用可能かどうかを識別するためのメソッドです。引数にはLAPolicy
型で認証ポリシーの種類を指定します。たとえばデバイスの設定でTouch IDが無効になっている場合、生体認証を必要とするポリシーは認証できません。
evaluatePolicyメソッド
func evaluatePolicy(
_ policy: LAPolicy,
localizedReason: String) async throws -> Bool
evaluatePolicy
は指定されたポリシーを非同期的に評価するためのメソッドです。2つ目の引数localizedReason
には認証ダイアログに表示するメッセージを渡します。

引数違いでcompletionHandlerから結果を取得できるメソッドも用意されています。
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "生体認証を利用してアプリにログインできます。") { [weak self] result, error in
guard let self = self else { return }
if let error = error {
print(error.localizedDescription)
return
}
self.isLogin = result
}
サポートしている生体認証を識別する
デバイスがサポートしている生体認証を識別するためにはLAContext
のbiometryType
プロパティから参照することができます。取得するためにはcanEvaluatePolicy
を実行した後のLAContext
でないとサポートしている生体認証を識別できていないので注意してください。
// canEvaluatePolicyを実行
switch context.biometryType {
case .none:
print("生体認証が使用できない")
case .faceID:
print("faceIDをサポート")
case .touchID:
print("touchIDをサポート")
case .opticID:
print("opticIDをサポート")
@unknown default:
print("不明")
}
※opticIDはApple Vision Proのロックを解除するための虹彩認証
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。