React client-side authentication with Facebook, LinkedIn and Google

Written by: Mario Grunitz

react-login

By Dmitry Shishko, full-stack developer at WeAreBrain.


In this article, I will be showing you how we used React to enable authentication for social networks on the client-side.

The steps

The main objective is to take the unique identifier of a user (uid, email, name), and then send these params to the backend (PHP, Ruby, NodeJS) to finish the auth process.

const addScript = (id, src) => new Promise((resolve, reject) => {
 const element = document.getElementById(id);
if (element) {
  return resolve(true);
 }
const script = document.createElement('script');
 script.setAttribute('type', 'text/javascript');
 script.setAttribute('id', id);
 script.setAttribute('src', src);
 script.addEventListener('load', resolve);
script.addEventListener('error', () => reject(new Error(`Error loading ${id}.`)));
script.addEventListener('abort', () => reject(new Error(`${id}  loading aborted.`)));
document.getElementsByTagName('head')[0].appendChild(script);
});
export const addFacebookScript = () => {
  const id = 'facebookAuth';
  const src = 'https://connect.facebook.net/en_US/sdk.js';
  
  return addScript(id, src);
};
export const addGoogleScript = () => {
  const id = 'googleAuth';
  const src = '//apis.google.com/js/client:platform.js';
return addScript(id, src);
};
export const addLinkedInScript = () => {
  const id = 'linkedinAuth';
  const src = '//platform.linkedin.com/in.js?async=true';
  
  return addScript(id, src);
};

The second step is to create a LinkedIn auth component. To set up Linkedin you need a LINKEDIN_API_KEY. Lets go to the Linkedin development panel and create an app:

/* global IN */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { addLinkedInScript } from './scripts';
export default class LinkedIn extends PureComponent {
 async componentDidMount() {
  try {
   await addLinkedInScript();
   // Initializtoin with you API_KEY
   IN.init({ api_key: LINKEDIN_API_KEY });
  } catch (error) {
    console.log(error.name, ':', error.message);
  }
 }
/**
 * Handle click button
 */
 handleClick = () => {
  const {
   loading,
   onSuccess,
   onFailure,
  } = this.props;
 
 if (loading || !IN.User) {
  return;
 }
IN.User.authorize(() => {
 // If authorization pass well, we take profile info
 IN.API.Profile('me')
  .fields(['id', 'firstName', 'lastName', 'emailAddress'])
  .result((res) => {
    const data = {};
    data.identity = {
      uid: IN.User.getMemberId(),
      provider: 'linkedin'
    };
    data.user = {
     email: res.values[0].emailAddress,
     firstName: res.values[0].firstName,
     lastName: res.values[0].lastName,
    };
    data.auth = IN.ENV.auth;
// Send data to back end
    onSuccess(data);
   });
  },
  err => onFailure(err));
 }
render() {
  return (
   <span
     className="btn linkedin"
     onClick={this.handleClick}
   >
    <i className="icon-in" />
   </span>
   );
  }
 }
LinkedIn.propTypes = {
 loading: PropTypes.bool.isRequired,
 onSuccess: PropTypes.func.isRequired,
 onFailure: PropTypes.func.isRequired,
};

Third, create a Google auth component; to initiate Google you will need a GOOGLE_CLIENT_ID. Go to the Google Developers Console and create a new project, you can do it here.

/* global gapi */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { addGoogleScript } from './scripts';
export default class Google extends PureComponent {
 async componentDidMount() {
  try {
   await addGoogleScript();
   const params = {
    client_id: GOOGLE_CLIENT_ID,
    scope: 'profile email',
   };
   gapi.load('auth2', () => {
    if (!gapi.auth2.getAuthInstance()) {
     gapi.auth2.init(params);
    }
   });
  } catch (error) {
   console.log(error.name, ':', error.message);
  }
 }
/**
 * Handle click button
 */
 handleClick = () => {
  const { loading, onSuccess, onFailure } = this.props;
  const auth2 = gapi.auth2.getAuthInstance();
  
  if (loading) {
   return;
  }
auth2.signIn()
   .then((res) => {
     // If authorization pass well, we take profile info
     const basicProfile = res.getBasicProfile();
     const data = {};
     data.identity = {
      uid: basicProfile.getId(),
      provider: 'google'
     };
     data.user = {
      email: basicProfile.getEmail(),
      firstName: basicProfile.getGivenName(),
      lastName: basicProfile.getFamilyName(),
     };
     data.auth = res.getAuthResponse();
     
     // Send data to back end
     onSuccess(data);
    },
    err => onFailure(err));
 }
render() {
  return (
   <button
    type="button"
    className="btn google"
    onClick={this.handleClick}
   >
    <i />
   </button>
  );
 }
}
Google.propTypes = {
 loading: PropTypes.bool.isRequired,
 onSuccess: PropTypes.func.isRequired,
 onFailure: PropTypes.func.isRequired,
};

Fourth, create a Facebook auth component; to set up Facebook you will need a FACEBOOK_APP_ID, go to Facebook and create an app:

/* global FB */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { addFacebookScript } from './scripts';
export default class Facebook extends PureComponent {
 static propTypes = {
  loading: PropTypes.bool.isRequired,
  onSuccess: PropTypes.func.isRequired,
  onFailure: PropTypes.func.isRequired,
 };
 
 async componentDidMount() {
  try {
   await addFacebookScript();
   const params = {
    appId: FACEBOOK_APP_ID,
    cookie: false,
    xfbml: false,
    version: 'v3.2'
   };
   FB.init(params);
   FB.getLoginStatus(resp => console.log('FB:status:', resp.status));
  } catch (error) {
   console.log(error.name, ':', error.message);
  }
 }
 
 handleClick = () => {
  const { loading, onSuccess } = this.props;
  if (loading) {
   return;
  }
 
  FB.getLoginStatus((resp) => {
   console.log('FB:status:', resp.status);
    const params = {
     provider: 'facebook'
    };
  
   if (resp.status === 'connected') {
    params.uid = resp.authResponse.accessToken;
// Send data to back end
    onSuccess(params);
    return;
   }
 
   FB.login((response) => {
    console.log('FB:status:', response.status);
    if (response.authResponse) {
     params.uid = resp.authResponse.accessToken;
     onSuccess(params);
    }
   }, { scope: 'email' });
  });
 }
 
 render() {
  return (
   <button
    type="button"
    className="btn facebook"
    onClick={this.handleClick} >
    <i className="icon-facebook" />
   </button>
  );
 }
}

And that’s it!

Now we’ve created three components, which allow you to get a user’s information from their socials, and send it to your backend.

Hope this was helpful.

(Visited 2,312 times, 2 visits today)
Last modified: May 29, 2020
Author info
Mario Grunitz
Mario is a WeAreBrain Co-founder. With more than 15 years of experience in the tech space, he has worked all over Europe and held countless leadership positions in corporate, startup and agency spheres.
Close