How to create a WordPress plugin to login and register using Facebook API

blog demo

20

Feb 2017
WOffice

How to create a WordPress plugin to login and register using Facebook API

In this tutorial, we will see how to write a simple WordPress plugin in order to Login and Register your users right on your WordPress site using the Facebook API. It is very easy to do and we will go through each step one by one.
You need to have basics in PHP, WordPress development, CSS and HTML. But nothing tricky here.
You can find the complete plugin on Github: Plugin repository
Note that this is a first part, as you will see at the end, there are many things that can be improved.
Update: You can find part 2 here!
The authentication flow from Facebook is quite simple:

  • We use the Facebook SDK to generate a login link to redirects toward Facebook’s server.
  • If everything is good and the user agrees to let our application get some details. We are redirected back to our WordPress site.
  • During the redirection, Facebook gives us a temporary “Access Token”.
  • We use this token to ask the Facebook API to get the user’s details: ID, Name, Email…
  • We handle the data in WordPress by either connecting the user if there was a previous connection or by creating a new account.

What is the goal?

We want to provide our users a very simple way to login and register to WordPress. Without email, username or password to enter in order to log in. Just a single button to click.
The easiest way will be to create a new shortcode which will display a Login/Register button and any error that should be displayed. So you can use it in any page / post / widget  or theme template using the do_shortcode function.
The shortcode will display nothing if the user is currently logged in. You might want to change that behavior.
We will use a plugin to wrap our code so it can work in any site. This plugin will be using the Facebook SDK and an object oriented coding style.
Feel free to change all the “alka” word  with your organization’s name.

Step 1: Building our plugin and importing the Facebook PHP SDK

First, we need to create a new plugin so our code is run by WordPress. Create a new directory “alka-facebook” (in wp-content/plugins/) that will hold all our files. Then, let’s get started! Create a new alka-facebook.php file:

<?php
/**
 * Plugin Name:       Alka Facebook
 * Description:       Login and Register your users using Facebook's API
 * Version:           1.0.0
 * Author:            Alkaweb
 * Author URI:        http://alka-web.com/alka-web-com
 * Text Domain:       alkaweb
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * GitHub Plugin URI: https://github.com/2Fwebd/alka-facebook
 */
class AlkaFacebook{
    /**
     * AlkaFacebook constructor.
     */
    public function __construct()
    {
    }
}
/*
 * Starts our plugins, easy!
 */
new AlkaFacebook();

You can now enable the plugin in Plugins > Alka Facebook > Activate. All our code will now be executed by WordPress, which is good.
Then, we can now import the Facebook PHP Sdk which will help us to make our calls to the Facebook API using PHP.
There are several ways to import it, the easiest one in WordPress is to download the SDK, rename the folder as facebook-sdk and move it to our plugin’s directory:

Now, we need to call the Facebook Sdk files required by the authentication actions that will be done within our plugin.
Just add the following to the top of the plugin’s file, right after the plugin header:

/*
 * Import the Facebook SDK and load all the classes
 */
include (plugin_dir_path( __FILE__ ) . 'facebook-sdk/autoload.php');
/*
 * Classes required to call the Facebook API
 * They will be used by our class
 */
use Facebook\Facebook;
use Facebook\Exceptions\FacebookSDKException;
use Facebook\Exceptions\FacebookResponseException;

Step 2: creating our Facebook Application

Secondly, in order to make API calls to the Facebook API, we obviously need to get some access. So Facebook knows who is making the calls and requesting the user details.
You can do that by going on the Facebook Apps page: https://developers.facebook.com/apps.

  • Click the “Add a new App” button
  • Set up the name and create your APP
  • Enable the Products > Facebook Login 
  • Add your Callback URL, which is http://yoursite.com/wp-admin/admin-ajax.php?action=alka_facebook you definitely need to change yoursite.com with your site’s URL.

  • Go to the Settings to get your App Id and App Secret 

We can now save them in our Class safely:

class AlkaFacebook{
    /**
     * Facebook APP ID
     *
     * @var string
     */
    private $app_id = 'xxxxxxxxxxxx';
    /**
     * Facebook APP Secret
     *
     * @var string
     */
    private $app_secret = 'yyyyyyyyyyyyy';
    /**
     * Callback URL used by the API
     *
     * @var string
     */
    private $callback_url = 'http://yoursite.com/wp-admin/admin-ajax.php?action=alka_facebook';

We are now ready to use Facebook API safely from our site.

Step 3: Creating our Shortcode

Thirdly, we will create a very simple shortcode to display our button, you can add options to this shortcode to go further we won’t do it in this tutorial though.
The shortcode is added using the “add_shortcode” WordPress function in our constructor and calls a method “renderShortcode“, which has a pretty good name according to how we will use it.

/**
 * AlkaFacebook constructor.
 */
public function __construct()
{
    // We register our shortcode
    add_shortcode( 'alka_facebook', array($this, 'renderShortcode') );
}
/**
 * Render the shortcode [alka_facebook/]
 *
 * It displays our Login / Register button
 */
public function renderShortcode() {
    // No need for the button is the user is already logged
    if(is_user_logged_in())
        return;
    // Different labels according to whether the user is allowed to register or not
    if (get_option( 'users_can_register' )) {
        $button_label = __('Login or Register with Facebook', 'alkaweb');
    } else {
        $button_label = __('Login with Facebook', 'alkaweb');
    }
    // Button markup
    $html = '<div id="alka-facebook-wrapper">';
    $html .= '<a href="#" id="alka-facebook-button">'.$button_label.'</a>';
    $html .= '</div>';
    // Write it down
    return $html;
}

You can now use [alka_facebook /] in your editor in any page and save. For testing purpose, you can now log out.

Step4: Connecting to the API

Next, we will now create a connection between our plugin and the Facebook API using our Facebook App’s details. In order to achieve this, we will create a new method to initialize the connection as it will be called several times, we return a Facebook instance:

/**
 * Init the API Connection
 *
 * @return Facebook
 */
private function initApi() {
    $facebook = new Facebook([
        'app_id' => $this->app_id,
        'app_secret' => $this->app_secret,
        'default_graph_version' => 'v2.2',
        'persistent_data_handler' => 'session'
    ]);
    return $facebook;
}

Thus, we can now use the SDK to get a login/register URL that will be used whenever the user clicks our button. Note that we use the PHP session to pass the data through all the methods and Facebook’s authentication steps:

/**
 * Login URL to Facebook API
 *
 * @return string
 */
private function getLoginUrl() {
    if(!session_id()) {
        session_start();
    }
    $fb = $this->initApi();
    $helper = $fb->getRedirectLoginHelper();
    // Optional permissions
    $permissions = ['email'];
    $url = $helper->getLoginUrl($this->callback_url, $permissions);
    return esc_url($url);
}

So, we can now use this URL in our button (renderShortcode) method:

$html .= '<a href="'.$this->getLoginUrl().'" class="btn" id="alka-facebook-button">'.$button_label.'</a>';

Our Facebook signing button now redirects us to Facebook, we are also redirect back to our callback URL. Yi hay!

Step 5: The callback

Lastly, the Callback is the code run by our plugin whenever an user is done with the Facebook dialog. He is redirected back to our site. For this matter, we created a new URL (already used earlier) http://yoursite.com/wp-admin/admin-ajax.php?action=alka_facebook which is basically a way to run our code with our own URL in WordPress. This is using the AJAX way, it would be better to use the REST API later though.

/**
 * AlkaFacebook constructor.
 */
public function __construct()
{
    // We register our shortcode
    add_shortcode( 'alka_facebook', array($this, 'renderShortcode') );
    // Callback URL
    add_action( 'wp_ajax_alka_facebook', array($this, 'apiCallback'));
    add_action( 'wp_ajax_nopriv_alka_facebook', array($this, 'apiCallback'));
}

And we need to create our callback’s method. This callback decides whether the user must be logged in or registered. This is where all the magic happens!
We will introduce a bunch of new stuff first here:

  • A new “alka_facebook_messagesession variable that will handle any error or message that must be displayed back to the user.
  • A new “alka_facebook_urlsession variable to redirect our user properly after the callback. It saves the page’s URL (where the shortcode is located)
  • A new class property: $access_token to use the access token from the Facebook API
  • A new class property: $redirect_url to use our alka_facebook_url within our class
  • A  new class property: $facebook_details to use the user data returned by the Facebook URL.

Moreover, we use class properties so we can split our code in several methods and never pass anything as an argument but rather as a class property. Which is cleaner.
In order that we now add our new properties:

/**
 * Access token from Facebook
 *
 * @var string
 */
private $access_token;
/**
 * Where we redirect our user after the process
 *
 * @var string
 */
private $redirect_url;
/**
 * User details from the API
 */
private $facebook_details;

We can also update our shortcode render method to pass the URL and display any message that would be returned by the callback through the $_SESSION:

/**
 * Render the shortcode [alka_facebook/]
 *
 * It displays our Login / Register button
 */
public function renderShortcode() {
    // Start the session
    if(!session_id()) {
        session_start();
    }
    // No need for the button is the user is already logged
    if(is_user_logged_in())
        return;
    // We save the URL for the redirection:
    if(!isset($_SESSION['alka_facebook_url']))
        $_SESSION['alka_facebook_url'] = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    // Different labels according to whether the user is allowed to register or not
    if (get_option( 'users_can_register' )) {
        $button_label = __('Login or Register with Facebook', 'alkaweb');
    } else {
        $button_label = __('Login with Facebook', 'alkaweb');
    }
    // HTML markup
    $html = '<div id="alka-facebook-wrapper">';
    // Messages
    if(isset($_SESSION['alka_facebook_message'])) {
        $message = $_SESSION['alka_facebook_message'];
        $html .= '<div id="alka-facebook-message" class="alert alert-danger">'.$message.'</div>';
        // We remove them from the session
        unset($_SESSION['alka_facebook_message']);
    }
    // Button
    $html .= '<a href="'.$this->getLoginUrl().'" class="btn" id="alka-facebook-button">'.$button_label.'</a>';
    $html .= '</div>';
    // Write it down
    return $html;
}

So what about we build our callback method now? The callback is split in 4 other methods:

  • getToken, to ask the Facebook API to get an authentication unique token. See the Facebook documentation here for all the details.
  • getUserDetails, once we have a token, we now ask the API to get the user’s details (name, email…). You can see all the information that you can fetch here.
  • loginUser, to login the User to WordPress.
  • createUser, to register a new user in WordPress.

Therefore, to decide if we login or register the user, we save for each user a new user meta: alka_facebook_id. Which is the Facebook user’s id. If it exists in our database, we login the user. If not, we make sure registration is allowed on the site before creating a new user.

/**
 * API call back running whenever we hit /wp-admin/admin-ajax.php?action=alka_facebook
 * This code handles the Login / Regsitration part
 */
public function apiCallback() {
    if(!session_id()) {
        session_start();
    }
    // Set the Redirect URL:
    $this->redirect_url = (isset($_SESSION['alka_facebook_url'])) ? $_SESSION['alka_facebook_url'] : home_url();
    // We start the connection
    $fb = $this->initApi();
    // We save the token in our instance
    $this->access_token = $this->getToken($fb);
    // We get the user details
    $this->facebook_details = $this->getUserDetails($fb);
    // We first try to login the user
    $this->loginUser();
    // Otherwise, we create a new account
    $this->createUser();
    // Redirect the user
    header("Location: ".$this->redirect_url, true);
    die();
}

Let’s create our 4 methods within our call back method:

/**
 * Get a TOKEN from the Facebook API
 * Or redirect back if there is an error
 *
 * @param $fb Facebook
 * @return string - The Token
 */
private function getToken($fb) {
    // Assign the Session variable for Facebook
    $_SESSION['FBRLH_state'] = $_GET['state'];
    // Load the Facebook SDK helper
    $helper = $fb->getRedirectLoginHelper();
    // Try to get an access token
    try {
        $accessToken = $helper->getAccessToken();
    }
    // When Graph returns an error
    catch(FacebookResponseException $e) {
        $error = __('Graph returned an error: ','alkaweb'). $e->getMessage();
        $message = array(
            'type' => 'error',
            'content' => $error
        );
    }
    // When validation fails or other local issues
    catch(FacebookSDKException $e) {
        $error = __('Facebook SDK returned an error: ','alkaweb'). $e->getMessage();
        $message = array(
            'type' => 'error',
            'content' => $error
        );
    }
    // If we don't got a token, it means we had an error
    if (!isset($accessToken)) {
        // Report our errors
        $_SESSION['alka_facebook_message'] = $message;
        // Redirect
        header("Location: ".$this->redirect_url, true);
        die();
    }
    return $accessToken->getValue();
}
/**
 * Get user details through the Facebook API
 *
 * @link https://developers.facebook.com/docs/facebook-login/permissions#reference-public_profile
 * @param $fb Facebook
 * @return \Facebook\GraphNodes\GraphUser
 */
private function getUserDetails($fb)
{
    try {
        $response = $fb->get('/me?fields=id,name,first_name,last_name,email,link', $this->access_token);
    } catch(FacebookResponseException $e) {
        $message = __('Graph returned an error: ','alkaweb'). $e->getMessage();
        $message = array(
            'type' => 'error',
            'content' => $error
        );
    } catch(FacebookSDKException $e) {
        $message = __('Facebook SDK returned an error: ','alkaweb'). $e->getMessage();
        $message = array(
            'type' => 'error',
            'content' => $error
        );
    }
    // If we caught an error
    if (isset($message)) {
        // Report our errors
        $_SESSION['alka_facebook_message'] = $message;
        // Redirect
        header("Location: ".$this->redirect_url, true);
        die();
    }
    return $response->getGraphUser();
}
/**
 * Login an user to WordPress
 *
 * @link https://codex.wordpress.org/Function_Reference/get_users
 * @return bool|void
 */
private function loginUser() {
    // We look for the `eo_facebook_id` to see if there is any match
    $wp_users = get_users(array(
        'meta_key'     => 'alka_facebook_id',
        'meta_value'   => $this->facebook_details['id'],
        'number'       => 1,
        'count_total'  => false,
        'fields'       => 'id',
    ));
    if(empty($wp_users[0])) {
        return false;
    }
    // Log the user ?
    wp_set_auth_cookie( $wp_users[0] );
}
/**
 * Create a new WordPress account using Facebook Details
 */
private function createUser() {
    $fb_user = $this->facebook_details;
    // Create an username
    $username = sanitize_user(str_replace(' ', '_', strtolower($this->facebook_details['name'])));
    // Creating our user
    $new_user = wp_create_user($username, wp_generate_password(), $fb_user['email']);
    if(is_wp_error($new_user)) {
        // Report our errors
        $_SESSION['alka_facebook_message'] = $new_user->get_error_message();
        // Redirect
        header("Location: ".$this->redirect_url, true);
        die();
    }
    // Setting the meta
    update_user_meta( $new_user, 'first_name', $fb_user['first_name'] );
    update_user_meta( $new_user, 'last_name', $fb_user['last_name'] );
    update_user_meta( $new_user, 'user_url', $fb_user['link'] );
    update_user_meta( $new_user, 'alka_facebook_id', $fb_user['id'] );
    // Log the user ?
    wp_set_auth_cookie( $new_user );
}

All good! We are ready to go.
Each method might require some comments, let me know if you have any question about them. I can update the article but the code is pretty commented though.
You can see the whole plugin from this Github repository.

Improvements

This plugin can be improved in several ways:

  • Create an option panel to get the APP ID and APP SECRET from the WordPress admin, which would be a bit more handy, right?
  • Styling our button using some cool CSS and a nice Facebook icon.
  • Displaying a welcome message when the user is logged in.
  • Saving the avatar from Facebook to WordPress.
  • Sending an email to the user with his password and username to be able to connect later without Facebook.

Liked this tutorial? Let us know, we could go through a part 2 where I would explain how to do all these improvements.
Update: You can find part 2 here!
 
Thanks for reading!


Comments 33

Comments are closed.