OAuth

Vegas OAuth integrates three OAuth services: Google, Facebook, LinkedIn. Consider the following example to see how to implement "Login with ..." feature into your project

Sample implementation

1. Module

In the beginning create OAuth module inside your app directory

mkdir app/Oauth
mkdir app/modules/Oauth/config
mkdir app/modules/Oauth/controllers/frontend -p
mkdir app/modules/Oauth/services
mkdir app/modules/Oauth/views/frontend/oauth -p
touch app/modules/Oauth/Module.php
touch app/modules/Oauth/config/routes.php

2. Service

Create a service.

touch app/modules/Oauth/services/OAuth.php

namespace Oauth\Services;

use Vegas\Security\OAuth\Exception\ServiceNotFoundException;
use Vegas\Security\OAuth\Identity;
use Vegas\Security\OAuth\Identity as OAuthIdentity;
use Vegas\Security\OAuth\ServiceAbstract;

/**
 * Class Oauth
 * @package Oauth\Services
 */
class Oauth implements \Phalcon\DI\InjectionAwareInterface
{
    use \Vegas\DI\InjectionAwareTrait;

    /**
     * @var array
     */
    protected $config = array();

    /**
     * List of initializes services
     *
     * @var array
     */
    protected $oAuthServices = array();

    /**
     * @var \Vegas\Security\OAuth
     */
    protected $oAuth = null;

    /**
     * Initializes service from provided configuration
     *
     * @param null|array $config
     * @return $this
     */
    public function initialize($config = null)
    {
        if (null == $config) {
            $this->config = $this->getDI()->get('config')->oauth->toArray();
        } else {
            $this->config = $config;
        }
        $this->setupServices();

        return $this;
    }

    /**
     * Setups oAuth services from configuration
     */
    protected function setupServices()
    {
        $this->oAuth = new \Vegas\Security\OAuth($this->di);
        foreach ($this->config as $serviceName => $serviceConfig) {
            $service = $this->oAuth->obtainServiceInstance($serviceName);
            $service->setupCredentials(array(
                'key'   =>  $serviceConfig['key'],
                'secret'    =>  $serviceConfig['secret'],
                'redirect_uri'  =>  $serviceConfig['redirect_uri']
            ));
            if (isset($serviceConfig['scopes'])) {
                $service->setScopes($serviceConfig['scopes']);
            }
            $service->init();
            $this->oAuthServices[$serviceName] = $service;
        }
    }

    /**
     * Returns the instance of indicated service
     *
     * @param $serviceName
     * @return ServiceAbstract
     * @throws \Vegas\Security\OAuth\Exception\ServiceNotFoundException
     */
    public function getService($serviceName)
    {
        if (!isset($this->oAuthServices[$serviceName])) {
            throw new ServiceNotFoundException($serviceName);
        }

        return $this->oAuthServices[$serviceName];
    }

    /**
     * Returns the prepared authorization uri to indicated oAuth Service
     *
     * @param $serviceName
     * @return mixed
     */
    public function getAuthorizationUri($serviceName)
    {
        $service = $this->getService($serviceName);
        return $service->getAuthorizationUri();
    }

    /**
     * Authorizes
     *
     * @param $serviceName
     * @return \OAuth\Common\Http\Uri\UriInterface|string
     */
    public function authorize($serviceName)
    {
        $service = $this->getService($serviceName);
        return $service->authorize();
    }

    /**
     * Remove session for indicated service
     *
     * @param null $serviceName
     */
    public function logout($serviceName = null)
    {
        if (null == $serviceName) {
            foreach ($this->oAuthServices as $serviceName => $service) {
                $service->destroySession();
            }
        } else {
            $service = $this->getService($serviceName);
            $service->destroySession();
        }
    }

    /**
     * Returns identity with accessToken for indicated service
     *
     * @param $serviceName
     * @return mixed
     */
    public function getIdentity($serviceName)
    {
        $service = $this->getService($serviceName);
        $identity = $service->getIdentity();
        $identity->accessToken = $service->getAccessToken();

        return $identity;
    }
}

Note. Check the following code to see how to use above service

$oauth = $this->serviceManager->getService('oauth:oauth');
$oauth->initialize();

Remember to call initialize method first.

3. Controller

The next step is create controller that handles authorization process

touch app/modules/Oauth/controllers/frontend/OAuthController.php

namespace Oauth\Controllers\Frontend;
use Vegas\Security\OAuth\Exception\FailedAuthorizationException;

/**
 * Class OAuthController
 * @package Oauth\Controllers\Frontend
 */
class OauthController extends \Vegas\Mvc\Controller\ControllerAbstract
{
    /**
     *
     */
    public function indexAction()
    {
        //oauth
        $oAuth = $this->serviceManager->getService('oauth:oauth');
        $oAuth->initialize();

        $this->view->linkedinUri = $oAuth->getAuthorizationUri('linkedin');
        $this->view->facebookUri = $oAuth->getAuthorizationUri('facebook');
        $this->view->googleUri = $oAuth->getAuthorizationUri('google');
    }

    /**
     * @return \Phalcon\Http\ResponseInterface
     */
    public function authorizeAction()
    {
        $this->view->disable();

        $serviceName = $this->dispatcher->getParam('service');
        $oauth = $this->serviceManager->getService('oauth:oauth');
        $oauth->initialize();

        try {
            //authorize given service
            $oauth->authorize($serviceName);

            /**
             * @var \Vegas\Security\OAuth\Identity $identity
             */
            $identity = $oauth->getIdentity($serviceName);
            //now you can create session for oauth identity
            //....

            return $this->response->redirect(array('for' => 'root'))->send();
        } catch(FailedAuthorizationException $ex) {
            $this->flashSession->message('error', $ex->getMessage());
            return $this->response->redirect(array('for' => 'login'))->send();
        }
    }

    /**
     * @return \Phalcon\Http\ResponseInterface
     */
    public function logoutAction()
    {
        $this->view->disable();

        $oauth = $this->serviceManager->getService('oauth:oauth');
        $oauth->initialize();

        //logout all services
        $oauth->logout();

        return $this->response->redirect(array('for' => 'root'))->send();
    }
}

4. Routes

Prepare routing rules to OAuth controller

touch app/modules/Oauth/config/routes.php

return array(
    'oauth' => array(
        'route' => '/oauth',
        'paths' => array(
            'module'    =>  'Oauth',
            'controller' => 'Frontend\Oauth',
            'action' => 'index',

            'auth'  =>  false
        )
    ),
    'logout' => array(
        'route' => '/logout',
        'paths' => array(
            'module'    =>  'Oauth',
            'controller' => 'Frontend\Oauth',
            'action' => 'logout',

            'auth'  =>  false
        )
    ),
    'authorize' => array(
        'route' => '/oauth/{service}',
        'paths' => array(
            'module'    =>  'Oauth',
            'controller' => 'Frontend\Oauth',
            'action' => 'authorize',

            'auth'  =>  false
        )
    )
);


5. View

Create view file to display authorization links

touch app/modules/Oauth/views/frontend/oauth/index.volt

<a href="{{ linkedinUri }}" class="btn btn-block btn-social btn-linkedin">
    <i class="fa fa-linkedin"></i>
    Sign in with Linkedin
</a>
<a href="{{ googleUri }}" class="btn btn-block btn-social btn-google-plus">
    <i class="fa fa-google-plus"></i>
    Sign in with Google
</a>
<a href="{{ facebookUri }}" class="btn btn-block btn-social btn-facebook">
    <i class="fa fa-facebook"></i>
    Sign in with Facebook
</a>


6. Configuration

Once we prepared codebase, we have to setup configuration for OAuth services

//app/config/config.php
'oauth' =>  array(
    'linkedin'  =>  array(
        'key'   =>  '',
        'secret'    =>  '',
        'redirect_uri' => '/oauth/linkedin',
        'scopes' => array(
            \Vegas\Security\OAuth\Service\Linkedin::SCOPE_FULL_PROFILE,
            \Vegas\Security\OAuth\Service\Linkedin::SCOPE_EMAIL_ADDRESS
        )
    ),

    'facebook'  =>  array(
        'key'   =>  '',
        'secret'    =>  '',
        'redirect_uri' => '/oauth/facebook',
        'scopes' => array(
            \Vegas\Security\OAuth\Service\Facebook::SCOPE_EMAIL,
            \Vegas\Security\OAuth\Service\Facebook::SCOPE_USER_ABOUT
        )
    ),

    'google'  =>  array(
        'key'    =>  '',
        'secret'   =>  '',
        'redirect_uri' => '/oauth/google',
        'scopes' => array(
            \Vegas\Security\OAuth\Service\Google::SCOPE_EMAIL,
            \Vegas\Security\OAuth\Service\Google::SCOPE_PROFILE
        )
    )
)
//...