1import * as LocalAuthentication from 'expo-local-authentication'; 2import React from 'react'; 3import { Text, View } from 'react-native'; 4 5import Button from '../components/Button'; 6import MonoText from '../components/MonoText'; 7 8interface State { 9 waiting: boolean; 10 supportedAuthenticationTypes?: string[]; 11 hasHardware?: boolean; 12 isEnrolled?: boolean; 13} 14 15// See: https://github.com/expo/expo/pull/10229#discussion_r490961694 16// eslint-disable-next-line @typescript-eslint/ban-types 17export default class LocalAuthenticationScreen extends React.Component<{}, State> { 18 static navigationOptions = { 19 title: 'LocalAuthentication', 20 }; 21 22 readonly state: State = { 23 waiting: false, 24 }; 25 26 componentDidMount() { 27 this.checkDevicePossibilities(); 28 } 29 30 async checkDevicePossibilities() { 31 const [hasHardware, isEnrolled, supportedAuthenticationTypes] = await Promise.all([ 32 LocalAuthentication.hasHardwareAsync(), 33 LocalAuthentication.isEnrolledAsync(), 34 this.getAuthenticationTypes(), 35 ]); 36 this.setState({ hasHardware, isEnrolled, supportedAuthenticationTypes }); 37 } 38 39 async getAuthenticationTypes() { 40 return (await LocalAuthentication.supportedAuthenticationTypesAsync()).map( 41 (type) => LocalAuthentication.AuthenticationType[type] 42 ); 43 } 44 45 authenticateWithFallback = () => { 46 this.authenticate(true); 47 }; 48 49 authenticateWithoutFallback = () => { 50 this.authenticate(false); 51 }; 52 53 async authenticate(withFallback: boolean = true) { 54 this.setState({ waiting: true }); 55 try { 56 const result = await LocalAuthentication.authenticateAsync({ 57 promptMessage: 'Authenticate', 58 cancelLabel: 'Cancel label', 59 disableDeviceFallback: !withFallback, 60 }); 61 if (result.success) { 62 alert('Authenticated!'); 63 } else { 64 alert('Failed to authenticate, reason: ' + result.error); 65 } 66 } finally { 67 this.setState({ waiting: false }); 68 } 69 } 70 71 render() { 72 const { waiting, ...capabilities } = this.state; 73 74 return ( 75 <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> 76 <View style={{ paddingBottom: 30 }}> 77 <Text>Device capabilities:</Text> 78 <MonoText textStyle={{ fontSize: 14 }}>{JSON.stringify(capabilities, null, 2)}</MonoText> 79 </View> 80 <View style={{ height: 200 }}> 81 {waiting ? ( 82 <Text>Waiting for authentication...</Text> 83 ) : ( 84 <View> 85 <Button 86 style={{ margin: 5 }} 87 onPress={this.authenticateWithFallback} 88 title="Authenticate with device fallback" 89 /> 90 <Button 91 style={{ margin: 5 }} 92 onPress={this.authenticateWithoutFallback} 93 title="Authenticate without device fallback" 94 /> 95 </View> 96 )} 97 </View> 98 </View> 99 ); 100 } 101} 102