TouchID と FaceID についておさらいしよう!!(AppleWatch認証はまだないけど)
パスコード認証、touchID認証、faceID認証…
そして、第四の認証となった AppleWatch認証。
iOS 14.5 では、まだアプリ側では使えません。
とはいえ、ここらで認証についておさらいしておくのもいいかと思います。
Mac だと前から使えたよね。
info.plist に追加
最初に追加しておきましょう。
NSFaceIDUsageDescription
keyを追加するだけ。
Xcode上では、「Privacy - Face ID Usage Description」と表示されています。
InfoPlist.strings によるローカライズもお忘れずに。
info.plist に追加しなくても、FaceIDの許可は聞かれます。
ただ、代わりに「Face IDには対応してしない可能性があります」等のメッセージが表示されます。注意ですね。
実際に書いていく🖋
import LocalAuthentication
LocalAuthentication
をインポートしておく必要があります。
どの生体認証が使えるのかチェック
iPhoneX(10)以降の端末には、TouchIDではなくFaceIDが搭載されています。
biometryType
は、そのデバイスが所有する生体認証を表示します。
case .touchID
touchID が使用可能。case .faceID
faceID が使用可能。case .none
使用できる生体認証が存在しない。
初期値は .none であり、一度 LAContext の処理に通さないと、初期値のままです。
そのため、canEvaluatePolicy
を使用する必要があります。
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
switch context.biometryType {
case .touchID:
// touchID が使える場合
case .faceID:
// faceID が使える場合
default:
// 新たな生体認証が増えた場合、呼ばれる可能性あり
break
}
} else {
// 生体認証が使えない場合(faceID を許可していない場合)
print("BiometryType Error: " + (error?.localizedDescription ?? "Unknown Error"))
}
生体認証を許可していない場合は、
User has denied the use of biometry for this app.
というコードが確認できます。
なお、biometryType
は iOS 11 以降追加されました。(それ以前は touchID のみなので)
iOS 10 以前をサポートしている場合は、以下のような処理も必要ですね。
・・・
if #available(iOS 11.0, *) {
switch context.biometryType {
case .touchID:
// touchID が使える場合
case .faceID:
// faceID が使える場合
default:
// 新たな生体認証が増えた場合、呼ばれる可能性あり
break
}
} else {
// touchID のみ
}
・・・
認証を実行
let context = LAContext()
let localizedReason = "ロックの解除に、認証を使用します。"
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: localizedReason, reply: {success, error in
if success {
// 認証成功時の処理
} else {
// キャンセルされた場合
print("Authenticate Cancel: " + (error?.localizedDescription ?? "Unknown Error"))
}
})
ちなみに、ユーザーがキャンセルボタンを押した場合は、
Canceled by user.
という error
が返されます。
policy
認証に使用する方法。
詳しくは下記にて。localizedReason
認証画面で表示される、認証を要求する理由(テキスト)。
詳しくは下記にて。reply
認証が終了した時点で呼び出されるブロック。 success
認証成功時はtrue
、
失敗時、またはキャンセルした場合はfalse
。 error
認証成功時はnil
。
失敗時やキャンセル時にのみ返される。
1.認証方法
LAPolicy
を指定して、認証の方法を指定できます。(ゆーて、iOSだと2種類だけだけど。)
Case | rawValue | iOS | |
---|---|---|---|
deviceOwnerAuthenticationWithBiometrics |
生体認証(TouchID または FaceID) | 1 | iOS 8~ |
deviceOwnerAuthenticationWithWatch |
AppleWatch による認証 | 3 | 非対応 |
deviceOwnerAuthenticationWithBiometricsOrWatch |
生体認証 または AppleWatch | 4 | 非対応 |
deviceOwnerAuthentication |
Apple Watch (iOSは不可)、生物測定、パスコード のいずれか | 2 | iOS 9~ |
AppleWatch認証は、macOS 限定みたいですね。
'deviceOwnerAuthenticationWithWatch' is unavailable in iOS
\1. 'deviceOwnerAuthenticationWithWatch' has been explicitly marked unavailable here (LocalAuthentication.LAPolicy)
iPhoneも iOS14.5から新実装(ロック解除に)されたので、そのうちにアプリでも使用可能になる…?
(…のか??)
deviceOwnerAuthentication
の場合
生体認証を行った後、失敗した場合は パスコード 認証を選択できます。
FaceID を 無効にしている場合、 パスコード 認証にスキップされます。
deviceOwnerAuthenticationWithBiometrics
の場合
生体認証(TouchID または FaceID)のみを行います。
もっと正確にいうと、パスコード入力を許可しない設定 です。
そのため、注意点が2つ。
- 「パスコードを入力」を非表示にすること。
認証失敗後、パスコード入力ができる項目が表示されますが…
Fallback authentication mechanism selected.
押しても特に何も表示されません。
iOS9からの仕様みたいですね。
let context = LAContext()
context.localizedFallbackTitle = ""
localizedFallbackTitle
を空にしておくと、表示されなくなります。
こちらが無難ですね。
- FaceID を 無効にしている場合、即時キャンセルされる。
User has denied the use of biometry for this app.
生体認証が使えない場合は、そもそもこの処理を行わないようにした方が無難です。
または、エラー内容によって処理を分ける…など。
2.認証の使用目的
認証を行う際、その理由を表示します。
FaceIDを使用する際は確認できませんが、TouchID や パスコード入力時 に表示されます。
let context = LAContext()
let localizedReason = "ロックの解除に、認証を使用します。"
※ 画像は、一部ローカライズしてます。
+α
ここまでの内容だけで、処理は実装完了です。
細かい内容について気づいた点を、以下にまとめておきます。
キャンセルされた理由に応じて処理を分ける
let context = LAContext()
let localizedReason = "ロックの解除に、認証を使用します。"
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: localizedReason, reply: {success, error in
if let error = error {
switch LAError(_nsError: error as NSError).code {
case .appCancel:
// システムによるキャンセル① アプリのコード
case .systemCancel:
// システムによるキャンセル② システム
case .userCancel:
// ユーザーによってキャンセルされた場合
case .biometryLockout:
// 生体認証エラー① 失敗制限に達した際のロック
case .biometryNotAvailable:
// 生体認証エラー② 許可していない
case .biometryNotEnrolled:
// 生体認証エラー③ 生体認証IDが1つもない
case .authenticationFailed:
// 認証に失敗してエラー
case .invalidContext:
// システムによるエラー① すでに無効化済み
case .notInteractive:
// システムによるエラー② 非表示になっている
case .passcodeNotSet:
// パスコード認証エラー① パスコードを設定していない
case .userFallback:
// パスコード認証エラー② LAPolicyによって無効化
default:
// そのほかの未対応エラー
}
} else if success {
// 認証成功時の処理
} else {
// 予期せぬエラーの場合
}
if !success {
print("Authenticate Cancel: " + (error?.localizedDescription ?? "Unknown Error"))
}
})
LAError.code | 理由 | 説明 |
---|---|---|
.appCancel |
システムによるキャンセル |
invalidate() で明示的に無効化した場合 |
.systemCancel |
システムによるキャンセル | アプリを閉じるなどをした場合 |
.userCancel |
ユーザーによってキャンセルされた場合 | ユーザーがキャンセルをタップした場合(他の理由があっても、キャンセルボタンを押した場合はこちらになります) |
.biometryLockout |
生体認証エラー | 認証の失敗回数が一定回数に達し、生体認証がロックされている状態 |
.biometryNotAvailable |
生体認証エラー | 生体認証(FaceID)の許可が、拒否されている場合 |
.biometryNotEnrolled |
生体認証エラー | 生体認証ID(FaceIDまたはTouchID)が1つもない場合 |
.authenticationFailed |
認証に失敗してエラー | 認証に失敗した場合?(キャンセルを押すと.userCancel になるので未確認) |
.invalidContext |
システムによるエラー |
invalidate() で無効化済みの Context を使っている場合 |
.notInteractive |
システムによるエラー |
interactionNotAllowed が true になっていて、認証UIの表示ができない場合 |
.passcodeNotSet |
パスコード認証エラー | パスコードが設定されていない場合 |
.userFallback |
パスコード認証エラー | LAPolicy がパスコード認証を使わないタイプの場合、「パスコードを入力」を押しても認証画面は表示されない。 |
デバイス内の事情によるエラー、コード等によるシステム的なエラーの半々といったところでしょうか。
実際に使いそうなのは上半分ですね。
なお、.biometryLockout
などの 生体認証に関するエラー は、iOS11 で旧項目から置き換わったものです。
iOS10 以前は、touchIDしかありませんでしたからね。
以下の旧項目は、現在非推奨となっています。
case .touchIDNotAvailable:
// touchID認証エラー① 失敗制限に達した際のロック
case .touchIDNotEnrolled:
// touchID認証エラー② 許可していない
case .touchIDLockout:
// touchID認証エラー③ touchIDが1つもない
シミュレーターで行う方法
[ Features ] → [ Face ID ] → [ Enrolled ] で認証可能になります。
[ Matching Face ] で認証成功アクション。
[ Non-matching Face ] で認証失敗アクション。
TouchID端末では、 FaceIDではなくTouchIDになります。
やり方はほぼ同じです。
参考
-
LAContext //Apple Developer
詳しいことは、全部ここに載ってます。 - アプリ内での Touch ID を利用したユーザ認証 //qiita
- Face IDとTouch IDの対応は意外と簡単! //qiita
-
iOS10から必要になったユーザデータにアクセスする為に表示する文言をローカライズする //qiita
InfoPlist.strings(Info.plistのローカライズ) に関する記事。
え…?本編と関係ない…??
ということでね
端末内で完結している認証なので、実装自体はカンタンです。
殴り書きなので、至らぬ点がありましたらぜひぜひ。
まだ AppleWatch認証 は、アプリ側では使えませんね。(今後使えるようになるかは不明)
とはいえ、追加される可能性があるなら、この辺は覗いておいた方がいいですね。
外ではマスク必須の今では、FaceIDはあまり役に立ちません。
そこで大きく役に立ち始めた AppleWatch認証…
とても便利です。ええ。
とはいえ、ロック解除以外(アプリ以外も含めて)には使えないけど。
ところで、 touchID 復活はまだでしょうか🤔
Discussion