A guide on setting up and using Facebook authentication with AuthSession API in your Expo app.
AuthSession API allows browser-based authentication (using OAuth or OpenID Connect) to your project for Android, iOS, and the web. This guide provides steps on configuring and using the API with Facebook and a development build.
1
To use AuthSession API, you'll need to install the following packages in your project:
-
npx expo install expo-auth-session expo-crypto expo-web-browser
If you're using SDK 47 or below, you'll need to install expo-random
instead of expo-crypto
package:
-
npx expo install expo-auth-session expo-random expo-web-browser
expo-random
is deprecated from SDK 48 and above and is replaced by expo-crypto
.
2
For a development build and when setting up production apps, define scheme
in the app.json. It is required for the authentication flow to complete the process and redirect the user back to the app. It handles the process of deep linking back to the app.
{
"expo": {
"scheme": "yourscheme"
}
}
If you do not provide a value for the scheme
, the authentication flow will complete, however, the user will not be redirected back to the app. They will have to manually exit the authentication popup which will result in the rejection of the process.
For Android, you'll need to add a scheme that contains the app ID as a prefix. Facebook requires this scheme to be able to redirect the user back to the app after the authentication process is complete.
For example, if your app ID is 1234567890
, then the scheme will be fb1234567890
. Modify the scheme
in app config and convert it to an array if you have more than one custom scheme to add this scheme:
{
"expo": {
"scheme": ["yourscheme", "fb1234567890"]
}
}
3
To use Facebook authentication, you'll need to create a Facebook app, enable the Facebook login product and get the app ID.
scheme://expo-development-client/?url={manifestUrl}
# Example
yourscheme://expo-development-client/?url=https://u.expo.dev/[your-eas-build-project-id]?channel-name=[channel-name]
Replace scheme
with the one you defined in the previous step. To learn what goes in the manifestUrl
parameter, read the development workflows section. Click Save changes.
Navigate to Settings > Basic, add a Privacy Policy URL for your app and click Save changes. This will help you get advance access (if required) for public_profile permission.
Also, copy the App ID as shown in the above screenshot. You'll need it in the next step.
1
Add the following import statements to your project code. The WebBrowser
API, AuthSession
API, and the Facebook
provider from the expo-auth-session
are essential to handle the authentication process.
import * as AuthSession from 'expo-auth-session';
import * as Facebook from 'expo-auth-session/providers/facebook';
import * as WebBrowser from 'expo-web-browser';
2
Expo's WebBrowser API provides maybeCompleteAuthSession()
method to dismiss the popup when the authentication sessions are completed successfully. It uses the redirect URL added in the provider's authorized list of URLs.
Invoke this method to the app screen you want to redirect back to by adding the following code snippet:
WebBrowser.maybeCompleteAuthSession();
If this method is not invoked, the popup will not dismiss itself.
3
Facebook.useAuthRequest()
hook provides request
and response
objects. It allows for async setup, which means that a mobile web browser won't block the request. It also accepts an object of client IDs that are generated in the Facebook app.
Define this hook inside the React component by adding the code snippet below:
export default function App() {
const [request, response, promptAsync] = Facebook.useAuthRequest({
clientId: "FB_APP_ID",
});
%%placeholder-start%%... %%placeholder-end%%
}
In the above code snippet, replace the FB_APP_ID
with the client ID generated in the Facebook app.
4
useAuthRequest()
hook also provides promptAsync()
that prompts the user to authenticate by opening a web browser. It is invoked when the user clicks the login button. The button must be disabled until the request is loaded asynchronously. This is done by passing the request
object from the useAuthRequest
hook to the disabled
prop of the button component.
An example button component that invokes promptAsync()
is shown below:
<Button
disabled={!request}
title="Sign in with Facebook"
onPress={() => {
promptAsync();
}}
/>
In the code snippet below, you can see a minimal working example of the AuthSession API with the Facebook provider. After successful authentication, a user's public information is fetched and displayed on the app screen.
import { useState, useEffect } from "react";
import { Button, Image, StyleSheet, Text, View } from "react-native";
import * as AuthSession from "expo-auth-session";
import * as Facebook from "expo-auth-session/providers/facebook";
import * as WebBrowser from "expo-web-browser";
WebBrowser.maybeCompleteAuthSession();
export default function App() {
const [user, setUser] = useState(null);
const [request, response, promptAsync] = Facebook.useAuthRequest({
clientId: "FB_APP_ID",
});
if (request) {
console.log(
"You need to add this url to your authorized redirect urls on your Facebook app: " +
request.redirectUri
);
}
useEffect(() => {
if (response && response.type === "success" && response.authentication) {
(async () => {
const userInfoResponse = await fetch(
`https://graph.facebook.com/me?access_token=${response.authentication.accessToken}&fields=id,name,picture.type(large)`
);
const userInfo = await userInfoResponse.json();
setUser(userInfo);
})();
}
}, [response]);
const handlePressAsync = async () => {
const result = await promptAsync();
if (result.type !== "success") {
alert("Uh oh, something went wrong");
return;
}
};
return (
<View style={styles.container}>
{user ? (
<Profile user={user} />
) : (
<Button
disabled={!request}
title="Sign in with Facebook"
onPress={handlePressAsync}
/>
)}
</View>
);
}
function Profile({ user }) {
return (
<View style={styles.profile}>
<Image source={{ uri: user.picture.data.url }} style={styles.image} />
<Text style={styles.name}>{user.name}</Text>
<Text>ID: {user.id}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
profile: {
alignItems: "center",
},
name: {
fontSize: 20,
},
image: {
width: 100,
height: 100,
borderRadius: 50,
},
});
For a development build, see Use development builds for further instructions on how to start the development server or run npx expo run:android
or npx expo run:ios
command to test the native project locally.
For a development build or projects using EAS, the URI scheme is automatically added.
For bare workflow, your project needs to conform to the URI scheme matching your android.package
for Android and ios.bundleIdentifier
for iOS. You can do that by running the following command for each platform:
-
npx uri-scheme add your-android.package --android
-
npx uri-scheme add your-ios.bundleIdentifier --ios
react-native-fbsdk-next
library with a development build.