...
"

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

blog-img
blog-img
blog-img

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!

blog-img
blog-img

Comments 33

    • Hello,
      I’m new to PHP and currently using wordpress. I have been looking for a well structured clear tutorial for Facebook login until now. Thank you very much for the tut!
      Please keep part 2 coming! And if i may, will you touch on Javascript SDK and how to integrate both too?
      Many thanks!

            • By the way, have this code been tested?
              I did this in one of my file

              But it’s showing up empty in the browser? Any help?

                • Hello,
                  Yes of course, tested an used on our side 🙂
                  You can call it from a theme as well but you need to make sure the file is being loaded. Using require_once for example. I would also recommend you to use this in a Child Theme so you won’t lose that change in any theme update.
                  Thanks for your feedback.

                    • Hello,
                      It’s me again. I am getting error when using localhost. I added my localhost url to OAuth Redirect Url as stated in your guide.
                      http://localhost:3000/wp-admin/admin-ajax.php?action=alka_facebook
                      Any advice how to fix it?
                      Below is the error:
                      Can’t Load URL: The domain of this URL isn’t included in the app’s domains. To be able to load this URL, add all domains and sub-domains of your app to the App Domains field in your app settings.

    • Great tutorial! Its working perfectly for me… a few questions
      1) When i hit the log in button that is now on my site thanks to you, (assuming i’m already logged into Facebook) I get logged into my site without agreeing to or letting Facebook give me details to the site – is that normal? It happens automatically. I thought the user would have to “Agree” to letting Facebook give over the details?
      2) I would like to get the users ‘gender’ and ‘age range’ according to it being available through Public_Profile from Facebook.
      A) How would i do that
      B) How do i store this in WordPress? as Age and Gender is not an option>
      Again, awesome work with the above! Its great!
      B

    • I did everything fine but when i clicl on the login with facebook it sends me to a blank page with a number 0 on the top left side what can be the problem?

    • Having some trouble with step 4. I get the plugin working, with the button not doing anything, but when I try and follow the steps in number 4, I get a 500 server error.
      Any ideas why this might be happening?
      Thanks for the tutorial and looking forward to #2

    • Firstly, I seemed to come across issues at step 4. However I have just tried to install the plugin from the Github version and I am having difficulty activating it – the following error is occuring:
      Parse error: syntax error, unexpected ‘[‘, expecting ‘)’ in /home/jellymap/public_html/wp-content/plugins/alka-facebook-master/alka-facebook.php on line 144
      Any help would be much appreciated.
      Kind regards,
      Kyle

        • Hello Kyle,
          I just checked, that’s because we are using a “new” syntax for PHP. So you need version 5.4 of PHP installed or anything above. It’s about 8 years old so some update won’t hurt. That’ll increase your site’s performance by the way.
          I hope that helps

            • Thanks man, appreciate the support – really looking forward to part 2. When do you think you’ll release it?
              Cheers,
              Kyle

                • Hi Kyle,
                  Thanks for your interest. We have another tutorial coming and that’ll be the next on the list.
                  Have a nice day

    • It would be nice to integrate the profile image recovery, even in this case you need to know the function get_avatar which unfortunately I can not yet understand, congratulations on the tutorial. Really well done

    • Hello,
      I’m making users sign up through facebook on my woo commerce. Also, I’m able to update first_name, last_name, email, id in WordPress wp_update_user. But unable to fetch city in billing_city. How it could be done. Any help will be appreciated. Thanks. Code which I used is:
      $user = apply_filters( ‘fbl/user_data_login’, array(
      ‘fb_user_id’ => $fb_user[‘id’],
      ‘first_name’ => $fb_user[‘first_name’],
      ‘last_name’ => $fb_user[‘last_name’],
      ‘user_email’ => $fb_user[’email’],
      ‘billing_city’ => $fb_user[‘location’],
      ‘user_url’ => $fb_user[‘link’],
      ‘user_pass’ => wp_generate_password(),
      ));

        • Have you checked that $fb_user[‘location’] was set? Like you can do a print_r($fb_user) to make sure you have the right data. It can likely be because it’s missing from the request.
          You also need to make sure you ask the permission to have this information from:
          $response = $fb->get('/me?fields=id,name,first_name,last_name,email,link', $this->access_token);
          I hope that helps

    • Hi guys i would like to save the user details in my wp database how do i go about it. Again assuming i am having many facebook authentications how do put my callback url to go back to all this pages

        • Hello,
          Not sure what you mean, can you give me more details here please? Because whenever you create a new WordPress User (as we’re doing in the callback), we save the data in your database.

    • Thanks for the tutorial but I’m having an error with sessions..
      Error: Warning: session_start(): Cannot send session cookie – headers already sent by (output started
      // Start the session
      if(!session_id()) {
      session_start();
      }

    • I logged in successfully using Facebook Login but when it turns or redirect back to WordPress, there’s no indication that I was logged in on WordPress. No account was created.

        • Not sure I follow up, how can you be logged in if you do not have any account? If you already had an account before on your site, it’ll use that one and not duplicate it. See comments in the snippets.

    • I’m getting “: session_start(): Cannot start session when headers already sent in… ”
      what could be the reason? Thank you

        • Hello Pavel,
          What version are you using? That’s because the session_start() is run too late in the request so it must be initialized before any HTML is returned. You can use try to remove that line for now. See if it works, otherwise, please share us your file and we’ll let you know how to fix it 🙂
          Cheers

    • Thanks Alka
      Above code was showing error when i first integrate it with my plugin but when I updated sdk version it start working

        • Hi there,
          Glad you got it working!
          Let us know if you have any other question!
          Thanks.

    • I know this site offers quality dependent content and extra data, is there any other website which offers such information in quality?

        • Hi there,
          Thanks for the kind words.
          We have another blog at feedier.com/blog.
          Hope that answers your question.
          Cheers, Baptiste.

Comments are closed.