├── assets ├── 1.png ├── icon.png ├── splash.png ├── favicon.png └── adaptive-icon.png ├── babel.config.js ├── .expo-shared └── assets.json ├── .gitignore ├── README.md ├── package.json ├── app.json ├── App.js └── src ├── screens ├── AuthScreen.js └── PaymentScreen.js └── components └── CardSVG.js /assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betomoedano/Local-Authentication-Expo/HEAD/assets/1.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betomoedano/Local-Authentication-Expo/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betomoedano/Local-Authentication-Expo/HEAD/assets/splash.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betomoedano/Local-Authentication-Expo/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/betomoedano/Local-Authentication-Expo/HEAD/assets/adaptive-icon.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Local authentication Expo Go 2 | 3 | ## Hello my friend! 👋 4 | 5 | This is an example of how to integrate local authentication 6 | using expo go 7 | 8 | ## Check out my youtube channel for more info 9 | 10 | > [👉🏼 **Español**](https://www.youtube.com/channel/UCzkDuc3rSDyEZYo3NoHzalw) 11 | 12 | > [👉🏼 **English**](https://www.youtube.com/channel/UCh247h68vszOMA_OWpGEa5g) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "local-auth", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web", 10 | "eject": "expo eject" 11 | }, 12 | "dependencies": { 13 | "expo": "~44.0.0", 14 | "expo-local-authentication": "~12.1.0", 15 | "expo-status-bar": "~1.2.0", 16 | "react": "17.0.1", 17 | "react-dom": "17.0.1", 18 | "react-native": "0.64.3", 19 | "react-native-svg": "12.1.1", 20 | "react-native-web": "0.17.1" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.12.9" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "local-auth", 4 | "slug": "local-auth", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true, 21 | "infoPlist": { 22 | "NSFaceIDUsageDescription": "Face ID is used to authenticate the user." 23 | } 24 | }, 25 | "android": { 26 | "adaptiveIcon": { 27 | "foregroundImage": "./assets/adaptive-icon.png", 28 | "backgroundColor": "#FFFFFF" 29 | } 30 | }, 31 | "web": { 32 | "favicon": "./assets/favicon.png" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | import Auth from './src/screens/AuthScreen'; 4 | import PaymentScreen from './src/screens/PaymentScreen'; 5 | import * as LocalAuthentication from 'expo-local-authentication'; 6 | 7 | export default function App() { 8 | const [isBiometricSupported, setIsBiometricSupported] = useState(false); 9 | const [isAuthenticated, setIsAuthenticated] = useState(false); 10 | 11 | // Check if hardware supports biometrics 12 | useEffect(() => { 13 | (async () => { 14 | const compatible = await LocalAuthentication.hasHardwareAsync(); 15 | setIsBiometricSupported(compatible); 16 | })(); 17 | }); 18 | 19 | function onAuthenticate () { 20 | const auth = LocalAuthentication.authenticateAsync({ 21 | promptMessage: 'Authenticate', 22 | fallbackLabel: 'Enter Password', 23 | }); 24 | auth.then(result => { 25 | setIsAuthenticated(result.success); 26 | console.log(result); 27 | } 28 | ); 29 | } 30 | 31 | return ( 32 | 33 | { isAuthenticated 34 | ? 35 | : 36 | } 37 | 38 | ); 39 | } 40 | 41 | const styles = StyleSheet.create({ 42 | container: { 43 | flex: 1, 44 | backgroundColor: '#fff', 45 | }, 46 | }); 47 | -------------------------------------------------------------------------------- /src/screens/AuthScreen.js: -------------------------------------------------------------------------------- 1 | import {View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native'; 2 | const myImage = require('../../assets/1.png'); 3 | 4 | export default function Auth({onAuthenticate}) { 5 | return( 6 | 7 | 8 | EXPENIO 9 | Going cashless has never been this easier with the world’s most leading expense manager. 10 | 13 | Login 14 | 15 | 16 | ) 17 | } 18 | 19 | const styles = StyleSheet.create({ 20 | btn: { 21 | width: 200, 22 | alignItems: 'center', 23 | justifyContent: 'center', 24 | alignSelf: 'center', 25 | backgroundColor: '#0893FC', 26 | padding: 10, 27 | borderRadius: 5, 28 | }, 29 | image: { 30 | width: 400, 31 | height: 461, 32 | }, 33 | text: { 34 | color: '#fff', 35 | fontSize: 20, 36 | fontWeight: '500', 37 | }, 38 | title: { 39 | fontSize: 50, 40 | fontWeight: '400', 41 | marginVertical: 30, 42 | textAlign: 'center', 43 | }, 44 | description: { 45 | fontSize: 18, 46 | color: 'gray', 47 | textAlign: 'center', 48 | marginHorizontal: 20, 49 | marginBottom: 50, 50 | } 51 | }) -------------------------------------------------------------------------------- /src/screens/PaymentScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SafeAreaView, StyleSheet, TextInput, Image, View, Button, Text, TouchableOpacity } from 'react-native'; 3 | import CardSVG from '../components/CardSVG'; 4 | 5 | export default function PaymentScreen({setIsAuthenticated}) { 6 | return ( 7 | 8 | Payment 9 | 10 | PAYING 11 | Robert Downey, Jr. 12 | $50.00 13 | 18 | 19 | setIsAuthenticated(false)} 21 | style={styles.btn}> 22 | Log out 23 | 24 | 25 | ); 26 | } 27 | 28 | const styles = StyleSheet.create({ 29 | container: { 30 | flex: 1, 31 | backgroundColor: '#fff', 32 | alignItems: 'center', 33 | }, 34 | textInput: { 35 | width: '90%', 36 | height: 50, 37 | padding: 10, 38 | borderRadius: 15, 39 | backgroundColor: '#00000010', 40 | marginBottom: 20, 41 | }, 42 | image: { 43 | width: 100, 44 | height: 100, 45 | borderRadius: 100, 46 | }, 47 | btn: { 48 | width: '90%', 49 | alignItems: 'center', 50 | justifyContent: 'center', 51 | backgroundColor: '#0893FC', 52 | padding: 10, 53 | margin: 10, 54 | borderRadius: 15, 55 | marginTop: 50, 56 | }, 57 | text: { 58 | color: '#fff', 59 | fontSize: 20, 60 | fontWeight: '500', 61 | }, 62 | title: { 63 | fontSize: 40, 64 | fontWeight: 'bold', 65 | alignSelf: 'flex-start', 66 | paddingLeft: 15, 67 | paddingBottom: 20, 68 | } 69 | }) -------------------------------------------------------------------------------- /src/components/CardSVG.js: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import Svg, { Path, Defs, LinearGradient, Stop } from "react-native-svg" 3 | 4 | const SvgComponent = (props) => ( 5 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 61 | 69 | 70 | 71 | 72 | 80 | 81 | 82 | 83 | 91 | 92 | 93 | 94 | 102 | 103 | 104 | 105 | 113 | 114 | 115 | 116 | 124 | 125 | 126 | 127 | 128 | 129 | ) 130 | 131 | export default SvgComponent 132 | --------------------------------------------------------------------------------