ReactNative+Expo LocalAuthenticationで指紋認証を試してみた


検証環境

バージョン
React 16.11.0
ReactNative 0.62.2
Expo 3.24.0
Android Pie

指紋認証・顔認証について

Android

BiometricPrompt APIを使用する。
生体認証システム
生体認証ダイアログを表示する-Androidデベロッパードキュメント
Android10~顔認証をサポートしている。
指紋認証はAndroid6.0~。

Android 10
デベロッパーが生体認証の利用可否をクエリできる BiometricManager クラスを導入しています。
BiometricPrompt 向けに指紋認証と顔認証を統合しています。
Android 9
BiometricPrompt 向けにのみ指紋認証を統合しています。

参考:【Android】BiometricPromptと指紋認証機能の実装方法について

iOS

TouchIDとFaceIDを使用する。
FaceID対応はiPhone X以上。
Face ID に対応している iPhone と iPad のモデル
Local Authentication-Apple Developer Documentation
Logging a User into Your App with Face ID or Touch ID

Expoで使用する

Expoドキュメント

GitHub

Expo Snackサンプル

インストール

 expo init
 expo install expo-local-authentication
 expo start

サンプルコード

 import React from "react";
 import { StyleSheet, Text, View, Button } from "react-native";
 import * as LocalAuthentication from "expo-local-authentication";

 export default class App extends React.Component {
   supportAuthentication = async () => {
     const result = await LocalAuthentication.supportedAuthenticationTypesAsync();
     alert(result);
   };

   checkDeviceForHardware = async () => {
     const compatible = await LocalAuthentication.hasHardwareAsync();
     if (compatible) {
       alert("有効なデバイスです");
     } else {
       alert("無効なデバイスです");
     }
   };

   checkForBiometrics = async () => {
     const biometricRecords = await LocalAuthentication.isEnrolledAsync();
     if (biometricRecords) {
       alert("生体認証有効");
     } else {
       alert("生体認証無効");
     }
   };

   handleAuthentication = async () => {
     const result = await LocalAuthentication.authenticateAsync({
       promptMessage: "認証を促すメッセージ",
       cancelLabel: "キャンセルラベル",
       fallbackLabel: "認証失敗時のメッセージ",
       disableDeviceFallback: false,
     });
     if (result.success) {
       alert("認証成功");
     } else {
       LocalAuthentication.cancelAuthenticate();
       alert("認証失敗");
     }
   };

   render() {
     return (
       <View style={styles.container}>
         <Text>Local authentication</Text>
         <Button
           title="デバイスチェック"
           onPress={this.checkDeviceForHardware}
         />
         <Button title="生体認証チェック" onPress={this.checkForBiometrics} />
         <Button
           title="認証サポートチェック"
           onPress={this.supportAuthentication}
         />
         <Button title="認証チェック" onPress={this.handleAuthentication} />
       </View>
     );
   }
 }

 const styles = StyleSheet.create({
   container: {
     flex: 1,
     backgroundColor: "#fff",
     alignItems: "center",
     justifyContent: "center",
   },
 });

LocalAuthentication API

LocalAuthentication.hasHardwareAsync()

デバイスで顔認証もしくは指紋認証が使用できるかどうか。

LocalAuthentication.supportedAuthenticationTypesAsync()

デバイスがサポートしている認証タイプを取得する。

 export declare enum AuthenticationType {
     FINGERPRINT = 1,
     FACIAL_RECOGNITION = 2,
     IRIS = 3
 }

返り値が1は指紋認証、2は顔認証を意味する。
デバイスがどちらの認証方法にも対応している場合、配列に両方含まれた[1,2]
どちらにも対応していない場合空配列が返る。

LocalAuthentication.isEnrolledAsync()

認証に使用する顔データもしくは指紋データが保存されているか。

LocalAuthentication.authenticateAsync(options)

指紋認証・顔認証を実行する。

指紋認証・顔認証データが存在しない場合falseになります。

{
   "error": "not_enrolled",
   "message": "KeyguardManager#isDeviceSecure() returned false",
   "success": false,
 }

認証がキャンセルされた場合。

{
   "error": "user_cancel",
   "message": "指紋の操作がユーザーによりキャンセルされました。",
   "success": false,
 }

認証に成功した場合successが返ります。

{
   "success": true,
 }

optionについて

{
  promptMessage: "認証を促すメッセージ",
  cancelLabel: "キャンセルラベル",
  fallbackLabel: "認証失敗時のメッセージ",
  disableDeviceFallback: false,
}
promptMessage (string)


上記画像の"Authenticate"のテキストを変更する。

cancelLabel (string)


disableDeviceFallbackオプションがtrueのときキャンセルボタンのテキストを変更する。

fallbackLabel (string)

認証に何度か失敗した後に表示される既定の Use Passcode ラベルをカスタマイズする(iOSのみ)。

disableDeviceFallback (boolean)

デフォルト(false)の場合、認証に複数回失敗したとき既定の方法(PINコード・パターンなど)で代替の認証を表示する。

trueに設定した場合、認証に複数回失敗しても別の認証方法を表示しない。

LocalAuthentication.cancelAuthenticate()

認証をキャンセルする(androidのみ)。