How to use facebook login in react native using firebase

firebase facebook login api directly doesn’t work in react native because it’s built to be used with http or https protocol. So, in this article I will show you how to use facebook login in react native using firebase.

First we need to install two modules in are react native app ie react-native-fbsdk module and firebase module.

To install react-native-fbsdk module follow the steps given here :

https://github.com/facebook/react-native-fbsdk

Next, install firebase module using the command below :

npm install firebase --save

Now go to https://firebase.google.com and login using your google username and password. Click on ‘GO TO CONSOLE’ and then click on ‘Add Project’. Give name to your project and click on ‘Create Project’. Now click on ‘Add Firebase to your web app’, you will get a modal with firebase api details . For our app we need ‘apiKey’ and ‘databaseURL’.

One more module we will be using in this article, that is, reactnavigation. I have discussed this module in detail my previous articles. Make sure to go though that if you have not used reactnavigation module before :

http://calsob.in/react-native-navigation-the-better-way/

Now we will add the code below in our index file :

import React, { Component } from 'react';
import {
  AppRegistry
} from 'react-native';
import Login from './login'
import Home from './home'
import {StackNavigator} from 'react-navigation'
import * as firebase from 'firebase'
const firebaseConfig = {
  apiKey: "AIzaSyBOVXrZVMXGiPQJdQiDpFYg_T_QigyHyP4",
  databaseURL: "https://mytestapp-94d40.firebaseio.com",
}
firebase.initializeApp(firebaseConfig)

const RouteConfigs = {
    Login: {screen:Login},
    Home: {screen:Home}
}

const StackNavigatorConfig = {
    headerMode: 'none',
}

const InvisionApp = StackNavigator(RouteConfigs, StackNavigatorConfig)

AppRegistry.registerComponent('InvisionApp', () => InvisionApp);

In the above code, we have initialized firebase with ‘apiKey’ and ‘databaseURL’ we got from our firebase app. Next, we configured the reactnavigation with Login screen and Home screen so that we can navigate from login screen to home screen once the facebook authentication is successful.

Now, we will add code below to our login.js file :

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Dimensions,
  ActivityIndicator,
  Button
} from 'react-native';
import firebase from 'firebase'
import { NavigationActions } from 'react-navigation'
const FBSDK = require('react-native-fbsdk');
const { LoginManager, AccessToken } = FBSDK;
const { width, height } = Dimensions.get('window')

export default class Login extends Component {

  constructor(props) {
   super(props);
   this.state = {
      showSpinner: true
    }
  }
  componentDidMount() {
    
    this.fireBaseListener = firebase.auth().onAuthStateChanged(auth => {
      if (auth) {
        this.firebaseRef = firebase.database().ref('users')
        this.firebaseRef.child(auth.uid).on('value', snap => {
          const user = snap.val()
          if (user != null) {
            this.firebaseRef.child(auth.uid).off('value')

             this.goHome(user)

          }
        })


      } else {
        this.setState({ showSpinner: false })
      }
    })
  }
  goHome(user) {
    const resetAction = NavigationActions.reset({
      index: 0,
      actions: [
        NavigationActions.navigate({ routeName: 'Home', params: { user } }),
      ],
    })
    this.props.navigation.dispatch(resetAction)

  }
  onPressLogin(){
      this.setState({ showSpinner: true })
        LoginManager.logInWithReadPermissions(['public_profile', 'user_birthday', 'email', 'user_photos'])
        .then((result) => this._handleCallBack(result),
          function(error) {
            alert('Login fail with error: ' + error);
          }
        )
  }
  _handleCallBack(result){
    let _this = this
    if (result.isCancelled) {
      alert('Login cancelled');
    } else {   
  AccessToken.getCurrentAccessToken().then(
          (data) => {
          
            const token = data.accessToken
            fetch('https://graph.facebook.com/v2.8/me?fields=id,first_name,last_name,gender,birthday&access_token=' + token)
            .then((response) => response.json())
            .then((json) => {
          
              const imageSize = 120
              const facebookID = json.id
              const fbImage = `https://graph.facebook.com/${facebookID}/picture?height=${imageSize}`
             this.authenticate(data.accessToken)
              .then(function(result){
                const { uid } = result               
                _this.createUser(uid,json,token,fbImage)
              })


            })
            .catch(function(err) {
            	  console.log(err);
            });
          }
        )

    }
  }
  authenticate = (token) => {
    const provider = firebase.auth.FacebookAuthProvider
    const credential = provider.credential(token)
    let ret = firebase.auth().signInWithCredential(credential)
    return ret;
  }
  createUser = (uid,userData,token,dp) => {
    const defaults = {
      uid,
      token,
      dp,
      ageRange: [20, 30]
    }
    firebase.database().ref('users').child(uid).update({ ...userData, ...defaults })
   
  }
  render() {
    return (
       this.state.showSpinner ? <View style={styles.container}><ActivityIndicator animating={this.state.showSpinner} /></View> :
     <View style={styles.container}>
           <Button
            onPress={this.onPressLogin.bind(this)}
            title="Login with facebook"
            color="#841584"
            />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  }  
});

In the above code first we are setting the showSpinner state to true, so that, when authentication state is being checked user can see spinner instead of blank screen.  When Login component mounts,  we check the the authentication state of the the user with firebase api. If authentication state is true ie the user is already authenticated then we simply redirect the user to Home Page with users info ( that is saved in firebase db when user was authenticated ).

If user login is for the first time then firebase auth state will be false. So, showSpinner will be set to false and instead of spinner user will se Facebook login button. When user press login button showSpinner state is set to true and user get to see spinner on screen. Then, Facebook authenticates user and generate a authentication token. We use this token to sign in user to firebase using firebase signInWithCredential method. After that, we save users data in firebase db. Mean while authentication state changes to true and user is redirected to home screen with users info, that is fetched from firebase db.

Here is a demo of Facebook login in react native with firebase