SnapShooter Backups Server, Database, Application and Laravel Backups - Get fully protected with SnapShooter

How to integrate Facebook login with CakePHP 3

Previously, we have learned how to integrate Facebook login using a plugin called Facebook Login. A lot of things have changed since then, include Facebook SDK and the maintenance of Facebook Login plugin. It has become obviously that we need a new way to integrate Facebook login with CakePHP application.

In this tutorial, we will show you how to integrate Facebook login with CakePHP 3 application using another CakePHP plugin.

Setup Users Table

A database table is required to store users' information such as email, password and so on. To keep it simple, we will create a very simple users table. It contains fields required to demonstrate Facebook login only.

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(250) NOT NULL,
  `password` varchar(250) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

If your users table has fields, as shown above, it should work for this tutorial. You can use your own users table in that case.

Setup CakePHP HybridAuth Plugin

CakePHP HybridAuth Plugin is a wrapper around HybridAuth library. HybridAuth library builds an abstraction layer on top of various social login. Which makes the task of integrating social login a breeze.

Install

Install CakePHP HybridAuth using Composer:

composer require --prefer-dist admad/cakephp-hybridauth

Load

Load the plugin using Bake command:

bin/cake plugin load ADmad/HybridAuth -b -r

This will basically append a line of code as shown below to your app's config/bootstrap.php. So you can do it manually if you wish to.

Plugin::load('ADmad/HybridAuth', ['bootstrap' => true, 'routes' => true]);

Configuration

Make a config file config/hybridauth.php:

use Cake\Core\Configure;
 
return [
    'HybridAuth' => [
        'providers' => [
            'Facebook' => [
                'enabled' => true,
                'keys' => [
                    'id' => 'facebook-id',
                    'secret' => 'facebook-secret-key'
                ],
                'scope' => 'email, public_profile'
            ]
        ]
    ],
];

Replace "facebook-id" and "facebook-secret-key" with your own. If you do not know where to find them, refer to this link.

In some case, you might wonder if you could place this configure values in other config files. The answer is yes. As long as you make sure HybridAuth config values exist. This plugin will happily pick them up.

Setup Controller

Next, we need a controller action to allow users to log in.

Create src/Controller/UsersController:

<?php
namespace App\Controller;
 
use Cake\Event\Event;
 
class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
 
        $this->Auth->allow();
 
    }
 
 
    public function login()
    {
        if ($this->request->is('post') || $this->request->query('provider')) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            }
            $this->Flash->error(__('Invalid username or password, try again'));
        }
    }
 
}

A caveat here. Do not place any special logic after the $this->Auth->identify() call. Because this method is not guaranteed to return, it redirects users away to the social site for authentication.

One more step for the controller work. Add CakePHP HybridAuth's authentication handlers to our application's auth component.

Add the handler in app/AppController.php

<php
class AppController extends Controller
{
 
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Auth', [
            'authenticate' => [
                'Form' => [
                    'fields' => ['username' => 'email']
                ],
                'ADmad/HybridAuth.HybridAuth' => [
                    // All keys shown below are defaults
                    'fields' => [
                        'provider' => 'provider',
                        'openid_identifier' => 'openid_identifier',
                        'email' => 'email'
                    ],
                    'profileModel' => 'ADmad/HybridAuth.SocialProfiles',
                    'profileModelFkField' => 'user_id',
                    'userModel' => 'Users',
                    'hauth_return_to' => [
                        'controller' => 'Users',
                        'action' => 'socail_login',
                        'prefix' => false,
                        'plugin' => false
                    ]
                ]
            ]
        ]);
    }
 
    // Your other controller code
}

Setup Event Listener

The event HybridAuth.newUser will be fired if CakePHP HybridAuth plugin could not find a user record from the users table. So an event listener is needed to create a brand new user record.

Add an event listener in app/AppController.php

<php
 
class AppController extends Controller
{
 
    public function beforeFilter(Event $event)
    {
        \Cake\Event\EventManager::instance()->on('HybridAuth.newUser', [$this, 'createUser']);
    }
 
    public function createUser(\Cake\Event\Event $event) {
        // Entity representing record in social_profiles table
        $profile = $event->data()['profile'];
 
        $user = $this->newEntity([
            'email' => $profile->email,
            'password' => time()
        ]);
        $user = $this->save($user);
 
        if (!$user) {
            throw new \RuntimeException('Unable to save new user');
        }
 
        return $user;
    }
 
 
    // Your other controller code
}

Note that we created a random password using current timestamp. This way, we can avoid having an empty password.

Setup View

There is not much to setup in a view, besides understanding how to create a login link.

In HybridAuth library, a social login URL follows current format:

http://your-website-url/login**?provider=facebook**

In CakePHP, we can generate the link above with HtmlHelper:

$this->Html->link(
 'Login with Facebook',
 ['controller' => 'Users', 'action' => 'login', '?' => ['provider' => 'Facebook']]
);

For now, your application should be integrated with Facebook login. Try it out and enjoy the benefits it brings for your users.

The End

Hopefully this simple tutorial helped you with your development. If you like our post, please follow us on Twitter and help spread the word. We need your support to continue. If you have questions or find our mistakes in above tutorial, do leave a comment below to let us know.