nodge/yii2-eauth Yii2 EAuth Extension. EAuth allows to authenticate users with accounts on other websites (Google, Facebook, Twitter, etc).

extensionoauthopenidauthenticationeauth

Yii2 EAuth extension

EAuth extension allows to authenticate users with accounts on other websites. Supported protocols: OpenID, OAuth 1.0 and OAuth 2.0.

EAuth is an extension to provide a unified (does not depend on the selected service) method to authenticate the user. The extension itself does not perform login, does not register the user and does not bind the user accounts from different providers.

Why own extension and not a third-party service?

The implementation of the authorization on your own server has several advantages:

  • Full control over the process: What will be written in the authorization window, what data we get, etc.
  • Ability to change the appearance of the widget.
  • When logging in via OAuth, it is possible to invoke methods on the API.
  • Fewer dependencies on third-party services - more reliable application.

The extension allows you to:

  • Ignore the nuances of authorization through the different types of services and use the class based adapters for each service.
  • Get a unique user ID that can be used to register the user in your application.
  • Extend the standard authorization classes to obtain additional data about the user.
  • Work with the API of social networks by extending the authorization classes.
  • Set up a list of supported services, customize the appearance of the widget, use the popup window without closing your application.

Extension includes:

  • The component that contains utility functions.
  • A widget that displays a list of services in the form of icons and allowing authorization in the popup window.
  • Base classes to create your own services.
  • Ready to authenticate via Google, Twitter, Facebook and other providers.

Included services:

  • OpenID:
    • Yahoo
    • Steam
  • OAuth1:
    • Twitter
    • LinkedIn
  • OAuth2:
    • Google
    • Facebook
    • Live
    • GitHub
    • LinkedIn
    • Instagram
    • Yandex (ru)
    • VKontake (ru)
    • Mail.ru (ru)
    • Odnoklassniki (ru)

Resources

Requirements

  • Yii 2.0 or above
  • curl php extension
  • LightOpenId
  • PHPoAuthLib

Installation

This library can be found on Packagist. The recommended way to install this is through composer.

Edit your composer.json and add:

{
        "require": {
                "nodge/yii2-eauth": "~2.0"
        }
}

And install dependencies:

$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar install

Usage

Demo project

The source code of the demo is available here.

Basic setup

Configuration

Add the following in your config:

<?php
...
    'components' => [
        'eauth' => [
            'class' => 'nodge\eauth\EAuth',
            'popup' => true, // Use the popup window instead of redirecting.
            'cache' => false, // Cache component name or false to disable cache. Defaults to 'cache' on production environments.
            'cacheExpire' => 0, // Cache lifetime. Defaults to 0 - means unlimited.
            'httpClient' => [
                // uncomment this to use streams in safe_mode
                //'useStreamsFallback' => true,
            ],
            'services' => [ // You can change the providers and their classes.
                'google' => [
                    // register your app here: https://code.google.com/apis/console/
                    'class' => 'nodge\eauth\services\GoogleOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                    'title' => 'Google',
                ],
                'twitter' => [
                    // register your app here: https://dev.twitter.com/apps/new
                    'class' => 'nodge\eauth\services\TwitterOAuth1Service',
                    'key' => '...',
                    'secret' => '...',
                ],
                'yandex' => [
                    // register your app here: https://oauth.yandex.ru/client/my
                    'class' => 'nodge\eauth\services\YandexOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                    'title' => 'Yandex',
                ],
                'facebook' => [
                    // register your app here: https://developers.facebook.com/apps/
                    'class' => 'nodge\eauth\services\FacebookOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'yahoo' => [
                    'class' => 'nodge\eauth\services\YahooOpenIDService',
                    //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
                ],
                'linkedin' => [
                    // register your app here: https://www.linkedin.com/secure/developer
                    'class' => 'nodge\eauth\services\LinkedinOAuth1Service',
                    'key' => '...',
                    'secret' => '...',
                    'title' => 'LinkedIn (OAuth1)',
                ],
                'linkedin_oauth2' => [
                    // register your app here: https://www.linkedin.com/secure/developer
                    'class' => 'nodge\eauth\services\LinkedinOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                    'title' => 'LinkedIn (OAuth2)',
                ],
                'github' => [
                    // register your app here: https://github.com/settings/applications
                    'class' => 'nodge\eauth\services\GitHubOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'live' => [
                    // register your app here: https://account.live.com/developers/applications/index
                    'class' => 'nodge\eauth\services\LiveOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'steam' => [
                    'class' => 'nodge\eauth\services\SteamOpenIDService',
                    //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
                    'apiKey' => '...', // Optional. You can get it here: https://steamcommunity.com/dev/apikey
                ],
                'instagram' => [
                    // register your app here: https://instagram.com/developer/register/
                    'class' => 'nodge\eauth\services\InstagramOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'vkontakte' => [
                    // register your app here: https://vk.com/editapp?act=create&site=1
                    'class' => 'nodge\eauth\services\VKontakteOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'mailru' => [
                    // register your app here: http://api.mail.ru/sites/my/add
                    'class' => 'nodge\eauth\services\MailruOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                ],
                'odnoklassniki' => [
                    // register your app here: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
                    // ... or here: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
                    'class' => 'nodge\eauth\services\OdnoklassnikiOAuth2Service',
                    'clientId' => '...',
                    'clientSecret' => '...',
                    'clientPublic' => '...',
                    'title' => 'Odnoklas.',
                    ],
            ],
        ],

        'i18n' => [
            'translations' => [
                'eauth' => [
                    'class' => 'yii\i18n\PhpMessageSource',
                    'basePath' => '@eauth/messages',
                ],
            ],
        ],

        // (optionally) you can configure pretty urls
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
                'login/<service:google|facebook|etc>' => 'site/login',
            ],
        ],

        // (optionally) you can configure logging
        'log' => [
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'logFile' => '@app/runtime/logs/eauth.log',
                    'categories' => ['nodge\eauth\*'],
                    'logVars' => [],
                ],
            ],
        ],
        ...
    ],
...

User model

You need to modify your User model to login with EAuth services. Example from demo project:

<?php
...
    /**
     * @var array EAuth attributes
     */
    public $profile;

    public static function findIdentity($id) {
        if (Yii::$app->getSession()->has('user-'.$id)) {
            return new self(Yii::$app->getSession()->get('user-'.$id));
        }
        else {
            return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
        }
    }

    /**
     * @param \nodge\eauth\ServiceBase $service
     * @return User
     * @throws ErrorException
     */
    public static function findByEAuth($service) {
        if (!$service->getIsAuthenticated()) {
            throw new ErrorException('EAuth user should be authenticated before creating identity.');
        }

        $id = $service->getServiceName().'-'.$service->getId();
        $attributes = [
            'id' => $id,
            'username' => $service->getAttribute('name'),
            'authKey' => md5($id),
            'profile' => $service->getAttributes(),
        ];
        $attributes['profile']['service'] = $service->getServiceName();
        Yii::$app->getSession()->set('user-'.$id, $attributes);
        return new self($attributes);
    }
...

Then you can access to EAuth attributes through:

<?php
    $identity = Yii::$app->getUser()->getIdentity();
    if (isset($identity->profile)) {
        VarDumper::dump($identity->profile, 10, true);
    }

Controller

Attach OpenID Controller behavior to disable CSRF validation for OpenID callbacks. Or you can disable CSRF validation by yourself.

<?php
...
    public function behaviors() {
                return [
                    'eauth' => [
                        // required to disable csrf validation on OpenID requests
                        'class' => \nodge\eauth\openid\ControllerBehavior::className(),
                        'only' => ['login'],
                    ],
                ];
            }
...

Add the following to your Login action:

<?php
...
    public function actionLogin() {
        $serviceName = Yii::$app->getRequest()->getQueryParam('service');
        if (isset($serviceName)) {
            /** @var $eauth \nodge\eauth\ServiceBase */
            $eauth = Yii::$app->get('eauth')->getIdentity($serviceName);
            $eauth->setRedirectUrl(Yii::$app->getUser()->getReturnUrl());
            $eauth->setCancelUrl(Yii::$app->getUrlManager()->createAbsoluteUrl('site/login'));

            try {
                if ($eauth->authenticate()) {
//                  var_dump($eauth->getIsAuthenticated(), $eauth->getAttributes()); exit;

                    $identity = User::findByEAuth($eauth);
                    Yii::$app->getUser()->login($identity);

                    // special redirect with closing popup window
                    $eauth->redirect();
                }
                else {
                    // close popup window and redirect to cancelUrl
                    $eauth->cancel();
                }
            }
            catch (\nodge\eauth\ErrorException $e) {
                // save error to show it later
                Yii::$app->getSession()->setFlash('error', 'EAuthException: '.$e->getMessage());

                // close popup window and redirect to cancelUrl
//              $eauth->cancel();
                $eauth->redirect($eauth->getCancelUrl());
            }
        }

        // default authorization code through login/password ..
    }
...

View

...
<?php
    if (Yii::$app->getSession()->hasFlash('error')) {
        echo '<div class="alert alert-danger">'.Yii::$app->getSession()->getFlash('error').'</div>';
    }
?>
...
<p class="lead">Do you already have an account on one of these sites? Click the logo to log in with it here:</p>
<?php echo \nodge\eauth\Widget::widget(['action' => 'site/login']); ?>
...

Extending

To receive all the necessary data to your application, you can override the base class of any provider. Base classes are stored in @eauth/src/services. Examples of extended classes can be found in @eauth/src/services/extended/.

After overriding the base class, you need to update your configuration file with a new class name.

Working with OAuth API

You can extend base classes with necessary methods and then write something like this:

<?php
    /** @var $eauth EAuthServiceBase */
    $eauth = Yii::$app->eauth->getIdentity('facebook');

    // to get protected resources user should be authenticated:
    if ($eauth->getIsAuthenticated()) {
        $eauth->callProtectedApiMethod();
        $eauth->callAnotherProtectedApiMethod();
    }

    // or you can get public resources at any time:
    $eauth->callPublicApiMethod();
    $eauth->callAnotherPublicApiMethod();

Example of an API call method:

<?php
    class FacebookOAuth2Service extends \nodge\eauth\services\FacebookOAuth2Service
    {
        public function fooApiMethod($bar) {
            $api_method = 'me'; // ex. for Facebook this results to https://graph.facebook.com/me

            // get protected resource
            $response = $this->makeSignedRequest($api_method, [
                'query' => [ 'foo' => 'bar' ], // GET arguments
                'data' => [ 'foo' => 'bar' ], // POST arguments
                'headers' => [ 'X-Foo' => 'bar' ], // Extra HTTP headers
            ]);

            // you can get public resources with the same API:
            //$response = $this->makeRequest($api_method, $options);

            // process $response
            $data = process($response);

            // return results
            return $data;
        }
    }

API calls are performed if the current user has a valid access token (saved during the authentication). You can save access_token to your database by using custom token storage in your config:

<?php
...
    'components' => [
        'eauth' => [
            'class' => 'nodge\eauth\EAuth',
            'tokenStorage' => [
                'class' => '@app\eauth\DatabaseTokenStorage',
            ],
        ],
        ...
    ],
...

Translation

To use translations, add the following in your config:

<?php
...
    'components' => [
        'i18n' => [
            'translations' => [
                'eauth' => [
                    'class' => 'yii\i18n\PhpMessageSource',
                    'basePath' => '@eauth/messages',
                ],
            ],
        ],
        ...
    ],
...

Available translations can be found in @eauth/src/messages.

License

The extension was released under the New BSD License, so you'll find the latest version on GitHub.

Changelog

Yii2 EAuth Change Log

2.5.0 (10.04.2017)

  • Fix bug with access token expire time in Facebook service (#102)
  • Use the latest Graph Api v2.8 for Facebook
  • Using version when making VK API call (#92)
  • New authorization and API url for Odnoklassniki service (#73)
  • Added Polish translation (#93)
  • Added Romanian translation (#94)

2.4.1 (13.01.2016)

  • Move response parsing from oauth to base service (#71)
  • Get user profile from Steam API (#70)

2.4.0 (03.01.2016)

  • Fixed error param names for Facebook (#63)
  • Use the latest Graph Api v2.5 for Facebook (#65)
  • Fixed makeRequest method (#68)
  • Added makeRequest method to OpenID services

2.3.0 (17.10.2015)

  • Added InstagramOAuth2Service (#61)
  • Fixed default token lifetime (#53)
  • Replace array() with [] (#54)
  • Remove deprecated Google OpenID service (#56)
  • Remove deprecated Yandex OpenID service

2.2.4 (27.07.2015)

  • Fixed typo in oauth2/Service.php (#34)
  • Added German translation
  • Added email attribute to LinkedinOAuth2Service.php

2.2.3 (15.07.2014)

  • Added ability to call public api methods (without access token) (#28)

2.2.2 (15.07.2014)

  • Fixed wrong redirect_uri when popup is used

2.2.1 (25.04.2014)

  • Fix missing query params in callback urls (#26)
  • Follow Yii2 code style

2.2.0 (19.04.2014)

  • Support for PHPoAuthLib v0.3 (#22)
  • Support for Yii2 beta
  • Internal state implementation replaced to PHPoAuthLib storage

2.1.5 (24.03.2014)

  • Fixed Yii2 refactor (#17)
  • PSR-4

2.1.4 (11.03.2014)

  • Fixed wrong callbackUrl in oauth\ServiceBase when UrlManager uses prettyUrl=false and showScript=false (#12)
  • Fixed Yii::t() calls according to Yii2 i18n Named Placeholders (#14)
  • Fixed Yii2 refactor #2630 (#15)

2.1.3 (30.01.2014)

  • Yii2 update (Request methods has been refactored).

2.1.2 (17.01.2014)

  • Fixed typo in oauth2\ServiceProxy

2.1.1 (07.01.2014)

  • Fixed scope validation for OAuth services.

2.1.0 (22.12.2013)

  • Reorganize project with new namespace.
  • Assets bundle has been moved.
  • Fixed typo in HttpClient (#8).
  • Added default User-Agent header to HttpClient.
  • Disabled CSRF validation for OpenID callbacks.
  • Optimized icons file.
  • Added SteamOpenIDService.
  • Improved redirect widget.

2.0.3 (26.10.2013)

  • Fixed redirect_uri when not using url rule (#2).
  • Fixed hasValidAccessToken() method for OAuth1 services (#3).
  • Fixed auto login cookie (#4).

2.0.2 (12.10.2013)

  • Fixed ServiceProxy constructor to match its interface (#1).
  • Added HttpClient with logging support and curl/streams fallback.
  • TokenStorage and HttpClient are configurable now.

2.0.1 (08.09.2013)

  • Fixed package versions in the composer.json.
  • Fixed directories names.
  • Added support for custom scope separator in OAuth2 services.
  • Added support for additional headers for OAuth2 requests.
  • Added method to get error from access token response.
  • Added GitHubOAuth2Service.
  • Added LinkedinOAuth2Service.
  • Added MailruOAuth2Service.
  • Added OdnoklassnikiOAuth2Service.
  • Added LiveOAuth2Service.
  • Added YahooOpenIDService.

Version 2.0.0 (03.09.2013)

  • Use curl for http requests by default.
  • getIsAuthenticated() function now looks up for existing access token for all OAuth services.
  • Added support for oauth_expires_in to OAuth1 services.
  • Added error handlers to OAuth1 services.
  • Added support for refresh tokens to OAuth2 ServiceProxy.
  • Added an option to disable OAuth2 state validation.

31.08.2013

  • Reorganize directories. Separate root directory by service type.
  • Fixed OAuthService::getCallbackUrl(). Now returns url without GET arguments.
  • Fixed typos in OAuth services.
  • Fixed OpenID loadAttributes functions.
  • OAuth2 display mode handling moved to the base class.
  • Added OAuthService::getAccessTokenData() method to access to valid access_token and related data.
  • Added token default lifetime setting.
  • Added "state" argument handling for OAuth2 services to improve security.
  • Updated OpenID library. Fixed error with stream requests.
  • Added VKontakteOAuth2Service.
  • Added GoogleOAuth2Service.
  • Added GoogleOAuth2Service.
  • Added YandexOAuth2Service.
  • Added session token storage using Yii session.

30.08.2013

  • Initial release for Yii2.

Statistics

Downloads
GitHub Stars
GitHub Forks

Releases

Comments



2.5.0 is the latest of 18 releases



New BSD License license
Stats
195 github stars & 126 github forks
15 downloads in the last day
244 downloads in the last 30 days
88067 total downloads