앱의 지문, FACE ID 로그인을 위해 생체인증을 적용 했다.
react-native-touch-id로 작업을 했었지만 react-native-biometrics도 있어 2개를 같이 구현했다.
react-native-touch-id는 업데이트가 된지 오래 됐다고 하는데 별 차이 없어 보임..
● 설치 및 권한 설정
npm install
npm install --save react-native-biometrics
npm install --save react-native-touch-id
Android(AndroidManifest.xml)
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
IOS(info.plist)
<key>NSFaceIDUsageDescription</key>
<string>RoyalFund Authentication with TouchId or FaceID </string>
● react-native-biometrics
Authentication.js
import ReactNativeBiometrics, {BiometryTypes} from 'react-native-biometrics';
import * as keyStore from '/lib/secure-key-store';
const rnBiometrics = new ReactNativeBiometrics();
//생체 인식 가능 여부
export const booleanBiometricsCheck = () => {
return rnBiometrics
.isSensorAvailable()
.then(resultObject => {
const {available, biometryType, error} = resultObject;
if(!available){ // 인식실패(lock)
console.log('isSensorAvailable error', error);
}else if(available && biometryType === BiometryTypes.TouchID){
return {result: true, type: biometryType};
}else if(available && biometryType === BiometryTypes.FaceID){
return {result: true, type: biometryType};
}else if(available && biometryType === BiometryTypes.Biometrics){
return {result: true, type: biometryType};
}else{
return {result: false, type: null};
}
})
.catch(error => {
console.log('booleanBiometricsCheck error ', error);
return {result: false, type: null};
});
};
//키생성
export const createKey = () => {
return rnBiometrics
.createKeys()
.then(resultObject => {
const {publicKey} = resultObject;
return {result: true, key: publicKey};
})
.catch(error => {
console.log('createKey error ', error);
return {result: false, key: null};
});
};
//키존재여부
export const checkKey = () => {
return rnBiometrics
.biometricKeysExist()
.then(resultObject => {
const {keysExist} = resultObject;
if(keysExist){
return true;
}else{
return false;
}
})
.catch(error => {
console.log('checkKey error ', error);
return false;
});
}
export const deleteKey = () => {
return rnBiometrics
.deleteKeys()
.then(resultObject => {
const {keysDeleted} = resultObject;
if(keysDeleted){
return true;
}else{
return false;
}
})
.catch(error => {
console.log('deleteKey error ', error);
return false;
});
};
//값 확인
export const biometricsLogin = (
userID: string = '',
msg: string = '로그인',
) => {
return rnBiometrics
.createSignature({
promptMessage: msg,
payload: userID,
})
.then(resultObject => {
const { success, signature} = resultObject;
if(success){
keyStore.setItem('biometricsKey', signature);
return {result: true, key: signature};
}else{
return {result: false, key: null};
}
})
.catch(error => {
console.log('biometricsLogin error ', error);
return {result: false, key: null, msg: error};
});
};
secure-key-store.js는 아래 참고
2023.08.09 - [react-native] - [RN] react-native-keychain 구현
Home.js
import { Alert } from 'react-native';
import messaging from '@react-native-firebase/messaging';
import * as authentication from "/lib/Authentication";
function Home (props){
registerBiometrics = async() => {
const token = await messaging().getToken();
const keyCreate = await authentication.createKey();
if(keyCreate?.result){
const biometricsCheck = await authentication.booleanBiometricsCheck();
if(biometricsCheck?.result){
const bioKey = await authentication.biometricsLogin('유저아이디' + token, '등록');
//성공 로직
if(bioKey?.key){
Alert.alert('알림', '성공');
console.log('bioKey Success');
}else{
Alert.alert(
'알림',
'생체인식에 실패했습니다.'
);
}
}
}else{
Alert.alert('알림', '생체인식을 사용할 수 없습니다.');
}
};
}
참고 사이트 : http://www.dmonster.co.kr/bbs/board.php?bo_table=b0902&wr_id=11237&sst=wr_hit&sod=asc&sop=and&page=1
디몬스터,앱개발,어플제작,앱제작,어플개발,앱광고,어플광고,홈페이지제작
디몬스터,앱개발,어플제작,앱제작,어플개발,앱광고,어플광고,홈페이지제작,홈페이지제작업체,반응형홈페이지, 070-7621-0572
www.dmonster.co.kr
● react-native-touch-id
Authentication.js
import { Linking, Platform, Alert } from 'react-native';
import TouchID from 'react-native-touch-id';
import * as keyStore from '/lib/secure-key-store';
// 생체 인증 등록
export const registerBiometrics = async () => {
try {
const optionalConfigObject = {
unifiedErrors: false, // use unified error messages (default false)
passcodeFallback: false // if true is passed, itwill allow isSupported to return an error if the device is not enrolled in touch id/face id etc. Otherwise, it will just tell you what method is supported, even if the user is not enrolled. (default false)
};
const isSupported = await TouchID.isSupported(optionalConfigObject)
.then(biometryType => {
// Success code
if (biometryType === 'FaceID') {
console.log('FaceID is supported.');
} else {
console.log('TouchID is supported.');
}
const registerConfig = {
title: '생체 정보 등록',
imageColor: '#4388D6',
imageErrorColor: '#FF0000',
sensorDescription: '지문을 등록해주세요.',
sensorErrorDescription: '지문 인식에 실패하였습니다.',
cancelText: '취소',
};
const registerResult = TouchID.authenticate('생체 정보를 등록해주세요.', registerConfig)
.then(success => {
console.log('생체 정보 확인이 완료되었습니다.');
keyStore.setItem('biometricYn', 'Y');
})
.catch(error => {
if (Platform.OS === 'android') {
console.log('생체 정보 확인에 실패하였습니다.');
}else if (Platform.OS === 'ios') {
if(error.name === 'LAErrorAuthenticationFailed' || error.name === 'RCTTouchIDUnknownError'){
Alert.alert('생체인증에 실패했습니다. 잠시 후 다시 시도해주세요.');
}else{
console.log('생체 정보 확인에 실패하였습니다.');
}
}
});
})
.catch(error => {
console.log('error name ::: ' + error.name);
// Failure code
if (Platform.OS === 'android') {
if(error.code === 'NOT_ENROLLED'){
Alert.alert('생체인증이 등록되어 있지 않습니다. 설정으로 이동합니다.', '', [{text: '확인', onPress: () => openSettings() }]);
}else{
console.log('생체인증을 지원하지 않는 디바이스입니다.');
}
}else if (Platform.OS === 'ios') {
if(error.name === 'LAErrorTouchIDNotEnrolled'){
Alert.alert('생체인증이 등록되어 있지 않습니다. 설정으로 이동합니다.', '', [{text: '확인', onPress: () => openSettings() }]);
}else if(error.name === 'LAErrorAuthenticationFailed' || error.name === 'RCTTouchIDUnknownError'){
Alert.alert('생체인증에 실패했습니다. 생체인증 설정 정보를 확인해주세요.', '', [{text: '확인', onPress: () => openSettings() }]);
}else{
console.log('생체인증을 지원하지 않는 디바이스입니다.');
}
}
});
} catch (error) {
// 오류 처리
console.log('생체 정보 등록 중 오류가 발생하였습니다:', error);
}
};
// 디바이스 생체인증 등록화면 이동
const openSettings = () => {
if (Platform.OS === 'android') {
Linking.openSettings();
}else if (Platform.OS === 'ios') {
Linking.openURL('App-Prefs:root=TOUCHID_PASSCODE');
}
};
생체인증 인증 횟수 초과로 인한 lock 오류로 디바이스 설정으로 가는 기능까지 구현함.
Home.js
import * as authentication from "/lib/Authentication";
function Home (props){
registerBiometrics = (msgData)=> {
authentication.registerBiometrics();
}
}
참고 사이트 : https://www.npmjs.com/package/react-native-touch-id
react-native-touch-id
React Native authentication with the native Touch ID popup.. Latest version: 4.4.1, last published: 4 years ago. Start using react-native-touch-id in your project by running `npm i react-native-touch-id`. There are 20 other projects in the npm registry usi
www.npmjs.com
2개 모두 구현을 하고 무엇을 사용할지는 각 프로젝트의 버전, 용도에 맞춰서 고르면 될 것 같다.
내가 느낀 가장 큰 특징은 아래와 같았음.
- react-native-biometrics - 개인키를 만들어 사용자 인증을 하는데 용이함, 비교적 최근에 나와 최근까지 업데이트 되고 있음.
- react-native-touch-id - 공식 문서에 FINGERPRINT_ERROR_LOCKOUT과 같은 오류 코드들이 잘 나와있어 인증 횟수 초과로 인한 LOCK 같은 것도 쉽게 캐치할 수 있음.
'react-native' 카테고리의 다른 글
[RN] react-native-orientation 화면 고정 (0) | 2023.08.18 |
---|---|
[RN] react-native-pin-view PIN CODE 구현 (0) | 2023.08.11 |
[RN] react-native-vector-icons 사용하기 (0) | 2023.08.11 |
[RN] react-native-keychain 구현 (0) | 2023.08.09 |
[RN] react-native-qrcode-scanner 활용 및 오류 수정 (0) | 2023.08.07 |