Is there a way to implement logging into facebook without having to input facebook user name and password?
I found this: https://github.com/magus/react-native-facebook-login. I’m using CRNA (create-react-native-app) with Expo and from what I understand I’d have to eject the project in order to use react-native-facebook-login because there is native code in that component.
I’d like to mimic the behavior that react-native-facebook-login provides. Is that possible using expo?
It’s what I’m using now but the pop-up requires a user to login with their username (email/phone number) and password. The behavior I’m looking for is for the user not to have to enter that info as demo’d here: https://github.com/magus/react-native-facebook-login
If you mean you want to read whatever Facebook authorization already exists on the device, the only way to do that on Expo iOS right now is to use the WebBrowser module (which shares cookies with Safari). cc @notbrent
Thanks. I opened it (https://github.com/expo/examples/tree/master/with-facebook-auth) in the expo app but it looks like this example also prompts the user to log in Facebook with username and password but the only difference is that I think it’s via web view rather than the Expo style popup.
Hi @hiromih! the example in with-facebook-auth shows how to use SFSafariViewController on iOS and Chrome Custom Tabs on Android via the Expo WebBrowser module. These underlying APIs share cookies with Safari / Chrome, so if the user has ever logged into Facebook with their device’s web browser then they will not need to enter a username / password. This is by far the most common way to do OAuth on mobile apps these days.
If you would like to use the Facebook app itself (not recommended), you can follow the steps in the documentation, in particular you will need to use native behavior on iOS and system on Android. This is a pain because it works differently in the Expo client and in standalone apps, and requires a lot of configuration.
I thought I might share my experience making it work in the Expo client & a standalone app since this seems like something many other Expo users may be interested in.
I noticed in your example, you have two deployments of the backend server (e.g. local expo app, and published expo app). I ended up doing a hack where I passed the redirect link to my small express server because there’s several different types of redirects you might want to do:
A) expo on real phone: (e.g. exp://qq-7gt.username.yarn.exp.direct/+)
B) expo on simulator: (e.g. exp://localhost:19000/+)
C) standalone app (e.g. customApp://…)
Even within expo, the ports might change or subdomain identifier, so it seems cumbersome to have to re-deploy a small express app for each unique path.
This is the relevant snippet I used for normalizing across these cases:
It seems sketchy to me (security-wise) so I’m going to whitelist certain linkingUrl on the server-side.
It feels very hacky but it works and it’s such a nice UX flow. What do you think? I can’t think of a better way without actually detaching from Expo and using the official FB RN SDK.
How to you setup the redirect url? On iOS, my app can ask permissions but once they are given, I get invalid redirect url on ios, with this as the safari url: Log into Facebook | Facebook
You need to setup a small server to redirect to your exp app because Facebook doesn’t allow you to directly redirect to a custom scheme. You can use now.sh or Firebase Functions to deploy this server.
I made a Firebase Function, but what URL do you need to put for the redirect for my standalone app? I saw in the app.json configuration that i can create a scheme for the redirect, but where can I find the actual URL to redirect to my from from my function?
Here’s a quick consolidation of the Facebook + Instagram (non-graph api auth) code I’ve used. I added a quick conditional only to show that this code can be used for either Social Login. The _openWebBrowserAsync() is essentially from wth-webbrowser-redirect example.
const isProduction = appOwnership === 'standalone';
const responseType = 'token';
const redirectUrl = isProduction
? Linking.makeUrl('/login')
: AuthSession.getRedirectUrl();
const socialUrl = socialType === 'facebook'
? 'https://www.facebook.com/v3.2/dialog/oauth?'
: `https://api.instagram.com/oauth/authorize/?`;
const authUrl = `${socialUrl}`
+ `client_id=${clientId}`
+ `&redirect_uri=${encodeURIComponent(redirectUrl)}`
+ `&response_type=${responseType}`;
const result = isProduction
? await this._openWebBrowserAsync(authUrl)
: await AuthSession.startAsync({ authUrl });
if (['cancel', 'dismissed', 'error', 'locked'].includes(result.type)) {
/*
type:
- 'cancel': process manually interrupted by user through closing browser
- 'dismissed': process manually interrupted by us (AuthSession.dismiss())
- 'error': {type: 'error', params: Object, errorCode: string, event: Object }
- 'locked': an AuthSession was attempted while another was active
if type='cancel', then there's a chance they wanted the business authentication,
and this is where the prompt screen could be applied.
*/
// eslint-disable-next-line
console.error('[LoginScreen] onLoginWithSocial FAIL. result: ', JSON.stringify(result, null, 2));
return;
}
// result will be of format: { type: 'success', params: Object, event: Object }
const socialToken = result.params.access_token;