0Pricing
Swift Academy · レッスン

生体認証

Face IDとTouch IDでユーザーを認証します。

「生体認証」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

LocalAuthenticationによる生体認証

Face IDとTouch IDを使うと、ユーザーはパスワードを入力せずに本人であることを証明できます。LocalAuthenticationフレームワークは、認証ポリシーを評価し、ユーザーが認証に成功したかどうかを通知するLAContextを通じてこの機能を提供します。

import LocalAuthentication
let context = LAContext()
// One LAContext object drives a single auth attempt

最初に利用可能性を確認する

プロンプトを表示する前に、必ずcanEvaluatePolicyを呼び出してください。デバイスに生体認証ハードウェアがない場合や、ユーザーが登録していない場合、生体認証がロックアウトされている場合があります。これはBoolを返し、失敗した場合は理由を示すエラーも返します。

import LocalAuthentication
func canUseBiometrics() -> Bool {
    let context = LAContext()
    var error: NSError?
    return context.canEvaluatePolicy(
        .deviceOwnerAuthenticationWithBiometrics,
        error: &error)
}

2つのポリシー

.deviceOwnerAuthenticationWithBiometricsはFace IDまたはTouch IDを必須とし、パスコードへのフォールバックはありません。.deviceOwnerAuthenticationは生体認証を試み、失敗するとデバイスのパスコードにフォールバックします。パスコードを許容できるかどうかに基づいて選択してください。

import LocalAuthentication
// Biometrics only (no passcode fallback):
let strict = LAPolicy.deviceOwnerAuthenticationWithBiometrics
// Biometrics with passcode fallback:
let lenient = LAPolicy.deviceOwnerAuthentication
_ = (strict, lenient)

ポリシーの評価

evaluatePolicyは認証を実行し、システムの生体認証シートを表示します。localizedReason文字列で、なぜ認証を求めているのかをユーザーに説明します。非同期形式はBoolを返すか、エラーをスローします。

import LocalAuthentication
func authenticate() async -> Bool {
    let context = LAContext()
    do {
        return try await context.evaluatePolicy(
            .deviceOwnerAuthentication,
            localizedReason:
                String(localized: "Unlock your account"))
    } catch {
        return false
    }
}

生体認証の種類を判別する

canEvaluatePolicyの後にcontext.biometryTypeを確認すると、デバイスが.faceID、.touchID、.opticID、.noneのどれを使用しているかがわかります。独自のUIで適切なアイコンと文言を表示するために使用してください。

import LocalAuthentication
func biometryLabel() -> String {
    let context = LAContext()
    _ = context.canEvaluatePolicy(
        .deviceOwnerAuthenticationWithBiometrics, error: nil)
    switch context.biometryType {
    case .faceID:  return "Face ID"
    case .touchID: return "Touch ID"
    case .opticID: return "Optic ID"
    default:       return "Passcode"
    }
}

エラーへの対応

失敗はLAErrorコードとして通知されます。たとえば、.userCancel、.userFallback(パスコードを選択した場合)、失敗が多すぎる場合の.biometryLockout、.biometryNotEnrolledがあります。これらを分岐して、一般的な失敗メッセージではなく役立つ案内を表示してください。

import LocalAuthentication
func describe(_ error: Error) -> String {
    guard let la = error as? LAError else { return "failed" }
    switch la.code {
    case .userCancel:        return "cancelled"
    case .biometryLockout:   return "locked out"
    case .biometryNotEnrolled: return "not set up"
    default:                 return "failed"
    }
}

Face IDの利用目的文字列

Face IDを使用するには、理由を説明するNSFaceIDUsageDescriptionをInfo.plistに追加する必要があります。これを省略すると、Face IDポリシーを初めて評価したときにアプリがクラッシュします。Touch IDにはこのキーは必要ありません。

// Info.plist:
// NSFaceIDUsageDescription =
//   "We use Face ID to unlock your saved passwords."
let required = "NSFaceIDUsageDescription is mandatory"
_ = required

シートのカスタマイズ

プロンプトは調整できます。localizedCancelTitleでキャンセルボタンの名前を変更し、localizedFallbackTitleでフォールバック विकल्पを設定できます(空にすると非表示になります)。フォールバックのタイトルを空にすると、パスコードの選択肢が表示されなくなります。

import LocalAuthentication
func configured() -> LAContext {
    let context = LAContext()
    context.localizedCancelTitle =
        String(localized: "Not now")
    context.localizedFallbackTitle = "" // hide fallback
    return context
}

成功した認証の再利用

デフォルトでは、evaluatePolicyを呼び出すたびに再度プロンプトが表示されます。touchIDAuthenticationAllowableReuseDurationを設定すると、直近に成功したロック解除を後続のチェックで新しいプロンプトなしに利用できます。短い時間内に複数の機密操作をまとめて行う場合に便利です。

import LocalAuthentication
func reusableContext() -> LAContext {
    let context = LAContext()
    context.touchIDAuthenticationAllowableReuseDuration = 30
    return context
}

生体認証とKeychainによるアクセス制限

LAContextはユーザーを認証しますが、それ自体でデータを保護するわけではありません。真のセキュリティを実現するには、KeychainのSecAccessControlと組み合わせてください。そうすれば、単にBoolの確認結果で隠すのではなく、認証に成功するまでシークレットを暗号学的に読み取れない状態にできます。

import LocalAuthentication
// A bare evaluatePolicy == true is bypassable if your
// logic is tampered with. Prefer SecAccessControl so
// the data is encrypted until auth succeeds.
let pairing = "combine LAContext with Keychain ACL"
_ = pairing

完全なロック解除フロー

利用可能性の確認、種類に応じたメッセージ表示、評価、エラー処理を、UIから呼び出せる堅牢な1つの処理にまとめます。

import LocalAuthentication
func unlock() async -> Bool {
    let context = LAContext()
    var err: NSError?
    guard context.canEvaluatePolicy(
        .deviceOwnerAuthentication, error: &err) else {
        return false
    }
    return (try? await context.evaluatePolicy(
        .deviceOwnerAuthentication,
        localizedReason:
            String(localized: "Access your vault"))) ?? false
}

クイックチェック

2つの主要なポリシーの違いを思い出してください。

まとめ

生体認証について学びました。

  • LAContextを使用し、evaluatePolicyの前にcanEvaluatePolicyを呼び出します。
  • .deviceOwnerAuthenticationWithBiometricsは生体認証のみを使用し、.deviceOwnerAuthenticationはパスコードへのフォールバックを追加します。
  • biometryTypeを確認して適切な文言を表示し、.biometryLockoutなどのLAErrorコードに対応します。
  • NSFaceIDUsageDescriptionを追加し、実際の保護にはKeychainのSecAccessControlと組み合わせます。

よくある質問

「生体認証」レッスンは無料ですか?

はい。「生体認証」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「生体認証」で何を学びますか?

Face IDとTouch IDでユーザーを認証します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「生体認証」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Keychainへの秘密情報の保存
  2. Keychainのアクセス制御
  3. 生体認証
  4. データ保護と暗号化
← Swift Academyに戻る