1. Preparing the React Native(Expo) Development Environment
Please follow the Expo official documentation to set up your React Native(Expo) development environment.
If you already have the React Native(Expo) development environment set up, you can proceed to the next step.
Download the Git Repository
If you want to download and use the sample project, use the following command to download the git repository.
Download the Furo Expo Sample project.
git clone https://github.com/furo-official/furo-sample-expo
2. Installing and Using Libraries
Use the following command to install the required libraries.
In this guide, we will additionally use the following libraries.
import { NavigationContainer } from '@react-navigation/native' ;
import { createNativeStackNavigator } from '@react-navigation/native-stack' ;
const Stack = createNativeStackNavigator ();
< NavigationContainer linking = { linking } >
< Stack.Navigator >
< Stack.Screen name = "Home" component = { HomeScreen } />
</ Stack.Navigator >
</ NavigationContainer > ;
react-native-inappbrowser-reborn
Used to open the Furo login page through the InApp browser.
import { InAppBrowser } from 'react-native-inappbrowser-reborn' ;
const response = await InAppBrowser . openAuth ( url , 'exp://' , options );
axios
Used to call Furo’s authentication API.
import axios from 'axios' ;
const { data } = await axios . post (
'https://api.furo.one/sessions/code/authenticate' ,
{ code },
);
3. Integrating Furo Login
Add the Client ID value copied from the Furo console to the .env file. If the .env file doesn’t exist, create it and set the environment variable as follows:
EXPO_FURO_CLIENT_ID = "{{YOUR_CLIENT_ID}}"
Enter exp://
in the Default Callback URI input field of the Furo console.
redirectUri and callbackUri
These attributes are used to redirect the user to a specific page within the application after login.
redirectUri can be specified directly within the application, while Default Callback URI can be specified in the Furo console.
The redirectUri specified within the app is at risk of being maliciously manipulated during communication, so redirectUri only works normally with URIs registered in the Default Callback URI in the Furo console.
4. Full Sample Code
import React , { useCallback , useEffect , useState } from 'react' ;
import { StatusBar } from 'expo-status-bar' ;
import { StyleSheet , Text , View , Button , Linking } from 'react-native' ;
import { NavigationContainer } from '@react-navigation/native' ;
import { createNativeStackNavigator } from '@react-navigation/native-stack' ;
import { InAppBrowser } from 'react-native-inappbrowser-reborn' ;
import axios from 'axios' ;
const CLIENT_ID = process . env . EXPO_FURO_CLIENT_ID ;
const LOGIN_URL = `https://auth.furo.one/login/ ${ CLIENT_ID } ` ;
const Stack = createNativeStackNavigator ();
export default function App () {
const linking = {
prefixes: [ 'exp://' ],
config: {
screens: {
Home: '*' ,
},
},
};
const Stack = createNativeStackNavigator ();
return (
< NavigationContainer linking = { linking } >
< Stack.Navigator >
< Stack.Screen name = "Home" component = { HomeScreen } />
</ Stack.Navigator >
</ NavigationContainer >
);
}
const HomeScreen = () => {
const [ accessToken , setAccessToken ] = useState ( null );
const openURLFromInAppBrowserOrLinking = useCallback ( async ( url ) => {
try {
if ( await InAppBrowser . isAvailable ()) {
const response = await InAppBrowser . openAuth ( url , 'exp://' , {
// iOS Properties
ephemeralWebSession: false ,
// Android Properties
showTitle: false ,
enableUrlBarHiding: true ,
enableDefaultShare: false ,
showInRecents: true ,
forceCloseOnRedirection: true ,
});
if ( response . type === 'success' && response . url ) {
console . log ( response );
Linking . openURL ( response . url );
}
} else {
Linking . openURL ( url );
}
} catch ( error ) {
console . error ( error );
}
}, []);
useEffect (() => {
const handleDeepLink = ({ url }) => {
const code = url . split ( '?' )[ 1 ]?. match ( /code= ([^ & ] + ) / )?.[ 1 ];
if ( code ) {
authenticateWithCode ( code )
. then (( response ) => {
const { access_token } = response ;
setAccessToken ( access_token );
})
. catch (( e ) => {
console . log ( 'error: ' , e . response . data );
});
}
};
Linking . addEventListener ( 'url' , handleDeepLink );
return () => {
Linking . removeAllListeners ( 'url' );
};
}, []);
const authenticateWithCode = async ( code ) => {
const { data } = await axios . post (
'https://api.furo.one/sessions/code/authenticate' ,
{ code },
);
return data ;
};
return (
< View style = { styles . container } >
< Text style = { styles . title } > [Furo] React Native(Expo) Example </ Text >
< View style = { styles . content } >
{ accessToken ? (
<>
< Text > { accessToken } </ Text >
< Button title = "Clear" onPress = { () => setAccessToken ( null ) } />
</>
) : (
< Button
title = "Login"
onPress = { () => openURLFromInAppBrowserOrLinking ( LOGIN_URL ) }
/>
) }
</ View >
< StatusBar style = "auto" />
</ View >
);
};
const styles = StyleSheet . create ({
container: {
flex: 1 ,
backgroundColor: '#fff' ,
alignItems: 'center' ,
justifyContent: 'center' ,
},
title: {
fontSize: 16 ,
fontWeight: '600' ,
},
content: {
marginTop: 10 ,
width: '80%' ,
alignItems: 'center' ,
},
});
Now the Furo login integration is complete in your React Native app.
When you run the app and click the Login
button, the Furo login page will open in the InApp browser, and once the login is completed, the accessToken will be displayed on the screen.