Newby Coder header banner

Implementing Facebook Login in React Native

Facebook Login can be integrated in react native using react-native-fbsdk to provide login functionality to application users via their Facebook account

This can be used as an alternative to user registration, and also can be considered secure

Response from server contains an access token which can be used to send facebook graph api request to get user's public profile data and additional private data if permission was requested for it

Provided example uses LoginManager to initiate webview login, because of which facebook login button was imported from react-native-social-buttons

react-native-fbsdk also provides a LoginButton component which initiates the Facebook login dialog but there was an issue: its onLoginFinished callback was not getting called

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

When using LoginButton, it changes to a logout button after login

Usage

Import
import { LoginManager } from "react-native-fbsdk";
import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk';
import { FacebookSocialButton } from "react-native-social-buttons";
Using loginmanager to initiate login dialog
  async signIn() {
    var result = await LoginManager.logInWithPermissions(["public_profile", "email"]);
    if (result.isCancelled) {
      console.log("Login cancelled");
    } else {
      // console.log("permissions granted : " + result.grantedPermissions.toString());
      this.graphRequest();
    }
  }
Graph request to get user data

Graph request, sent after user logs in and grants permission, returns profile data of user

  _responseInfoCallback(error: ?Object, result: ?Object) {
    if (error) {
      console.log('Error fetching data: ' + error.toString());
    } else {
      this.setState({user: result, authenticated: true});
    }
  }

  async graphRequest() {
    // Create a graph request asking for user information with a callback to handle the response.
    const infoRequest = new GraphRequest(
      '/me?fields=name,picture,email',
      null,
      // a lambda is used due to the presence of 'this' keyword inside _responseInfoCallback
      // on using _responseInfoCallback (function name) instead of lambda, this.setState() becomes out of scope
      // alternatively try defining _responseInfoCallback inside graphRequest()
      (err, res) => {this._responseInfoCallback(err, res);}
    );
    // Start the graph request
    const response = await new GraphRequestManager().addRequest(infoRequest).start();
  }

Creating new React Native App

Check React Native Installation for installation related info

Use react-native init command to create a new React Native project (here named NcFacebookLoginApp)

react-native init NcFacebookLoginApp

This creates a directory named NcFacebookLoginApp and initializes it as a react native application directory

This can be skipped in case an existing react native project is being integrated into

Dependency

To use LoginManager, GraphRequest, add react-native-fbsdk to project

Go to project directory and run following yarn command to install the dependency

yarn add react-native-fbsdk react-native-social-buttons

Or using npm

npm install react-native-fbsdk react-native-social-buttons --save

react-native-social-buttons is added for FacebookSocialButton

Setup

Create a Facebook App ID & App Name

Login to https://developers.facebook.com/ and click on MyApps

Click on Create App

cl-facebook-create-app

Select an option which mentions Facebook Login (option 3)

cl-facebook-create-app-select-type

Enter app id which should not contain Facebook trademark or brand elements like fb, and click Create App ID

cl-facebook-create-app-enter-appid

Android settings

App Code

A boolean state variable authenticated is used to determine whether to show login button or profile data

NcFacebookLoginApp(react native app name)/App.js
import React from 'react';
import {
  View,
  Text,
  Image
} from 'react-native';
import { LoginManager } from "react-native-fbsdk";
import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk';
import { FacebookSocialButton } from "react-native-social-buttons";

export default class App extends React.Component {

  constructor() {
    super();
    this.state = {
      authenticated: false
    }
  }

  _responseInfoCallback(error: ?Object, result: ?Object) {
    if (error) {
      console.log('Error fetching data: ' + error.toString());
    } else {
      this.setState({user: result, authenticated: true});
    }
  }

  async graphRequest() {
    const infoRequest = new GraphRequest(
      '/me?fields=name,picture,email',
      null,
      (err, res) => {this._responseInfoCallback(err, res);}
    );
    const response = await new GraphRequestManager().addRequest(infoRequest).start();
  }

  async signIn() {
    var result = await LoginManager.logInWithPermissions(["public_profile", "email"]);
    if (result.isCancelled) {
      console.log("Login cancelled");
    } else {
      this.graphRequest();
    }
  }

  signInButton() {
    return (
      <View>
        <FacebookSocialButton onPress={() => {this.signIn();}}/>
      </View>
    );
  }

  renderUser() {
    const { email, picture, name } = this.state.user;
    return (
      <View style={{ alignItems: 'center', width:'100%'}}>
        <View>
        { picture.length == 0? null:
          <Image source={{uri:picture.data.url}} style={{ width:130, height:130, marginBottom:20 }}/> }
        </View>
        <View style={{ width:'100%', alignItems: 'center', backgroundColor:'#628367', padding:20}}>
          <Text style={{color:'white'}}>Name: {name}</Text>
          <Text style={{color:'white'}}>Email: {email}</Text>
        </View>
      </View>
    );
  };

  render() {
    return (
      <View style={{ backgroundColor: 'white', flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          { this.state.authenticated? this.renderUser() : this.signInButton()}
      </View>
    );
  };
};

Run instructions

Running in Android

cd into project directory (here NcFacebookLoginApp)

cd NcFacebookLoginApp

Run metro server to serve js

react-native start

Go to project directory in another terminal tab

Enter following run command for Android:

react-native run-android
cl-react-native-android-facebook-login1cl-react-native-android-facebook-login2cl-react-native-android-facebook-login4

App was edited to include email in list of permissions

cl-react-native-android-facebook-login3

Subsequent logins

cl-react-native-android-facebook-login5