I'm attempting to write a React Native app using Firebase and Facebook Auth. Here is the complete app code:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { LoginManager, AccessToken, LoginButton } from 'react-native-fbsdk';
import * as f from './config/firebase';
export default class App extends React.Component {
fbLoginHandler(error, result) {
if (error) {
alert('Login failed with error: ' + error);
} else if (result && result.isCancelled) {
alert('Login cancelled');
} else {
AccessToken.getCurrentAccessToken().then((accessTokenData) => {
const credential = f.provider.credential(accessTokenData.accessToken);
f.auth.signInAndRetrieveDataWithCredential(credential).then((s) => {
alert('Success! ' + s);
}, (signinError) => {
console.log('Signin error', signinError);
alert('Signin error' + signinError);
});
}, (tokenError) => {
alert('Some error occurred' + tokenError);
});
}
}
render () {
return (
<View style={styles.container}>
<LoginButton
readPermissions={['public_profile', 'email']}
onLoginFinished={(error, result) => this.fbLoginHandler(error, result)}
onLogoutFinished={() => alert('logout.')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
}
});
This is my Firebase config file (the './config/firebase'
import in the above snippet):
import * as firebase from 'firebase';
const config = {
apiKey: <api key>,
authDomain: <auth domain>,
databaseURL: <database URL>,
projectId: <project ID>,
storageBucket: <storage bucket>,
messagingSenderId: <messaging sender ID>
};
firebase.initializeApp(config);
export const database = firebase.database();
export const auth = firebase.auth();
export const provider = new firebase.auth.FacebookAuthProvider();
I have entered the required OAuth redirect URI on my Facebook console, as instructed in the Firebase documentation. I've also added a few others based on suggestions found in other Stack Overflow threads. The redirect URIs I'm authorizing are:
https://<MyAppID>.firebaseapp.com/__/auth/handler
https://auth.firebase.com/auth/facebook/callback
https://auth.firebase.com/v2/<MyAppID>/auth/facebook/callback
https://localhost/
http://localhost/
The auth process gets part of the way there (I can see on my Facebook console that a user has been authenticated) but signInAndRetrieveDataWithCredential(credential)
returns an error:
{
code: "auth/internal-error",
message: {
error:{
code:400,
message:"Callback URL does not contain state: http://localhost?id_token=<token>&providerId=facebook.com",
errors:[{
message:"Callback URL does not contain state: http://localhost?id_token=<token>&providerId=facebook.com",
domain:"global",
reason:"invalid"
}]
}}
}
}
I have searched the internet, the Facebook developer documentation, the Firebase documentation, and of course Stack Overflow, but I can't find any reference to this specific error anywhere. I believe the error - despite being returned from a Firebase function - is simply being passed through from the Facebook Auth API, but I am not even 100% sure about that.
My assumption is that I must have an incorrect config setting in either Facebook or Firebase, but I've already tried altering the obvious ones (e.g. the redirect URIs, all the OAuth option toggles, etc.) with no change in the error message.
Any insights would be greatly appreciated!
Although I still am not able to diagnose this specific error, I found an effective solution by using the third party react-native-firebase
package in place of Google's firebase
package:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { LoginManager, AccessToken, LoginButton } from 'react-native-fbsdk';
import firebase from 'react-native-firebase';
export default class App extends React.Component {
fbLoginHandler(error, result) {
if (error) {
alert('Login failed with error: ' + error);
} else if (result && result.isCancelled) {
alert('Login cancelled');
} else {
AccessToken.getCurrentAccessToken().then((accessTokenData) => {
const credential = firebase.auth.FacebookAuthProvider.credential(accessTokenData.accessToken);
firebase.auth().signInAndRetrieveDataWithCredential(credential).then((s) => {
alert('Success! ' + s);
}, (signinError) => {
console.log('Signin error', signinError);
alert('Signin error' + signinError);
});
}, (tokenError) => {
alert('Some error occurred' + tokenError);
});
}
}
render () {
return (
<View style={styles.container}>
<LoginButton
readPermissions={['public_profile', 'email']}
onLoginFinished={(error, result) => this.fbLoginHandler(error, result)}
onLogoutFinished={() => alert('logout.')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
}
});