├── .gitignore
├── src
├── assets
│ ├── images
│ │ ├── auth.png
│ │ └── auth-src.png
│ ├── WidgetAssetBundle.php
│ ├── js
│ │ └── eauth.js
│ └── css
│ │ └── eauth.css
├── ErrorException.php
├── Bootstrap.php
├── messages
│ ├── blank
│ │ └── eauth.php
│ ├── en
│ │ └── eauth.php
│ ├── de
│ │ └── eauth.php
│ ├── ro
│ │ └── eauth.php
│ ├── pl
│ │ └── eauth.php
│ ├── uk
│ │ └── eauth.php
│ └── ru
│ │ └── eauth.php
├── services
│ ├── extended
│ │ ├── GitHubOAuth2Service.php
│ │ ├── MailruOAuth2Service.php
│ │ ├── TwitterOAuth1Service.php
│ │ ├── OdnoklassnikiOAuth2Service.php
│ │ ├── VKontakteOAuth2Service.php
│ │ └── FacebookOAuth2Service.php
│ ├── YahooOpenIDService.php
│ ├── YandexOAuth2Service.php
│ ├── SteamOpenIDService.php
│ ├── TwitterOAuth1Service.php
│ ├── LinkedinOAuth1Service.php
│ ├── LinkedinOAuth2Service.php
│ ├── InstagramOAuth2Service.php
│ ├── MailruOAuth2Service.php
│ ├── LiveOAuth2Service.php
│ ├── GitHubOAuth2Service.php
│ ├── FacebookOAuth2Service.php
│ ├── OdnoklassnikiOAuth2Service.php
│ ├── VKontakteOAuth2Service.php
│ └── GoogleOAuth2Service.php
├── openid
│ ├── ControllerBehavior.php
│ └── Service.php
├── views
│ ├── widget.php
│ └── redirect.php
├── RedirectWidget.php
├── Widget.php
├── IAuthService.php
├── oauth1
│ ├── Service.php
│ └── ServiceProxy.php
├── oauth
│ ├── SessionTokenStorage.php
│ ├── ServiceBase.php
│ └── HttpClient.php
├── oauth2
│ ├── ServiceProxy.php
│ └── Service.php
├── EAuth.php
└── ServiceBase.php
├── composer.json
├── LICENSE
├── CHANGELOG.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | composer.lock
3 | composer.phar
--------------------------------------------------------------------------------
/src/assets/images/auth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nodge/yii2-eauth/HEAD/src/assets/images/auth.png
--------------------------------------------------------------------------------
/src/assets/images/auth-src.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nodge/yii2-eauth/HEAD/src/assets/images/auth-src.png
--------------------------------------------------------------------------------
/src/ErrorException.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | class ErrorException extends \yii\base\ErrorException
13 | {
14 |
15 | }
--------------------------------------------------------------------------------
/src/Bootstrap.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | use Yii;
13 | use yii\base\Application;
14 | use yii\base\BootstrapInterface;
15 |
16 | /**
17 | * This is the bootstrap class for the yii2-eauth extension.
18 | */
19 | class Bootstrap implements BootstrapInterface
20 | {
21 | /**
22 | * @inheritdoc
23 | */
24 | public function bootstrap($app)
25 | {
26 | Yii::setAlias('@eauth', __DIR__);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/assets/WidgetAssetBundle.php:
--------------------------------------------------------------------------------
1 |
14 | * @since 2.0
15 | */
16 | class WidgetAssetBundle extends AssetBundle
17 | {
18 | public $sourcePath = '@eauth/assets';
19 | public $css = [
20 | 'css/eauth.css',
21 | ];
22 | public $js = [
23 | 'js/eauth.js',
24 | ];
25 | public $depends = [
26 | 'yii\web\JqueryAsset',
27 | ];
28 | }
29 |
--------------------------------------------------------------------------------
/src/messages/blank/eauth.php:
--------------------------------------------------------------------------------
1 | '{service}',
5 | 'Invalid response http code: {code}.' => '{code}',
6 | 'Invalid response format.' => '',
7 | 'Unable to complete the authentication because the required data was not received.' => '{provider}',
8 | 'Unable to complete the request because the user was not authenticated.' => '',
9 |
10 | 'Redirecting back to the application...' => '',
11 | 'Click here to return to the application.' => '',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Yandex',
16 | 'VK.com' => 'VK.com',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Moikrug.ru',
20 | 'Odnoklassniki' => 'Odnoklassniki',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodge/yii2-eauth",
3 | "description": "Yii2 EAuth Extension. EAuth allows to authenticate users with accounts on other websites (Google, Facebook, Twitter, etc).",
4 | "keywords": ["yii2", "extension", "eauth", "openid", "oauth", "authentication"],
5 | "homepage": "https://github.com/Nodge/yii2-eauth",
6 | "type": "yii2-extension",
7 | "license": "New BSD License",
8 | "authors": [
9 | {
10 | "name": "Maxim Zemskov",
11 | "email": "nodge@yandex.ru",
12 | "homepage": "http://nodge.ru/"
13 | }
14 | ],
15 | "support": {
16 | "source": "https://github.com/nodge/yii2-eauth"
17 | },
18 | "autoload": {
19 | "psr-4": {
20 | "nodge\\eauth\\": "src/"
21 | }
22 | },
23 | "require": {
24 | "php": ">=5.4.0",
25 | "lib-curl": "*",
26 | "yiisoft/yii2": "*",
27 | "lusitanian/oauth": "~0.3.0",
28 | "nodge/lightopenid": "~1.1.0"
29 | },
30 | "extra": {
31 | "bootstrap": "nodge\\eauth\\Bootstrap"
32 | }
33 | }
--------------------------------------------------------------------------------
/src/services/extended/GitHubOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class GitHubOAuth2Service extends \nodge\eauth\services\GitHubOAuth2Service
13 | {
14 |
15 | protected function fetchAttributes()
16 | {
17 | $info = $this->makeSignedRequest('user');
18 |
19 | $this->attributes['id'] = $info['id'];
20 | $this->attributes['name'] = $info['login'];
21 | $this->attributes['url'] = $info['html_url'];
22 |
23 | $this->attributes['following'] = $info['following'];
24 | $this->attributes['followers'] = $info['followers'];
25 | $this->attributes['public_repos'] = $info['public_repos'];
26 | $this->attributes['public_gists'] = $info['public_gists'];
27 | $this->attributes['avatar_url'] = $info['avatar_url'];
28 |
29 | return true;
30 | }
31 | }
--------------------------------------------------------------------------------
/src/messages/en/eauth.php:
--------------------------------------------------------------------------------
1 | 'Undefined service name: {service}.',
5 | 'Invalid response http code: {code}.' => 'Invalid response http code: {code}.',
6 | 'Invalid response format.' => 'Invalid response format.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Unable to complete the authentication because the required data was not received.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Unable to complete the request because the user was not authenticated.',
9 |
10 | 'Redirecting back to the application...' => 'Redirecting back to the application...',
11 | 'Click here to return to the application.' => 'Click here to return to the application.',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Yandex',
16 | 'VK.com' => 'VK.com',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Moikrug.ru',
20 | 'Odnoklassniki' => 'Odnoklassniki',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
--------------------------------------------------------------------------------
/src/messages/de/eauth.php:
--------------------------------------------------------------------------------
1 | 'Undefinierter Servicename: {service}',
5 | 'Invalid response http code: {code}.' => 'Ungültiger HTTP Code: {code}',
6 | 'Invalid response format.' => 'Ungültiges Antwortformat.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Die Authentifizierung konnte nicht durchgeführt werden, da keine Daten empfangen wurden.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Die Anfrage konnte nicht durchgeführt werden, da der Nutzer nicht authentifiziert war.',
9 |
10 | 'Redirecting back to the application...' => 'Weiterleitung zur Applikation...',
11 | 'Click here to return to the application.' => 'Klicke hier um zur Applikation zurückzukehren',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Yandex',
16 | 'VK.com' => 'VK.com',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Moikrug.ru',
20 | 'Odnoklassniki' => 'Odnoklassniki',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
--------------------------------------------------------------------------------
/src/messages/ro/eauth.php:
--------------------------------------------------------------------------------
1 | 'Serviciu nedefinit: {service}.',
5 | 'Invalid response http code: {code}.' => 'Codul http al răspunsului este invalid: {code}.',
6 | 'Invalid response format.' => 'Formatul răspunsului este invalid.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Nu s-a putut finaliza autentificarea pentru că datele necesare nu au fost primite.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Cererea nu a fost finalizată pentru că utilizatorul nu este autentificat.',
9 |
10 | 'Redirecting back to the application...' => 'Te redirecționăm înapoi la aplicație...',
11 | 'Click here to return to the application.' => 'Apasă aici pentru a te întoarce la aplicație.',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Yandex',
16 | 'VK.com' => 'VK.com',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Moikrug.ru',
20 | 'Odnoklassniki' => 'Odnoklassniki',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
24 |
--------------------------------------------------------------------------------
/src/openid/ControllerBehavior.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\openid;
11 |
12 | use Yii;
13 | use yii\base\Action;
14 | use yii\base\ActionFilter;
15 |
16 | /**
17 | * @package application.extensions.eauth
18 | */
19 | class ControllerBehavior extends ActionFilter
20 | {
21 | /**
22 | * This method is invoked right before an action is to be executed (after all possible filters.)
23 | * You may override this method to do last-minute preparation for the action.
24 | *
25 | * @param Action $action the action to be executed.
26 | * @return boolean whether the action should continue to be executed.
27 | */
28 | public function beforeAction($action)
29 | {
30 | $request = Yii::$app->getRequest();
31 |
32 | if (in_array($request->getBodyParam('openid_mode', ''), ['id_res', 'cancel'])) {
33 | $request->enableCsrfValidation = false;
34 | }
35 |
36 | return parent::beforeAction($action);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/views/widget.php:
--------------------------------------------------------------------------------
1 | $assetBundle])->register($this);
14 |
15 | // Open the authorization dilalog in popup window.
16 | if ($popup) {
17 | $options = [];
18 | foreach ($services as $name => $service) {
19 | $options[$service->id] = $service->jsArguments;
20 | }
21 | $this->registerJs('$("#' . $id . '").eauth(' . json_encode($options) . ');');
22 | }
23 |
24 | ?>
25 |
26 |
27 | $service) {
29 | echo '- ';
30 | echo Html::a($service->title, [$action, 'service' => $name], [
31 | 'class' => 'eauth-service-link',
32 | 'data-eauth-service' => $service->id,
33 | ]);
34 | echo '
';
35 | }
36 | ?>
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/services/extended/MailruOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class MailruOAuth2Service extends \nodge\eauth\services\MailruOAuth2Service
13 | {
14 |
15 | protected function fetchAttributes()
16 | {
17 | $tokenData = $this->getAccessTokenData();
18 |
19 | $info = $this->makeSignedRequest('/', [
20 | 'query' => [
21 | 'uids' => $tokenData['params']['x_mailru_vid'],
22 | 'method' => 'users.getInfo',
23 | 'app_id' => $this->clientId,
24 | ],
25 | ]);
26 |
27 | $info = $info[0];
28 |
29 | $this->attributes['id'] = $info['uid'];
30 | $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
31 | $this->attributes['first_name'] = $info['first_name'];
32 | $this->attributes['last_name'] = $info['last_name'];
33 | $this->attributes['url'] = $info['link'];
34 | $this->attributes['photo'] = $info['pic'];
35 |
36 | return true;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/messages/pl/eauth.php:
--------------------------------------------------------------------------------
1 | 'Nieznana nazwa usługi: {service}.',
5 | 'Invalid response http code: {code}.' => 'Nieprawidłowy kod HTTP odpowiedzi: {code}.',
6 | 'Invalid response format.' => 'Nieprawidłowy format odpowiedzi.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Nie można dokonać uwierzytelniania, ponieważ nie otrzymano wymaganych danych.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Nie można przetworzyć żądania, ponieważ użytkownik nie został uwierzytelniony.',
9 |
10 | 'Redirecting back to the application...' => 'Przekierowuję z powrotem do aplikacji...',
11 | 'Click here to return to the application.' => 'Kliknij tutaj, aby powrócić do aplikacji.',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Yandex',
16 | 'VK.com' => 'VK.com',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Moikrug.ru',
20 | 'Odnoklassniki' => 'Odnoklassniki',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
24 |
--------------------------------------------------------------------------------
/src/messages/uk/eauth.php:
--------------------------------------------------------------------------------
1 | 'Авторизація за допомогою {service} не підтримується.',
5 | 'Invalid response http code: {code}.' => 'Невірна відповідь від сервера авторизації: {code}.',
6 | 'Invalid response format.' => 'Сервер авторизації повернув данні в невірному форматі.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Неможливо завершити авторизацію користувача, так як {provider} не передає необхідну інформацію.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Неможливо виконати захищений запит, так як користувач не був авторизований.',
9 |
10 | 'Redirecting back to the application...' => 'Redirecting back to the application...',
11 | 'Click here to return to the application.' => 'Click here to return to the application.',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Яндекс',
16 | 'VK.com' => 'ВКонтакте',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Мой круг',
20 | 'Odnoklassniki' => 'Одноклассники',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
24 |
--------------------------------------------------------------------------------
/src/views/redirect.php:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
41 |
42 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/messages/ru/eauth.php:
--------------------------------------------------------------------------------
1 | 'Авторизация с помощью {service} не поддерживается.',
5 | 'Invalid response http code: {code}.' => 'Неверный ответ от сервера авторизации: {code}.',
6 | 'Invalid response format.' => 'Сервер авторизации вернул данные в неправильном формате.',
7 | 'Unable to complete the authentication because the required data was not received.' => 'Невозможно завершить авторизацию пользователя, потому что {provider} не передает необходимую информацию.',
8 | 'Unable to complete the request because the user was not authenticated.' => 'Невозможно выполнить защищенный запрос, потому что пользователь не был авторизован.',
9 |
10 | 'Redirecting back to the application...' => 'Перенаправление обратно в приложение...',
11 | 'Click here to return to the application.' => 'Нажмите сюда чтобы вернуться обратно в приложение.',
12 |
13 | 'Google' => 'Google',
14 | 'Twitter' => 'Twitter',
15 | 'Yandex' => 'Яндекс',
16 | 'VK.com' => 'ВКонтакте',
17 | 'Facebook' => 'Facebook',
18 | 'Mail.ru' => 'Mail.ru',
19 | 'Moikrug.ru' => 'Мой круг',
20 | 'Odnoklassniki' => 'Одноклассники',
21 | 'LinkedIn' => 'LinkedIn',
22 | 'GitHub' => 'GitHub',
23 | ];
--------------------------------------------------------------------------------
/src/RedirectWidget.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | use \Yii;
13 | use yii\helpers\ArrayHelper;
14 |
15 | /**
16 | * The EAuthRedirectWidget widget displays the redirect page after returning from provider.
17 | *
18 | * @package application.extensions.eauth
19 | */
20 | class RedirectWidget extends Widget
21 | {
22 |
23 | /**
24 | * @var mixed the widget mode. Default to "login".
25 | */
26 | public $url = null;
27 |
28 | /**
29 | * @var boolean whether to use redirect inside the popup window.
30 | */
31 | public $redirect = true;
32 |
33 | /**
34 | * @var string
35 | */
36 | public $view = 'redirect';
37 |
38 | /**
39 | * @var array
40 | */
41 | public $params = [];
42 |
43 | /**
44 | * Executes the widget.
45 | */
46 | public function run()
47 | {
48 | echo $this->render($this->view,
49 | ArrayHelper::merge([
50 | 'id' => $this->getId(),
51 | 'url' => $this->url,
52 | 'redirect' => $this->redirect,
53 | ], $this->params)
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Maxim Zemskov
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/src/services/YahooOpenIDService.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services;
11 |
12 | use nodge\eauth\openid\Service;
13 |
14 | /**
15 | * Yahoo provider class.
16 | *
17 | * @package application.extensions.eauth.services
18 | */
19 | class YahooOpenIDService extends Service
20 | {
21 |
22 | protected $name = 'yahoo';
23 | protected $title = 'Yahoo';
24 | protected $type = 'OpenID';
25 | protected $jsArguments = ['popup' => ['width' => 880, 'height' => 520]];
26 |
27 | protected $url = 'https://me.yahoo.com';
28 | protected $requiredAttributes = [
29 | 'name' => ['fullname', 'namePerson'],
30 | // 'login' => ['nickname', 'namePerson/friendly'],
31 | // 'email' => ['email', 'contact/email'],
32 | ];
33 | protected $optionalAttributes = [
34 | // 'language' => ['language', 'pref/language'],
35 | // 'gender' => ['gender', 'person/gender'],
36 | // 'timezone' => ['timezone', 'pref/timezone'],
37 | // 'image' => ['image', 'media/image/default'],
38 | ];
39 |
40 | /*protected function fetchAttributes() {
41 | $this->attributes['fullname'] = $this->attributes['name'].' '.$this->attributes['lastname'];
42 | return true;
43 | }*/
44 | }
--------------------------------------------------------------------------------
/src/assets/js/eauth.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Yii EAuth extension.
3 | * @author Maxim Zemskov
4 | * @link http://github.com/Nodge/yii2-eauth/
5 | * @license http://www.opensource.org/licenses/bsd-license.php
6 | */
7 | (function ($) {
8 | var popup,
9 | defaults = {
10 | popup: {
11 | width: 450,
12 | height: 380
13 | }
14 | };
15 |
16 | function openPopup(options) {
17 | if (popup != null)
18 | popup.close();
19 |
20 | var redirect_uri,
21 | url = redirect_uri = options.url;
22 |
23 | url += url.indexOf('?') >= 0 ? '&' : '?';
24 | if (url.indexOf('redirect_uri=') === -1)
25 | url += 'redirect_uri=' + encodeURIComponent(redirect_uri) + '&';
26 | url += 'js=';
27 |
28 | var centerWidth = (window.screen.width - options.popup.width) / 2,
29 | centerHeight = (window.screen.height - options.popup.height) / 2;
30 |
31 | popup = window.open(url, "yii_eauth_popup", "width=" + options.popup.width + ",height=" + options.popup.height + ",left=" + centerWidth + ",top=" + centerHeight + ",resizable=yes,scrollbars=no,toolbar=no,menubar=no,location=no,directories=no,status=yes");
32 | popup.focus();
33 | }
34 |
35 | $.fn.eauth = function (services) {
36 | $(this).on('click', '[data-eauth-service]', function (e) {
37 | e.preventDefault();
38 |
39 | var service = $(this).data('eauthService'),
40 | options = $.extend({
41 | url: this.href
42 | }, defaults, services[service]);
43 |
44 | openPopup(options);
45 | });
46 | };
47 | })(jQuery);
48 |
--------------------------------------------------------------------------------
/src/services/extended/TwitterOAuth1Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class TwitterOAuth1Service extends \nodge\eauth\services\TwitterOAuth1Service
13 | {
14 |
15 | protected function fetchAttributes()
16 | {
17 | $info = $this->makeSignedRequest('account/verify_credentials.json');
18 |
19 | $this->attributes['id'] = $info['id'];
20 | $this->attributes['name'] = $info['name'];
21 | $this->attributes['url'] = 'http://twitter.com/account/redirect_by_id?id=' . $info['id_str'];
22 |
23 | $this->attributes['username'] = $info['screen_name'];
24 | $this->attributes['language'] = $info['lang'];
25 | $this->attributes['timezone'] = timezone_name_from_abbr('', $info['utc_offset'], date('I'));
26 | $this->attributes['photo'] = $info['profile_image_url'];
27 |
28 | return true;
29 | }
30 |
31 | /**
32 | * Returns the error array.
33 | *
34 | * @param array $response
35 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
36 | */
37 | protected function fetchResponseError($response)
38 | {
39 | if (isset($response['errors'])) {
40 | $first = reset($response['errors']);
41 | return [
42 | 'code' => $first['code'],
43 | 'message' => $first['message'],
44 | ];
45 | }
46 | return null;
47 | }
48 | }
--------------------------------------------------------------------------------
/src/services/extended/OdnoklassnikiOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class OdnoklassnikiOAuth2Service extends \nodge\eauth\services\OdnoklassnikiOAuth2Service
13 | {
14 |
15 | protected $scopes = [self::SCOPE_VALUABLE_ACCESS];
16 |
17 | protected function fetchAttributes()
18 | {
19 | parent::fetchAttributes();
20 |
21 | $info = $this->makeSignedRequest('', [
22 | 'query' => [
23 | 'method' => 'users.getInfo',
24 | 'uids' => $this->attributes['id'],
25 | 'fields' => 'url_profile',
26 | 'format' => 'JSON',
27 | 'application_key' => $this->clientPublic,
28 | 'client_id' => $this->clientId,
29 | ],
30 | ]);
31 |
32 | preg_match('/\d+\/{0,1}$/', $info[0]->url_profile, $matches);
33 | $this->attributes['id'] = (int)$matches[0];
34 | $this->attributes['url'] = $info[0]->url_profile;
35 |
36 | return true;
37 | }
38 |
39 |
40 | /**
41 | * @param string $link
42 | * @param string $message
43 | * @return array
44 | */
45 | public function wallPost($link, $message)
46 | {
47 | return $this->makeSignedRequest('', [
48 | 'query' => [
49 | 'application_key' => $this->clientPublic,
50 | 'method' => 'share.addLink',
51 | 'format' => 'JSON',
52 | 'linkUrl' => $link,
53 | 'comment' => $message,
54 | ],
55 | ]);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/services/YandexOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use OAuth\Common\Token\TokenInterface;
15 | use nodge\eauth\oauth2\Service;
16 |
17 | /**
18 | * Yandex OAuth provider class.
19 | *
20 | * @package application.extensions.eauth.services
21 | */
22 | class YandexOAuth2Service extends Service
23 | {
24 |
25 | protected $name = 'yandex_oauth';
26 | protected $title = 'Yandex';
27 | protected $type = 'OAuth2';
28 | protected $jsArguments = ['popup' => ['width' => 500, 'height' => 450]];
29 | protected $tokenDefaultLifetime = TokenInterface::EOL_NEVER_EXPIRES;
30 |
31 | protected $scope = [];
32 | protected $providerOptions = [
33 | 'authorize' => 'https://oauth.yandex.ru/authorize',
34 | 'access_token' => 'https://oauth.yandex.ru/token',
35 | ];
36 |
37 | protected function fetchAttributes()
38 | {
39 | $info = $this->makeSignedRequest('https://login.yandex.ru/info');
40 |
41 | $this->attributes['id'] = $info['id'];
42 | $this->attributes['name'] = $info['real_name'];
43 | //$this->attributes['login'] = $info['display_name'];
44 | //$this->attributes['email'] = $info['emails'][0];
45 | //$this->attributes['email'] = $info['default_email'];
46 | $this->attributes['gender'] = ($info['sex'] == 'male') ? 'M' : 'F';
47 |
48 | return true;
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/src/services/extended/VKontakteOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class VKontakteOAuth2Service extends \nodge\eauth\services\VKontakteOAuth2Service
13 | {
14 | const API_VERSION = '5.57';
15 | // protected $scope = 'friends';
16 |
17 | protected function fetchAttributes()
18 | {
19 | $tokenData = $this->getAccessTokenData();
20 | $info = $this->makeSignedRequest('users.get.json', [
21 | 'query' => [
22 | 'uids' => $tokenData['params']['user_id'],
23 | //'fields' => '', // uid, first_name and last_name is always available
24 | 'fields' => 'nickname, sex, bdate, city, country, timezone, photo, photo_medium, photo_big, photo_rec',
25 | 'v' => self::API_VERSION,
26 | ],
27 | ]);
28 |
29 | $info = $info['response'][0];
30 |
31 | $this->attributes = $info;
32 | $this->attributes['id'] = $info['id'];
33 | $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
34 | $this->attributes['url'] = 'http://vk.com/id' . $info['id'];
35 |
36 | if (!empty($info['nickname'])) {
37 | $this->attributes['username'] = $info['nickname'];
38 | } else {
39 | $this->attributes['username'] = 'id' . $info['id'];
40 | }
41 |
42 | $this->attributes['gender'] = $info['sex'] == 1 ? 'F' : 'M';
43 |
44 | if (!empty($info['timezone'])) {
45 | $this->attributes['timezone'] = timezone_name_from_abbr('', $info['timezone'] * 3600, date('I'));
46 | }
47 |
48 | return true;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/services/extended/FacebookOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services\extended;
11 |
12 | class FacebookOAuth2Service extends \nodge\eauth\services\FacebookOAuth2Service
13 | {
14 |
15 | protected $scopes = [
16 | self::SCOPE_EMAIL,
17 | self::SCOPE_USER_BIRTHDAY,
18 | self::SCOPE_USER_HOMETOWN,
19 | self::SCOPE_USER_LOCATION,
20 | self::SCOPE_USER_PHOTOS,
21 | ];
22 |
23 | /**
24 | * http://developers.facebook.com/docs/reference/api/user/
25 | *
26 | * @see FacebookOAuth2Service::fetchAttributes()
27 | */
28 | protected function fetchAttributes()
29 | {
30 | $this->attributes = $this->makeSignedRequest('me', [
31 | 'query' => [
32 | 'fields' => join(',', [
33 | 'id',
34 | 'name',
35 | 'link',
36 | 'email',
37 | 'verified',
38 | 'first_name',
39 | 'last_name',
40 | 'gender',
41 | 'birthday',
42 | 'hometown',
43 | 'location',
44 | 'locale',
45 | 'timezone',
46 | 'updated_time',
47 | ])
48 | ]
49 | ]);
50 |
51 | $this->attributes['photo_url'] = $this->baseApiUrl.$this->getId().'/picture?width=100&height=100';
52 |
53 | return true;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/services/SteamOpenIDService.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\services;
11 |
12 | use nodge\eauth\openid\Service;
13 |
14 | /**
15 | * Steam provider class.
16 | *
17 | * @package application.extensions.eauth.services
18 | */
19 | class SteamOpenIDService extends Service
20 | {
21 |
22 | protected $name = 'steam';
23 | protected $title = 'Steam';
24 | protected $type = 'OpenID';
25 | protected $jsArguments = ['popup' => ['width' => 990, 'height' => 615]];
26 |
27 | protected $url = 'http://steamcommunity.com/openid/';
28 | protected $apiUrl = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/';
29 |
30 | public $apiKey;
31 |
32 | protected function fetchAttributes()
33 | {
34 | $chunks = explode('/', $this->attributes['id']);
35 | $id = array_pop($chunks);
36 |
37 | $this->attributes['name'] = $id;
38 |
39 | if ($this->apiKey) {
40 | $response = $this->makeRequest($this->apiUrl, [
41 | 'query' => [
42 | 'steamids' => $id,
43 | 'key' => $this->apiKey,
44 | 'format' => 'json'
45 | ]
46 | ]);
47 |
48 | if (isset($response['response']['players'][0])) {
49 | $profile = $response['response']['players'][0];
50 |
51 | $this->attributes = array_merge($this->attributes, $profile);
52 | $this->attributes['name'] = $profile['personaname'];
53 | $this->attributes['url'] = $profile['profileurl'];
54 | }
55 | }
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/src/services/TwitterOAuth1Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use OAuth\OAuth1\Token\TokenInterface;
15 | use nodge\eauth\oauth1\Service;
16 |
17 |
18 | /**
19 | * Twitter provider class.
20 | *
21 | * @package application.extensions.eauth.services
22 | */
23 | class TwitterOAuth1Service extends Service
24 | {
25 |
26 | protected $name = 'twitter';
27 | protected $title = 'Twitter';
28 | protected $type = 'OAuth1';
29 | protected $jsArguments = ['popup' => ['width' => 900, 'height' => 550]];
30 |
31 | protected $providerOptions = [
32 | 'request' => 'https://api.twitter.com/oauth/request_token',
33 | 'authorize' => 'https://api.twitter.com/oauth/authenticate', //https://api.twitter.com/oauth/authorize
34 | 'access' => 'https://api.twitter.com/oauth/access_token',
35 | ];
36 | protected $baseApiUrl = 'https://api.twitter.com/1.1/';
37 | protected $tokenDefaultLifetime = TokenInterface::EOL_NEVER_EXPIRES;
38 |
39 | /**
40 | * @return bool
41 | */
42 | protected function fetchAttributes()
43 | {
44 | $info = $this->makeSignedRequest('account/verify_credentials.json');
45 |
46 | $this->attributes['id'] = $info['id'];
47 | $this->attributes['name'] = $info['name'];
48 | $this->attributes['url'] = 'http://twitter.com/account/redirect_by_id?id=' . $info['id_str'];
49 |
50 | /*$this->attributes['username'] = $info['screen_name'];
51 | $this->attributes['language'] = $info['lang'];
52 | $this->attributes['timezone'] = timezone_name_from_abbr('', $info['utc_offset'], date('I'));
53 | $this->attributes['photo'] = $info['profile_image_url'];*/
54 |
55 | return true;
56 | }
57 |
58 | /**
59 | * Authenticate the user.
60 | *
61 | * @return boolean whether user was successfuly authenticated.
62 | */
63 | public function authenticate()
64 | {
65 | if (isset($_GET['denied'])) {
66 | $this->cancel();
67 | }
68 |
69 | return parent::authenticate();
70 | }
71 | }
--------------------------------------------------------------------------------
/src/services/LinkedinOAuth1Service.php:
--------------------------------------------------------------------------------
1 |
9 | * @link http://github.com/Nodge/yii2-eauth/
10 | * @license http://www.opensource.org/licenses/bsd-license.php
11 | */
12 |
13 | namespace nodge\eauth\services;
14 |
15 | use nodge\eauth\oauth1\Service;
16 |
17 | /**
18 | * LinkedIn provider class.
19 | *
20 | * @package application.extensions.eauth.services
21 | */
22 | class LinkedinOAuth1Service extends Service
23 | {
24 |
25 | protected $name = 'linkedin';
26 | protected $title = 'LinkedIn';
27 | protected $type = 'OAuth1';
28 | protected $jsArguments = ['popup' => ['width' => 900, 'height' => 550]];
29 |
30 | protected $providerOptions = [
31 | 'request' => 'https://api.linkedin.com/uas/oauth/requestToken',
32 | 'authorize' => 'https://www.linkedin.com/uas/oauth/authenticate', // https://www.linkedin.com/uas/oauth/authorize
33 | 'access' => 'https://api.linkedin.com/uas/oauth/accessToken',
34 | ];
35 | protected $baseApiUrl = 'http://api.linkedin.com/v1/';
36 |
37 | protected function fetchAttributes()
38 | {
39 | $info = $this->makeSignedRequest('people/~:(id,first-name,last-name,public-profile-url)', [
40 | 'query' => [
41 | 'format' => 'json',
42 | ],
43 | ]);
44 |
45 | $this->attributes['id'] = $info['id'];
46 | $this->attributes['name'] = $info['firstName'] . ' ' . $info['lastName'];
47 | $this->attributes['url'] = $info['publicProfileUrl'];
48 |
49 | return true;
50 | }
51 |
52 | /**
53 | * Returns the error array.
54 | *
55 | * @param array $response
56 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
57 | */
58 | protected function fetchResponseError($response)
59 | {
60 | if (isset($response['error-code'])) {
61 | return [
62 | 'code' => $response['error-code'],
63 | 'message' => $response['message'],
64 | ];
65 | } else if (isset($response['errorCode'])) {
66 | return [
67 | 'code' => $response['errorCode'],
68 | 'message' => $response['message'],
69 | ];
70 | }
71 | return null;
72 | }
73 | }
--------------------------------------------------------------------------------
/src/services/LinkedinOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
9 | * @link http://github.com/Nodge/yii2-eauth/
10 | * @license http://www.opensource.org/licenses/bsd-license.php
11 | */
12 |
13 | namespace nodge\eauth\services;
14 |
15 | use OAuth\OAuth2\Service\ServiceInterface;
16 | use nodge\eauth\oauth2\Service;
17 |
18 | /**
19 | * LinkedIn provider class.
20 | *
21 | * @package application.extensions.eauth.services
22 | */
23 | class LinkedinOAuth2Service extends Service
24 | {
25 |
26 | /**
27 | * Defined scopes
28 | *
29 | * @link http://developer.linkedin.com/documents/authentication#granting
30 | */
31 | const SCOPE_R_BASICPROFILE = 'r_basicprofile';
32 | const SCOPE_R_FULLPROFILE = 'r_fullprofile';
33 | const SCOPE_R_EMAILADDRESS = 'r_emailaddress';
34 | const SCOPE_R_NETWORK = 'r_network';
35 | const SCOPE_R_CONTACTINFO = 'r_contactinfo';
36 | const SCOPE_RW_NUS = 'rw_nus';
37 | const SCOPE_RW_GROUPS = 'rw_groups';
38 | const SCOPE_W_MESSAGES = 'w_messages';
39 |
40 | protected $name = 'linkedin_oauth2';
41 | protected $title = 'LinkedIn';
42 | protected $type = 'OAuth2';
43 | protected $jsArguments = ['popup' => ['width' => 900, 'height' => 550]];
44 |
45 | protected $scopes = [self::SCOPE_R_BASICPROFILE];
46 | protected $providerOptions = [
47 | 'authorize' => 'https://www.linkedin.com/uas/oauth2/authorization',
48 | 'access_token' => 'https://www.linkedin.com/uas/oauth2/accessToken',
49 | ];
50 | protected $baseApiUrl = 'https://api.linkedin.com/v1/';
51 |
52 | protected function fetchAttributes()
53 | {
54 | $info = $this->makeSignedRequest('people/~:(id,first-name,last-name,public-profile-url)', [
55 | 'query' => [
56 | 'format' => 'json',
57 | ],
58 | ]);
59 |
60 | $this->attributes['id'] = $info['id'];
61 | $this->attributes['name'] = $info['firstName'] . ' ' . $info['lastName'];
62 | $this->attributes['url'] = $info['publicProfileUrl'];
63 |
64 | return true;
65 | }
66 |
67 | /**
68 | * @return int
69 | */
70 | public function getAuthorizationMethod()
71 | {
72 | return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING_V2;
73 | }
74 | }
--------------------------------------------------------------------------------
/src/assets/css/eauth.css:
--------------------------------------------------------------------------------
1 |
2 | .eauth {
3 | overflow: hidden;
4 | }
5 |
6 | .eauth-list {
7 | margin: -1em 0 0;
8 | padding: 0;
9 | list-style: none;
10 | }
11 |
12 | .eauth-service {
13 | display: inline-block;
14 | vertical-align: top;
15 | margin: 1em 1em 0 0;
16 | }
17 |
18 | .eauth-service-link {
19 | position: relative;
20 | display: block;
21 | width: 60px;
22 | padding-top: 34px;
23 | text-align: center;
24 | }
25 |
26 | .eauth-service-link:before,
27 | .eauth-service-link:after {
28 | content: '';
29 | position: absolute;
30 | top: 0;
31 | left: 50%;
32 | width: 32px;
33 | height: 32px;
34 | margin-left: -16px;
35 | background: url("../images/auth.png") 0 0 no-repeat;
36 | }
37 |
38 | .eauth-service-link:after {
39 | display: none;
40 | }
41 |
42 | .eauth-service-link:hover:after {
43 | display: block;
44 | }
45 |
46 | /* --- Services --- */
47 |
48 | .eauth-service-id-google_oauth .eauth-service-link:before {
49 | background-position: 0 -34px;
50 | }
51 |
52 | .eauth-service-id-yandex_oauth .eauth-service-link:before {
53 | background-position: 0 -102px;
54 | }
55 |
56 | .eauth-service-id-twitter .eauth-service-link:before {
57 | background-position: 0 -68px;
58 | }
59 |
60 | .eauth-service-id-vkontakte .eauth-service-link:before {
61 | background-position: 0 -136px;
62 | }
63 |
64 | .eauth-service-id-facebook .eauth-service-link:before {
65 | background-position: 0 -170px;
66 | }
67 |
68 | .eauth-service-id-mailru .eauth-service-link:before {
69 | background-position: 0 -204px;
70 | }
71 |
72 | .eauth-service-id-moikrug .eauth-service-link:before {
73 | background-position: 0 -238px;
74 | }
75 |
76 | .eauth-service-id-odnoklassniki .eauth-service-link:before {
77 | background-position: 0 -272px;
78 | }
79 |
80 | .eauth-service-id-linkedin .eauth-service-link:before,
81 | .eauth-service-id-linkedin_oauth2 .eauth-service-link:before {
82 | background-position: 0 -306px;
83 | }
84 |
85 | .eauth-service-id-github .eauth-service-link:before {
86 | background-position: 0 -340px;
87 | }
88 |
89 | .eauth-service-id-live .eauth-service-link:before {
90 | background-position: 0 -372px;
91 | }
92 |
93 | .eauth-service-id-yahoo .eauth-service-link:before {
94 | background-position: 0 -406px;
95 | }
96 |
97 | .eauth-service-id-steam .eauth-service-link:before {
98 | background-position: 0 -440px;
99 | }
100 |
101 | .eauth-service-id-instagram .eauth-service-link:before {
102 | background-position: 0 -474px;
103 | }
--------------------------------------------------------------------------------
/src/services/InstagramOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use nodge\eauth\oauth2\Service;
15 | use OAuth\Common\Token\TokenInterface;
16 | use OAuth\OAuth2\Service\ServiceInterface;
17 |
18 | /**
19 | * Instagram provider class.
20 | *
21 | * @package application.extensions.eauth.services
22 | */
23 | class InstagramOAuth2Service extends Service
24 | {
25 |
26 | /**
27 | * Defined scopes
28 | * @link https://instagram.com/developer/authentication/
29 | */
30 | const SCOPE_BASIC = 'basic';
31 | const SCOPE_COMMENTS = 'comments';
32 | const SCOPE_RELATIONSHIPS = 'relationships';
33 | const SCOPE_LIKES = 'likes';
34 |
35 | protected $name = 'instagram';
36 | protected $title = 'Instagram';
37 | protected $type = 'OAuth2';
38 | protected $jsArguments = ['popup' => ['width' => 900, 'height' => 550]];
39 | protected $popupDisplayName = false;
40 |
41 | protected $scopes = [self::SCOPE_BASIC];
42 | protected $providerOptions = [
43 | 'authorize' => 'https://api.instagram.com/oauth/authorize/',
44 | 'access_token' => 'https://api.instagram.com/oauth/access_token',
45 | ];
46 | protected $baseApiUrl = 'https://api.instagram.com/v1/';
47 |
48 | protected $tokenDefaultLifetime = TokenInterface::EOL_NEVER_EXPIRES;
49 |
50 | protected function fetchAttributes()
51 | {
52 | $info = $this->makeSignedRequest('users/self');
53 | $data = $info['data'];
54 |
55 | $this->attributes = array_merge($this->attributes, [
56 | 'id' => $data['id'],
57 | 'username' => $data['username'],
58 | 'full_name' => $data['full_name'],
59 | 'profile_picture' => $data['profile_picture'],
60 | 'bio' => $data['bio'],
61 | 'website' => $data['website'],
62 | 'counts' => $data['counts']
63 | ]);
64 |
65 | return true;
66 | }
67 |
68 | /**
69 | * @return int
70 | */
71 | public function getAuthorizationMethod()
72 | {
73 | return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING;
74 | }
75 |
76 | /**
77 | * Returns the protected resource.
78 | *
79 | * @param string $url url to request.
80 | * @param array $options HTTP request options. Keys: query, data, referer.
81 | * @param boolean $parseResponse Whether to parse response.
82 | * @return mixed the response.
83 | */
84 | public function makeSignedRequest($url, $options = [], $parseResponse = true)
85 | {
86 | $options['query']['format'] = 'json';
87 | return parent::makeSignedRequest($url, $options, $parseResponse);
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/src/services/MailruOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use nodge\eauth\oauth2\Service;
15 |
16 | /**
17 | * Mail.Ru provider class.
18 | *
19 | * @package application.extensions.eauth.services
20 | */
21 | class MailruOAuth2Service extends Service
22 | {
23 |
24 | protected $name = 'mailru';
25 | protected $title = 'Mail.ru';
26 | protected $type = 'OAuth2';
27 | protected $jsArguments = ['popup' => ['width' => 580, 'height' => 400]];
28 |
29 | protected $scopes = [];
30 | protected $providerOptions = [
31 | 'authorize' => 'https://connect.mail.ru/oauth/authorize',
32 | 'access_token' => 'https://connect.mail.ru/oauth/token',
33 | ];
34 | protected $baseApiUrl = 'http://www.appsmail.ru/platform/api';
35 |
36 | protected function fetchAttributes()
37 | {
38 | $tokenData = $this->getAccessTokenData();
39 |
40 | $info = $this->makeSignedRequest('/', [
41 | 'query' => [
42 | 'uids' => $tokenData['params']['x_mailru_vid'],
43 | 'method' => 'users.getInfo',
44 | 'app_id' => $this->clientId,
45 | ],
46 | ]);
47 |
48 | $info = $info[0];
49 |
50 | $this->attributes['id'] = $info['uid'];
51 | $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
52 | $this->attributes['url'] = $info['link'];
53 |
54 | return true;
55 | }
56 |
57 | /**
58 | * Returns the protected resource.
59 | *
60 | * @param string $url url to request.
61 | * @param array $options HTTP request options. Keys: query, data, referer.
62 | * @param boolean $parseResponse Whether to parse response.
63 | * @return mixed the response.
64 | */
65 | public function makeSignedRequest($url, $options = [], $parseResponse = true)
66 | {
67 | $token = $this->getAccessTokenData();
68 | if (isset($token)) {
69 | $options['query']['secure'] = 1;
70 | $options['query']['session_key'] = $token['access_token'];
71 | $params = '';
72 | ksort($options['query']);
73 | foreach ($options['query'] as $k => $v) {
74 | $params .= $k . '=' . $v;
75 | }
76 | $options['query']['sig'] = md5($params . $this->clientSecret);
77 | }
78 | return parent::makeSignedRequest($url, $options, $parseResponse);
79 | }
80 |
81 | /**
82 | * Returns the error array.
83 | *
84 | * @param array $response
85 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
86 | */
87 | protected function fetchResponseError($response)
88 | {
89 | if (isset($response['error'])) {
90 | return [
91 | 'code' => $response['error']['error_code'],
92 | 'message' => $response['error']['error_msg'],
93 | ];
94 | } else {
95 | return null;
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/src/services/LiveOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use OAuth\OAuth2\Service\ServiceInterface;
15 | use nodge\eauth\oauth2\Service;
16 |
17 | /**
18 | * Microsoft Live provider class.
19 | *
20 | * @package application.extensions.eauth.services
21 | */
22 | class LiveOAuth2Service extends Service
23 | {
24 |
25 | const SCOPE_BASIC = 'wl.basic';
26 | const SCOPE_OFFLINE = 'wl.offline_access';
27 | const SCOPE_SIGNIN = 'wl.signin';
28 | const SCOPE_BIRTHDAY = 'wl.birthday';
29 | const SCOPE_CALENDARS = 'wl.calendars';
30 | const SCOPE_CALENDARS_UPDATE = 'wl.calendars_update';
31 | const SCOPE_CONTACTS_BIRTHDAY = 'wl.contacts_birthday';
32 | const SCOPE_CONTACTS_CREATE = 'wl.contacts_create';
33 | const SCOPE_CONTACTS_CALENDARS = 'wl.contacts_calendars';
34 | const SCOPE_CONTACTS_PHOTOS = 'wl.contacts_photos';
35 | const SCOPE_CONTACTS_SKYDRIVE = 'wl.contacts_skydrive';
36 | const SCOPE_EMAILS = 'wl.emails';
37 | const sCOPE_EVENTS_CREATE = 'wl.events_create';
38 | const SCOPE_MESSENGER = 'wl.messenger';
39 | const SCOPE_PHONE_NUMBERS = 'wl.phone_numbers';
40 | const SCOPE_PHOTOS = 'wl.photos';
41 | const SCOPE_POSTAL_ADDRESSES = 'wl.postal_addresses';
42 | const SCOPE_SHARE = 'wl.share';
43 | const SCOPE_SKYDRIVE = 'wl.skydrive';
44 | const SCOPE_SKYDRIVE_UPDATE = 'wl.skydrive_update';
45 | const SCOPE_WORK_PROFILE = 'wl.work_profile';
46 | const SCOPE_APPLICATIONS = 'wl.applications';
47 | const SCOPE_APPLICATIONS_CREATE = 'wl.applications_create';
48 |
49 | protected $name = 'live';
50 | protected $title = 'Live';
51 | protected $type = 'OAuth2';
52 | protected $jsArguments = ['popup' => ['width' => 500, 'height' => 600]];
53 |
54 | protected $scopes = [self::SCOPE_BASIC];
55 | protected $providerOptions = [
56 | 'authorize' => 'https://login.live.com/oauth20_authorize.srf',
57 | 'access_token' => 'https://login.live.com/oauth20_token.srf',
58 | ];
59 | protected $baseApiUrl = 'https://apis.live.net/v5.0/';
60 |
61 | protected function fetchAttributes()
62 | {
63 | $info = $this->makeSignedRequest('me');
64 |
65 | $this->attributes['id'] = $info['id'];
66 | $this->attributes['name'] = $info['name'];
67 | $this->attributes['url'] = 'https://profile.live.com/cid-' . $info['id'] . '/';
68 |
69 | /*$this->attributes['email'] = $info['emails']['account'];
70 | $this->attributes['first_name'] = $info['first_name'];
71 | $this->attributes['last_name'] = $info['last_name'];
72 | $this->attributes['gender'] = $info['gender'];
73 | $this->attributes['locale'] = $info['locale'];*/
74 |
75 | return true;
76 | }
77 |
78 | /**
79 | * @return int
80 | */
81 | public function getAuthorizationMethod()
82 | {
83 | return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING;
84 | }
85 | }
--------------------------------------------------------------------------------
/src/services/GitHubOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use OAuth\Common\Token\TokenInterface;
15 | use OAuth\OAuth2\Service\ServiceInterface;
16 | use nodge\eauth\oauth2\Service;
17 |
18 | /**
19 | * GitHub provider class.
20 | *
21 | * @package application.extensions.eauth.services
22 | */
23 | class GitHubOAuth2Service extends Service
24 | {
25 |
26 | /**
27 | * Defined scopes, see http://developer.github.com/v3/oauth/ for definitions
28 | */
29 | const SCOPE_USER = 'user';
30 | const SCOPE_PUBLIC_REPO = 'public_repo';
31 | const SCOPE_REPO = 'repo';
32 | const SCOPE_DELETE_REPO = 'delete_repo';
33 | const SCOPE_GIST = 'gist';
34 |
35 | protected $name = 'github';
36 | protected $title = 'GitHub';
37 | protected $type = 'OAuth2';
38 | protected $jsArguments = ['popup' => ['width' => 600, 'height' => 450]];
39 |
40 | protected $scopes = [];
41 | protected $providerOptions = [
42 | 'authorize' => 'https://github.com/login/oauth/authorize',
43 | 'access_token' => 'https://github.com/login/oauth/access_token',
44 | ];
45 | protected $baseApiUrl = 'https://api.github.com/';
46 |
47 | protected $tokenDefaultLifetime = TokenInterface::EOL_NEVER_EXPIRES;
48 | protected $errorAccessDeniedCode = 'user_denied';
49 |
50 | protected function fetchAttributes()
51 | {
52 | $info = $this->makeSignedRequest('user');
53 |
54 | $this->attributes['id'] = $info['id'];
55 | $this->attributes['name'] = $info['login'];
56 | $this->attributes['url'] = $info['html_url'];
57 |
58 | return true;
59 | }
60 |
61 | /**
62 | * Used to configure response type -- we want JSON from github, default is query string format
63 | *
64 | * @return array
65 | */
66 | public function getExtraOAuthHeaders()
67 | {
68 | return ['Accept' => 'application/json'];
69 | }
70 |
71 | /**
72 | * Required for GitHub API calls.
73 | *
74 | * @return array
75 | */
76 | public function getExtraApiHeaders()
77 | {
78 | return ['Accept' => 'application/vnd.github.beta+json'];
79 | }
80 |
81 | /**
82 | * @return int
83 | */
84 | public function getAuthorizationMethod()
85 | {
86 | return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING;
87 | }
88 |
89 | /**
90 | * Returns the error array.
91 | *
92 | * @param array $response
93 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
94 | */
95 | protected function fetchResponseError($response)
96 | {
97 | if (isset($response['message'])) {
98 | return [
99 | 'code' => isset($response['error']) ? $response['code'] : 0,
100 | 'message' => $response['message'],
101 | ];
102 | } else {
103 | return null;
104 | }
105 | }
106 |
107 | }
--------------------------------------------------------------------------------
/src/Widget.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | use Yii;
13 |
14 | /**
15 | * The EAuthWidget widget prints buttons to authenticate user with OpenID and OAuth providers.
16 | *
17 | * @package application.extensions.eauth
18 | */
19 | class Widget extends \yii\base\Widget
20 | {
21 |
22 | /**
23 | * @var string EAuth component name.
24 | */
25 | public $component = 'eauth';
26 |
27 | /**
28 | * @var array the services.
29 | * @see EAuth::getServices()
30 | */
31 | public $services = null;
32 |
33 | /**
34 | * @var array predefined services. If null then use all services. Default is null.
35 | */
36 | public $predefinedServices = null;
37 |
38 | /**
39 | * @var boolean whether to use popup window for authorization dialog. Javascript required.
40 | */
41 | public $popup = null;
42 |
43 | /**
44 | * @var string the action to use for dialog destination. Default: the current route.
45 | */
46 | public $action = null;
47 |
48 | /**
49 | * @var boolean include the CSS file. Default is true.
50 | * If this is set false, you are responsible to explicitly include the necessary CSS file in your page.
51 | */
52 | public $assetBundle = 'nodge\\eauth\\assets\\WidgetAssetBundle';
53 |
54 | /**
55 | * Initializes the widget.
56 | * This method is called by {@link CBaseController::createWidget}
57 | * and {@link CBaseController::beginWidget} after the widget's
58 | * properties have been initialized.
59 | */
60 | public function init()
61 | {
62 | parent::init();
63 |
64 | // EAuth component
65 | /** @var $component \nodge\eauth\EAuth */
66 | $component = Yii::$app->get($this->component);
67 |
68 | // Some default properties from component configuration
69 | if (!isset($this->services)) {
70 | $this->services = $component->getServices();
71 | }
72 |
73 | if (is_array($this->predefinedServices)) {
74 | $_services = [];
75 | foreach ($this->predefinedServices as $_serviceName) {
76 | if (isset($this->services[$_serviceName])) {
77 | $_services[$_serviceName] = $this->services[$_serviceName];
78 | }
79 | }
80 | $this->services = $_services;
81 | }
82 |
83 | if (!isset($this->popup)) {
84 | $this->popup = $component->popup;
85 | }
86 |
87 | // Set the current route, if it is not set.
88 | if (!isset($this->action)) {
89 | $this->action = '/' . Yii::$app->requestedRoute;
90 | }
91 | }
92 |
93 | /**
94 | * Executes the widget.
95 | * This method is called by {@link CBaseController::endWidget}.
96 | */
97 | public function run()
98 | {
99 | parent::run();
100 | echo $this->render('widget', [
101 | 'id' => $this->getId(),
102 | 'services' => $this->services,
103 | 'action' => $this->action,
104 | 'popup' => $this->popup,
105 | 'assetBundle' => $this->assetBundle,
106 | ]);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/services/FacebookOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use nodge\eauth\oauth2\Service;
15 |
16 | /**
17 | * Facebook provider class.
18 | *
19 | * @package application.extensions.eauth.services
20 | */
21 | class FacebookOAuth2Service extends Service
22 | {
23 |
24 | /**
25 | * Full list of scopes may be found here:
26 | * https://developers.facebook.com/docs/authentication/permissions/
27 | */
28 | const SCOPE_EMAIL = 'email';
29 | const SCOPE_USER_BIRTHDAY = 'user_birthday';
30 | const SCOPE_USER_HOMETOWN = 'user_hometown';
31 | const SCOPE_USER_LOCATION = 'user_location';
32 | const SCOPE_USER_PHOTOS = 'user_photos';
33 |
34 | protected $name = 'facebook';
35 | protected $title = 'Facebook';
36 | protected $type = 'OAuth2';
37 | protected $jsArguments = ['popup' => ['width' => 585, 'height' => 290]];
38 |
39 | protected $scopes = [];
40 | protected $providerOptions = [
41 | 'authorize' => 'https://www.facebook.com/dialog/oauth',
42 | 'access_token' => 'https://graph.facebook.com/oauth/access_token',
43 | ];
44 | protected $baseApiUrl = 'https://graph.facebook.com/v2.8/';
45 |
46 | protected function fetchAttributes()
47 | {
48 | $info = $this->makeSignedRequest('me', [
49 | 'query' => [
50 | 'fields' => join(',', [
51 | 'id',
52 | 'name',
53 | 'link'
54 | ])
55 | ]
56 | ]);
57 |
58 | $this->attributes['id'] = $info['id'];
59 | $this->attributes['name'] = $info['name'];
60 | $this->attributes['url'] = $info['link'];
61 |
62 | return true;
63 | }
64 |
65 | /**
66 | * @param string $response
67 | * @return array
68 | */
69 | public function parseAccessTokenResponse($response)
70 | {
71 | // Facebook gives us a query string or json
72 | if ($response[0] === '{') {
73 | return json_decode($response, true);
74 | }
75 | else {
76 | parse_str($response, $data);
77 | return $data;
78 | }
79 | }
80 |
81 | /**
82 | * Returns the error array.
83 | *
84 | * @param array $response
85 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
86 | */
87 | protected function fetchResponseError($response)
88 | {
89 | if (isset($response['error'])) {
90 | return [
91 | 'code' => $response['error']['code'],
92 | 'message' => $response['error']['message'],
93 | ];
94 | } else {
95 | return null;
96 | }
97 | }
98 |
99 | /**
100 | * @param array $data
101 | * @return string|null
102 | */
103 | public function getAccessTokenResponseError($data)
104 | {
105 | $error = $this->fetchResponseError($data);
106 | if (!$error) {
107 | return null;
108 | }
109 | return $error['code'].': '.$error['message'];
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/IAuthService.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | /**
13 | * IAuthService is the interface for all service types and providers.
14 | *
15 | * @package application.extensions.eauth
16 | */
17 | interface IAuthService
18 | {
19 |
20 | /**
21 | * Returns service name(id).
22 | */
23 | public function getServiceName();
24 |
25 | /**
26 | * Returns service title.
27 | */
28 | public function getServiceTitle();
29 |
30 | /**
31 | * Returns service type (e.g. OpenID, OAuth).
32 | */
33 | public function getServiceType();
34 |
35 | /**
36 | * Returns arguments for the jQuery.eauth() javascript function.
37 | */
38 | public function getJsArguments();
39 |
40 |
41 | /**
42 | * Sets {@link EAuth} application component
43 | *
44 | * @param EAuth $component the application auth component.
45 | */
46 | public function setComponent($component);
47 |
48 | /**
49 | * Returns the {@link EAuth} application component.
50 | */
51 | public function getComponent();
52 |
53 |
54 | /**
55 | * Sets redirect url after successful authorization.
56 | *
57 | * @param string $url url to redirect.
58 | */
59 | public function setRedirectUrl($url);
60 |
61 | /**
62 | * Returns the redirect url after successful authorization.
63 | */
64 | public function getRedirectUrl();
65 |
66 |
67 | /**
68 | * Sets redirect url after unsuccessful authorization (e.g. user canceled).
69 | *
70 | * @param string $url url to redirect.
71 | */
72 | public function setCancelUrl($url);
73 |
74 | /**
75 | * Returns the redirect url after unsuccessful authorization (e.g. user canceled).
76 | */
77 | public function getCancelUrl();
78 |
79 |
80 | /**
81 | * Authenticate the user.
82 | */
83 | public function authenticate();
84 |
85 | /**
86 | * Whether user was successfuly authenticated.
87 | */
88 | public function getIsAuthenticated();
89 |
90 |
91 | /**
92 | * Redirect to the url. If url is null, {@link redirectUrl} will be used.
93 | *
94 | * @param string $url url to redirect.
95 | */
96 | public function redirect($url = null);
97 |
98 | /**
99 | * Redirect to the {@link cancelUrl} or simply close the popup window.
100 | */
101 | public function cancel();
102 |
103 |
104 | /**
105 | * Returns the user unique id.
106 | */
107 | public function getId();
108 |
109 | /**
110 | * Returns the array that contains all available authorization attributes.
111 | */
112 | public function getAttributes();
113 |
114 | /**
115 | * Returns the authorization attribute value.
116 | *
117 | * @param string $key the attribute name.
118 | * @param mixed $default the default value.
119 | */
120 | public function getAttribute($key, $default = null);
121 |
122 | /**
123 | * Whether the authorization attribute exists.
124 | *
125 | * @param string $key the attribute name.
126 | */
127 | public function hasAttribute($key);
128 |
129 | }
--------------------------------------------------------------------------------
/src/services/OdnoklassnikiOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
10 | * @link http://github.com/Nodge/yii2-eauth/
11 | * @license http://www.opensource.org/licenses/bsd-license.php
12 | */
13 |
14 | namespace nodge\eauth\services;
15 |
16 | use nodge\eauth\oauth2\Service;
17 |
18 | /**
19 | * Odnoklassniki.Ru provider class.
20 | *
21 | * @package application.extensions.eauth.services
22 | */
23 | class OdnoklassnikiOAuth2Service extends Service
24 | {
25 |
26 | const SCOPE_VALUABLE_ACCESS = 'VALUABLE ACCESS';
27 | const SCOPE_SET_STATUS = 'SET STATUS';
28 | const SCOPE_PHOTO_CONTENT = 'PHOTO CONTENT';
29 |
30 | protected $name = 'odnoklassniki';
31 | protected $title = 'Odnoklassniki';
32 | protected $type = 'OAuth2';
33 | protected $jsArguments = ['popup' => ['width' => 680, 'height' => 500]];
34 |
35 | protected $clientPublic;
36 | protected $scopes = [];
37 | protected $scopeSeparator = ';';
38 | protected $providerOptions = [
39 | 'authorize' => 'https://connect.ok.ru/oauth/authorize',
40 | 'access_token' => 'https://api.ok.ru/oauth/token.do',
41 | ];
42 | protected $baseApiUrl = 'https://api.ok.ru/api/';
43 |
44 | protected $tokenDefaultLifetime = 1500; // about 25 minutes
45 | protected $validateState = false;
46 |
47 | protected function fetchAttributes()
48 | {
49 | $info = $this->makeSignedRequest('', [
50 | 'query' => [
51 | 'method' => 'users.getCurrentUser',
52 | 'format' => 'JSON',
53 | 'application_key' => $this->clientPublic,
54 | 'client_id' => $this->clientId,
55 | ],
56 | ]);
57 |
58 | $this->attributes['id'] = $info['uid'];
59 | $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
60 |
61 | return true;
62 | }
63 |
64 | /**
65 | * @return string
66 | */
67 | public function getClientPublic()
68 | {
69 | return $this->clientPublic;
70 | }
71 |
72 | /**
73 | * @param string $clientPublic
74 | */
75 | public function setClientPublic($clientPublic)
76 | {
77 | $this->clientPublic = $clientPublic;
78 | }
79 |
80 | /**
81 | * Returns the protected resource.
82 | *
83 | * @param string $url url to request.
84 | * @param array $options HTTP request options. Keys: query, data, referer.
85 | * @param boolean $parseResponse Whether to parse response.
86 | * @return mixed the response.
87 | */
88 | public function makeSignedRequest($url, $options = [], $parseResponse = true)
89 | {
90 | $token = $this->getAccessTokenData();
91 | if (isset($token)) {
92 | $params = '';
93 | ksort($options['query']);
94 | foreach ($options['query'] as $k => $v) {
95 | $params .= $k . '=' . $v;
96 | }
97 | $options['query']['sig'] = md5($params . md5($token['access_token'] . $this->clientSecret));
98 | $options['query']['access_token'] = $token['access_token'];
99 | }
100 | return parent::makeSignedRequest($url, $options, $parseResponse);
101 | }
102 |
103 | /**
104 | * Returns the error array.
105 | *
106 | * @param array $response
107 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
108 | */
109 | protected function fetchResponseError($response)
110 | {
111 | if (isset($response['error_code'])) {
112 | return [
113 | 'code' => $response['error_code'],
114 | 'message' => $response['error_msg'],
115 | ];
116 | } else {
117 | return null;
118 | }
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/src/services/VKontakteOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use nodge\eauth\oauth2\Service;
15 | use OAuth\OAuth2\Service\ServiceInterface;
16 |
17 | /**
18 | * VKontakte provider class.
19 | *
20 | * @package application.extensions.eauth.services
21 | */
22 | class VKontakteOAuth2Service extends Service
23 | {
24 |
25 | const SCOPE_FRIENDS = 'friends';
26 | const API_VERSION = '5.57';
27 |
28 | protected $name = 'vkontakte';
29 | protected $title = 'VK.com';
30 | protected $type = 'OAuth2';
31 | protected $jsArguments = ['popup' => ['width' => 585, 'height' => 350]];
32 |
33 | protected $scopes = [self::SCOPE_FRIENDS];
34 | protected $providerOptions = [
35 | 'authorize' => 'http://api.vk.com/oauth/authorize',
36 | 'access_token' => 'https://api.vk.com/oauth/access_token',
37 | ];
38 | protected $baseApiUrl = 'https://api.vk.com/method/';
39 |
40 | protected function fetchAttributes()
41 | {
42 | $tokenData = $this->getAccessTokenData();
43 | $info = $this->makeSignedRequest('users.get.json', [
44 | 'query' => [
45 | 'uids' => $tokenData['params']['user_id'],
46 | 'fields' => '', // uid, first_name and last_name is always available
47 | //'fields' => 'nickname, sex, bdate, city, country, timezone, photo, photo_medium, photo_big, photo_rec',
48 | 'v' => self::API_VERSION,
49 | ],
50 | ]);
51 |
52 | $info = $info['response'][0];
53 |
54 | $this->attributes['id'] = $info['id'];
55 | $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
56 | $this->attributes['url'] = 'http://vk.com/id' . $info['id'];
57 |
58 | /*if (!empty($info['nickname']))
59 | $this->attributes['username'] = $info['nickname'];
60 | else
61 | $this->attributes['username'] = 'id'.$info['uid'];
62 |
63 | $this->attributes['gender'] = $info['sex'] == 1 ? 'F' : 'M';
64 |
65 | $this->attributes['city'] = $info['city'];
66 | $this->attributes['country'] = $info['country'];
67 |
68 | $this->attributes['timezone'] = timezone_name_from_abbr('', $info['timezone']*3600, date('I'));;
69 |
70 | $this->attributes['photo'] = $info['photo'];
71 | $this->attributes['photo_medium'] = $info['photo_medium'];
72 | $this->attributes['photo_big'] = $info['photo_big'];
73 | $this->attributes['photo_rec'] = $info['photo_rec'];*/
74 |
75 | return true;
76 | }
77 |
78 | /**
79 | * Returns the error array.
80 | *
81 | * @param array $response
82 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
83 | */
84 | protected function fetchResponseError($response)
85 | {
86 | if (isset($response['error'])) {
87 | return [
88 | 'code' => is_string($response['error']) ? 0 : $response['error']['error_code'],
89 | // 'message' => is_string($response['error']) ? $response['error'] : $response['error']['error_msg'],
90 | // 'message' => is_string($response['error']) ? $response['error'] : $response['error']['error_msg'],
91 | ];
92 | } else {
93 | return null;
94 | }
95 | }
96 |
97 | /**
98 | * @param array $data
99 | * @return string|null
100 | */
101 | public function getAccessTokenResponseError($data)
102 | {
103 | if (!isset($data['error'])) {
104 | return null;
105 | }
106 | $error = $data['error'];
107 | if (isset($data['error_description'])) {
108 | $error .= ': ' . $data['error_description'];
109 | }
110 | return $error;
111 | }
112 |
113 | /**
114 | * Returns a class constant from ServiceInterface defining the authorization method used for the API.
115 | *
116 | * @return int
117 | */
118 | public function getAuthorizationMethod()
119 | {
120 | return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING;
121 | }
122 |
123 | }
--------------------------------------------------------------------------------
/src/oauth1/Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth1;
11 |
12 | use Yii;
13 | use OAuth\Common\Exception\Exception as OAuthException;
14 | use OAuth\Common\Http\Uri\Uri;
15 | use OAuth\Common\Consumer\Credentials;
16 | use OAuth\OAuth1\Signature\Signature;
17 | use nodge\eauth\EAuth;
18 | use nodge\eauth\ErrorException;
19 | use nodge\eauth\IAuthService;
20 | use nodge\eauth\oauth\ServiceBase;
21 |
22 | /**
23 | * EOAuthService is a base class for all OAuth providers.
24 | *
25 | * @package application.extensions.eauth
26 | */
27 | abstract class Service extends ServiceBase implements IAuthService
28 | {
29 |
30 | /**
31 | * @var string OAuth2 client id.
32 | */
33 | protected $key;
34 |
35 | /**
36 | * @var string OAuth2 client secret key.
37 | */
38 | protected $secret;
39 |
40 | /**
41 | * @var array Provider options. Must contain the keys: request, authorize, access.
42 | */
43 | protected $providerOptions = [
44 | 'request' => '',
45 | 'authorize' => '',
46 | 'access' => '',
47 | ];
48 |
49 | /**
50 | * @var ServiceProxy
51 | */
52 | private $_proxy;
53 |
54 | /**
55 | * Initialize the component.
56 | *
57 | * @param EAuth $component the component instance.
58 | * @param array $options properties initialization.
59 | */
60 | // public function init($component, $options = []) {
61 | // parent::init($component, $options);
62 | // }
63 |
64 | /**
65 | * @param string $key
66 | */
67 | public function setKey($key)
68 | {
69 | $this->key = $key;
70 | }
71 |
72 | /**
73 | * @param string $secret
74 | */
75 | public function setSecret($secret)
76 | {
77 | $this->secret = $secret;
78 | }
79 |
80 | /**
81 | * @return ServiceProxy
82 | */
83 | protected function getProxy()
84 | {
85 | if (!isset($this->_proxy)) {
86 | $storage = $this->getTokenStorage();
87 | $httpClient = $this->getHttpClient();
88 | $credentials = new Credentials($this->key, $this->secret, $this->getCallbackUrl());
89 | $signature = new Signature($credentials);
90 | $this->_proxy = new ServiceProxy($credentials, $httpClient, $storage, $signature, null, $this);
91 | }
92 | return $this->_proxy;
93 | }
94 |
95 | /**
96 | * Authenticate the user.
97 | *
98 | * @return boolean whether user was successfuly authenticated.
99 | * @throws ErrorException
100 | */
101 | public function authenticate()
102 | {
103 | try {
104 | $proxy = $this->getProxy();
105 |
106 | if (!empty($_GET['oauth_token'])) {
107 | $token = $proxy->retrieveAccessToken();
108 |
109 | // This was a callback request, get the token now
110 | $proxy->requestAccessToken($_GET['oauth_token'], $_GET['oauth_verifier'], $token->getRequestTokenSecret());
111 |
112 | $this->authenticated = true;
113 | } else if ($proxy->hasValidAccessToken()) {
114 | $this->authenticated = true;
115 | } else {
116 | // extra request needed for oauth1 to request a request token :-)
117 | $token = $proxy->requestRequestToken();
118 | /** @var $url Uri */
119 | $url = $proxy->getAuthorizationUri(['oauth_token' => $token->getRequestToken()]);
120 | Yii::$app->getResponse()->redirect($url->getAbsoluteUri())->send();
121 | }
122 | } catch (OAuthException $e) {
123 | throw new ErrorException($e->getMessage(), $e->getCode(), 1, $e->getFile(), $e->getLine(), $e);
124 | }
125 |
126 | return $this->getIsAuthenticated();
127 | }
128 |
129 | /**
130 | * @return string
131 | */
132 | public function getRequestTokenEndpoint()
133 | {
134 | return $this->providerOptions['request'];
135 | }
136 |
137 | /**
138 | * @return string
139 | */
140 | public function getAuthorizationEndpoint()
141 | {
142 | return $this->providerOptions['authorize'];
143 | }
144 |
145 | /**
146 | * @return string
147 | */
148 | public function getAccessTokenEndpoint()
149 | {
150 | return $this->providerOptions['access'];
151 | }
152 |
153 | /**
154 | * @return array
155 | */
156 | public function getAccessTokenArgumentNames()
157 | {
158 | return [
159 | 'oauth_token' => 'oauth_token',
160 | 'oauth_token_secret' => 'oauth_token_secret',
161 | 'oauth_expires_in' => 'oauth_expires_in',
162 | ];
163 | }
164 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Yii2 EAuth Change Log
2 | =====================
3 |
4 | ### 2.5.0 (10.04.2017)
5 | * Fix bug with access token expire time in Facebook service (#102)
6 | * Use the latest Graph Api v2.8 for Facebook
7 | * Using version when making VK API call (#92)
8 | * New authorization and API url for Odnoklassniki service (#73)
9 | * Added Polish translation (#93)
10 | * Added Romanian translation (#94)
11 |
12 | ### 2.4.1 (13.01.2016)
13 | * Move response parsing from oauth to base service (#71)
14 | * Get user profile from Steam API (#70)
15 |
16 | ### 2.4.0 (03.01.2016)
17 | * Fixed error param names for Facebook (#63)
18 | * Use the latest Graph Api v2.5 for Facebook (#65)
19 | * Fixed `makeRequest` method (#68)
20 | * Added `makeRequest` method to OpenID services
21 |
22 | ### 2.3.0 (17.10.2015)
23 | * Added InstagramOAuth2Service (#61)
24 | * Fixed default token lifetime (#53)
25 | * Replace array() with [] (#54)
26 | * Remove deprecated Google OpenID service (#56)
27 | * Remove deprecated Yandex OpenID service
28 |
29 | ### 2.2.4 (27.07.2015)
30 | * Fixed typo in `oauth2/Service.php` (#34)
31 | * Added German translation
32 | * Added `email` attribute to `LinkedinOAuth2Service.php`
33 |
34 | ### 2.2.3 (15.07.2014)
35 | * Added ability to call public api methods (without access token) (#28)
36 |
37 | ### 2.2.2 (15.07.2014)
38 | * Fixed wrong redirect_uri when popup is used
39 |
40 | ### 2.2.1 (25.04.2014)
41 | * Fix missing query params in callback urls (#26)
42 | * Follow Yii2 code style
43 |
44 | ### 2.2.0 (19.04.2014)
45 | * Support for PHPoAuthLib v0.3 (#22)
46 | * Support for Yii2 beta
47 | * Internal state implementation replaced to PHPoAuthLib storage
48 |
49 | ### 2.1.5 (24.03.2014)
50 | * Fixed Yii2 refactor (#17)
51 | * PSR-4
52 |
53 | ### 2.1.4 (11.03.2014)
54 | * Fixed wrong callbackUrl in oauth\ServiceBase when UrlManager uses prettyUrl=false and showScript=false (#12)
55 | * Fixed Yii::t() calls according to Yii2 i18n Named Placeholders (#14)
56 | * Fixed Yii2 refactor #2630 (#15)
57 |
58 | ### 2.1.3 (30.01.2014)
59 | * Yii2 update (Request methods has been refactored).
60 |
61 | ### 2.1.2 (17.01.2014)
62 | * Fixed typo in oauth2\ServiceProxy
63 |
64 | ### 2.1.1 (07.01.2014)
65 | * Fixed scope validation for OAuth services.
66 |
67 | ### 2.1.0 (22.12.2013)
68 | * Reorganize project with new namespace.
69 | * Assets bundle has been moved.
70 | * Fixed typo in HttpClient (#8).
71 | * Added default User-Agent header to HttpClient.
72 | * Disabled CSRF validation for OpenID callbacks.
73 | * Optimized icons file.
74 | * Added SteamOpenIDService.
75 | * Improved redirect widget.
76 |
77 | ### 2.0.3 (26.10.2013)
78 | * Fixed redirect_uri when not using url rule (#2).
79 | * Fixed hasValidAccessToken() method for OAuth1 services (#3).
80 | * Fixed auto login cookie (#4).
81 |
82 | ### 2.0.2 (12.10.2013)
83 | * Fixed ServiceProxy constructor to match its interface (#1).
84 | * Added HttpClient with logging support and curl/streams fallback.
85 | * TokenStorage and HttpClient are configurable now.
86 |
87 | ### 2.0.1 (08.09.2013)
88 | * Fixed package versions in the composer.json.
89 | * Fixed directories names.
90 | * Added support for custom scope separator in OAuth2 services.
91 | * Added support for additional headers for OAuth2 requests.
92 | * Added method to get error from access token response.
93 | * Added GitHubOAuth2Service.
94 | * Added LinkedinOAuth2Service.
95 | * Added MailruOAuth2Service.
96 | * Added OdnoklassnikiOAuth2Service.
97 | * Added LiveOAuth2Service.
98 | * Added YahooOpenIDService.
99 |
100 | ### Version 2.0.0 (03.09.2013)
101 | * Use curl for http requests by default.
102 | * getIsAuthenticated() function now looks up for existing access token for all OAuth services.
103 | * Added support for oauth_expires_in to OAuth1 services.
104 | * Added error handlers to OAuth1 services.
105 | * Added support for refresh tokens to OAuth2 ServiceProxy.
106 | * Added an option to disable OAuth2 state validation.
107 |
108 | ### 31.08.2013
109 | * Reorganize directories. Separate root directory by service type.
110 | * Fixed OAuthService::getCallbackUrl(). Now returns url without GET arguments.
111 | * Fixed typos in OAuth services.
112 | * Fixed OpenID loadAttributes functions.
113 | * OAuth2 display mode handling moved to the base class.
114 | * Added OAuthService::getAccessTokenData() method to access to valid access_token and related data.
115 | * Added token default lifetime setting.
116 | * Added "state" argument handling for OAuth2 services to improve security.
117 | * Updated OpenID library. Fixed error with stream requests.
118 | * Added VKontakteOAuth2Service.
119 | * Added GoogleOAuth2Service.
120 | * Added GoogleOAuth2Service.
121 | * Added YandexOAuth2Service.
122 | * Added session token storage using Yii session.
123 |
124 | ### 30.08.2013
125 | * Initial release for Yii2.
126 |
--------------------------------------------------------------------------------
/src/oauth/SessionTokenStorage.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth;
11 |
12 | use Yii;
13 | use OAuth\Common\Storage\TokenStorageInterface;
14 | use OAuth\Common\Token\TokenInterface;
15 | use OAuth\Common\Storage\Exception\TokenNotFoundException;
16 | use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
17 |
18 | /**
19 | * Stores a token in a PHP session.
20 | */
21 | class SessionTokenStorage implements TokenStorageInterface
22 | {
23 |
24 | const SESSION_TOKEN_PREFIX = 'eauth-token-';
25 | const SESSION_STATE_PREFIX = 'eauth-state-';
26 |
27 | /**
28 | * @var
29 | */
30 | protected $componentName;
31 |
32 | /**
33 | * @param string $componentName
34 | */
35 | public function __construct($componentName = 'session')
36 | {
37 | $this->componentName = $componentName;
38 | }
39 |
40 | /**
41 | * @return null|object
42 | */
43 | protected function getSession()
44 | {
45 | return Yii::$app->get($this->componentName);
46 | }
47 |
48 | /**
49 | * @param string $service
50 | * @return TokenInterface
51 | * @throws TokenNotFoundException
52 | */
53 | public function retrieveAccessToken($service)
54 | {
55 | if ($this->hasAccessToken($service)) {
56 | return $this->getSession()->get(self::SESSION_TOKEN_PREFIX . $service);
57 | }
58 | throw new TokenNotFoundException('Token not found in session, are you sure you stored it?');
59 | }
60 |
61 | /**
62 | * @param string $service
63 | * @param TokenInterface $token
64 | * @return TokenInterface
65 | */
66 | public function storeAccessToken($service, TokenInterface $token)
67 | {
68 | $this->getSession()->set(self::SESSION_TOKEN_PREFIX . $service, $token);
69 | return $token;
70 | }
71 |
72 | /**
73 | * @param string $service
74 | * @return bool
75 | */
76 | public function hasAccessToken($service)
77 | {
78 | return $this->getSession()->has(self::SESSION_TOKEN_PREFIX . $service);
79 | }
80 |
81 | /**
82 | * Delete the users token. Aka, log out.
83 | *
84 | * @param string $service
85 | * @return TokenStorageInterface
86 | */
87 | public function clearToken($service)
88 | {
89 | $this->getSession()->remove(self::SESSION_TOKEN_PREFIX . $service);
90 | return $this;
91 | }
92 |
93 | /**
94 | * Delete *ALL* user tokens.
95 | *
96 | * @return TokenStorageInterface
97 | */
98 | public function clearAllTokens()
99 | {
100 | $session = $this->getSession();
101 | foreach ($session as $key => $value) {
102 | if (strpos($key, self::SESSION_TOKEN_PREFIX) === 0) {
103 | $session->remove($key);
104 | }
105 | }
106 | return $this;
107 | }
108 |
109 | /**
110 | * Store the authorization state related to a given service
111 | *
112 | * @param string $service
113 | * @param string $state
114 | * @return TokenStorageInterface
115 | */
116 | public function storeAuthorizationState($service, $state)
117 | {
118 | $this->getSession()->set(self::SESSION_STATE_PREFIX . $service, $state);
119 | return $this;
120 | }
121 |
122 | /**
123 | * Check if an authorization state for a given service exists
124 | *
125 | * @param string $service
126 | * @return bool
127 | */
128 | public function hasAuthorizationState($service)
129 | {
130 | return $this->getSession()->has(self::SESSION_STATE_PREFIX . $service);
131 | }
132 |
133 | /**
134 | * Retrieve the authorization state for a given service
135 | *
136 | * @param string $service
137 | * @return string
138 | * @throws AuthorizationStateNotFoundException
139 | */
140 | public function retrieveAuthorizationState($service)
141 | {
142 | if ($this->hasAuthorizationState($service)) {
143 | return $this->getSession()->get(self::SESSION_STATE_PREFIX . $service);
144 | }
145 | throw new AuthorizationStateNotFoundException('State not found in session, are you sure you stored it?');
146 | }
147 |
148 | /**
149 | * Clear the authorization state of a given service
150 | *
151 | * @param string $service
152 | * @return TokenStorageInterface
153 | */
154 | public function clearAuthorizationState($service)
155 | {
156 | $this->getSession()->remove(self::SESSION_STATE_PREFIX . $service);
157 | return $this;
158 | }
159 |
160 | /**
161 | * Delete *ALL* user authorization states. Use with care. Most of the time you will likely
162 | * want to use clearAuthorizationState() instead.
163 | *
164 | * @return TokenStorageInterface
165 | */
166 | public function clearAllAuthorizationStates()
167 | {
168 | $session = $this->getSession();
169 | foreach ($session as $key => $value) {
170 | if (strpos($key, self::SESSION_STATE_PREFIX) === 0) {
171 | $session->remove($key);
172 | }
173 | }
174 | return $this;
175 | }
176 |
177 | }
178 |
--------------------------------------------------------------------------------
/src/openid/Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\openid;
11 |
12 | use \Yii;
13 | use \LightOpenID;
14 | use yii\web\HttpException;
15 | use nodge\eauth\ServiceBase;
16 | use nodge\eauth\IAuthService;
17 | use nodge\eauth\ErrorException;
18 |
19 | /**
20 | * EOpenIDService is a base class for all OpenID providers.
21 | *
22 | * @package application.extensions.eauth
23 | */
24 | abstract class Service extends ServiceBase implements IAuthService
25 | {
26 |
27 | /**
28 | * @var string a pattern that represents the part of URL-space for which an OpenID Authentication request is valid.
29 | * See the spec for more info: http://openid.net/specs/openid-authentication-2_0.html#realms
30 | * Note: a pattern can be without http(s):// part
31 | */
32 | public $realm;
33 |
34 | /**
35 | * @var LightOpenID the openid library instance.
36 | */
37 | private $auth;
38 |
39 | /**
40 | * @var string the OpenID authorization url.
41 | */
42 | protected $url;
43 |
44 | /**
45 | * @var array the OpenID required attributes.
46 | */
47 | protected $requiredAttributes = [];
48 |
49 | /**
50 | * @var array the OpenID optional attributes.
51 | */
52 | protected $optionalAttributes = [];
53 |
54 |
55 | /**
56 | * Initialize the component.
57 | */
58 | public function init()
59 | {
60 | parent::init();
61 | $this->auth = new LightOpenID(Yii::$app->getRequest()->getHostInfo());
62 | }
63 |
64 | /**
65 | * Authenticate the user.
66 | *
67 | * @return boolean whether user was successfuly authenticated.
68 | * @throws ErrorException
69 | * @throws HttpException
70 | */
71 | public function authenticate()
72 | {
73 | if (!empty($_REQUEST['openid_mode'])) {
74 | switch ($_REQUEST['openid_mode']) {
75 | case 'id_res':
76 | $this->id_res();
77 | return true;
78 | break;
79 |
80 | case 'cancel':
81 | $this->cancel();
82 | break;
83 |
84 | default:
85 | throw new HttpException(400, Yii::t('yii', 'Your request is invalid.'));
86 | break;
87 | }
88 | } else {
89 | $this->processRequest();
90 | }
91 |
92 | return false;
93 | }
94 |
95 | /**
96 | * @throws ErrorException
97 | */
98 | protected function id_res()
99 | {
100 | try {
101 | if ($this->auth->validate()) {
102 | $this->attributes['id'] = $this->auth->identity;
103 | $this->loadRequiredAttributes();
104 | $this->loadOptionalAttributes();
105 | $this->authenticated = true;
106 | } else {
107 | throw new ErrorException(Yii::t('eauth', 'Unable to complete the authentication because the required data was not received.', ['provider' => $this->getServiceTitle()]));
108 | }
109 | } catch (\Exception $e) {
110 | throw new ErrorException($e->getMessage(), $e->getCode());
111 | }
112 | }
113 |
114 | /**
115 | * @throws ErrorException
116 | */
117 | protected function loadOptionalAttributes()
118 | {
119 | $attributes = $this->auth->getAttributes();
120 | foreach ($this->optionalAttributes as $key => $attr) {
121 | if (isset($attributes[$attr[1]])) {
122 | $this->attributes[$key] = $attributes[$attr[1]];
123 | }
124 | }
125 | }
126 |
127 | /**
128 | *
129 | */
130 | protected function loadRequiredAttributes()
131 | {
132 | $attributes = $this->auth->getAttributes();
133 | foreach ($this->requiredAttributes as $key => $attr) {
134 | if (isset($attributes[$attr[1]])) {
135 | $this->attributes[$key] = $attributes[$attr[1]];
136 | } else {
137 | throw new ErrorException(Yii::t('eauth', 'Unable to complete the authentication because the required data was not received.', ['provider' => $this->getServiceTitle()]));
138 | }
139 | }
140 | }
141 |
142 | /**
143 | * @throws ErrorException
144 | */
145 | protected function processRequest()
146 | {
147 | $this->auth->identity = $this->url; //Setting identifier
148 |
149 | $this->auth->required = []; //Try to get info from openid provider
150 | foreach ($this->requiredAttributes as $attribute) {
151 | $this->auth->required[$attribute[0]] = $attribute[1];
152 | }
153 | foreach ($this->optionalAttributes as $attribute) {
154 | $this->auth->required[$attribute[0]] = $attribute[1];
155 | }
156 |
157 | $this->auth->realm = $this->getRealm();
158 | $this->auth->returnUrl = Yii::$app->getRequest()->getHostInfo() . Yii::$app->getRequest()->getUrl(); //getting return URL
159 |
160 | try {
161 | $url = $this->auth->authUrl();
162 | Yii::$app->getResponse()->redirect($url)->send();
163 | } catch (\Exception $e) {
164 | throw new ErrorException($e->getMessage(), $e->getCode());
165 | }
166 | }
167 |
168 | /**
169 | * @return string
170 | */
171 | protected function getRealm()
172 | {
173 | if (isset($this->realm)) {
174 | if (!preg_match('#^[a-z]+\://#', $this->realm)) {
175 | return 'http' . (Yii::$app->getRequest()->getIsSecureConnection() ? 's' : '') . '://' . $this->realm;
176 | } else {
177 | return $this->realm;
178 | }
179 | } else {
180 | return Yii::$app->getRequest()->getHostInfo();
181 | }
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/oauth/ServiceBase.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth;
11 |
12 | use Yii;
13 | use OAuth\Common\Storage\TokenStorageInterface;
14 | use nodge\eauth\EAuth;
15 | use nodge\eauth\IAuthService;
16 | use nodge\eauth\ErrorException;
17 | use yii\helpers\ArrayHelper;
18 | use yii\helpers\Url;
19 |
20 | /**
21 | * EOAuthService is a base class for all OAuth providers.
22 | *
23 | * @package application.extensions.eauth
24 | */
25 | abstract class ServiceBase extends \nodge\eauth\ServiceBase implements IAuthService
26 | {
27 |
28 | /**
29 | * @var string Base url for API calls.
30 | */
31 | protected $baseApiUrl;
32 |
33 | /**
34 | * @var int Default token lifetime. Used when service wont provide expires_in param.
35 | */
36 | protected $tokenDefaultLifetime = null;
37 |
38 | /**
39 | * @var array TokenStorage class. Null means default value from EAuth component config.
40 | */
41 | protected $tokenStorage;
42 |
43 | /**
44 | * @var TokenStorageInterface
45 | */
46 | private $_tokenStorage;
47 |
48 | /**
49 | * Initialize the component.
50 | *
51 | * @param EAuth $component the component instance.
52 | * @param array $options properties initialization.
53 | */
54 | // public function init($component, $options = []) {
55 | // parent::init($component, $options);
56 | // }
57 |
58 | /**
59 | * For OAuth we can check existing access token.
60 | * Useful for API calls.
61 | *
62 | * @return bool
63 | * @throws ErrorException
64 | */
65 | public function getIsAuthenticated()
66 | {
67 | if (!$this->authenticated) {
68 | try {
69 | $proxy = $this->getProxy();
70 | $this->authenticated = $proxy->hasValidAccessToken();
71 | } catch (\OAuth\Common\Exception\Exception $e) {
72 | throw new ErrorException($e->getMessage(), $e->getCode(), 1, $e->getFile(), $e->getLine(), $e);
73 | }
74 | }
75 | return parent::getIsAuthenticated();
76 | }
77 |
78 | /**
79 | * @return \nodge\eauth\oauth1\ServiceProxy|\nodge\eauth\oauth2\ServiceProxy
80 | */
81 | abstract protected function getProxy();
82 |
83 | /**
84 | * @return string the current url
85 | */
86 | protected function getCallbackUrl()
87 | {
88 | return Url::to('', true);
89 | }
90 |
91 | /**
92 | * @param array $config
93 | */
94 | public function setTokenStorage(array $config)
95 | {
96 | $this->tokenStorage = ArrayHelper::merge($this->tokenStorage, $config);
97 | }
98 |
99 | /**
100 | * @return TokenStorageInterface
101 | */
102 | protected function getTokenStorage()
103 | {
104 | if (!isset($this->_tokenStorage)) {
105 | $config = $this->tokenStorage;
106 | if (!isset($config)) {
107 | $config = $this->getComponent()->getTokenStorage();
108 | }
109 | $this->_tokenStorage = Yii::createObject($config);
110 | }
111 | return $this->_tokenStorage;
112 | }
113 |
114 | /**
115 | * @return int
116 | */
117 | public function getTokenDefaultLifetime()
118 | {
119 | return $this->tokenDefaultLifetime;
120 | }
121 |
122 | /**
123 | * Returns the protected resource.
124 | *
125 | * @param string $url url to request.
126 | * @param array $options HTTP request options. Keys: query, data, headers.
127 | * @param boolean $parseResponse Whether to parse response.
128 | * @return mixed the response.
129 | * @throws ErrorException
130 | */
131 | public function makeSignedRequest($url, $options = [], $parseResponse = true)
132 | {
133 | if (!$this->getIsAuthenticated()) {
134 | throw new ErrorException(Yii::t('eauth', 'Unable to complete the signed request because the user was not authenticated.'), 401);
135 | }
136 |
137 | return $this->request($url, $options, $parseResponse, function ($url, $method, $headers, $data) {
138 | return $this->getProxy()->request($url, $method, $data, $headers);
139 | });
140 | }
141 |
142 | /**
143 | * Returns the public resource.
144 | *
145 | * @param string $url url to request.
146 | * @param array $options HTTP request options. Keys: query, data, headers.
147 | * @param boolean $parseResponse Whether to parse response.
148 | * @return mixed the response.
149 | * @throws ErrorException
150 | */
151 | public function makeRequest($url, $options = [], $parseResponse = true)
152 | {
153 | $headers = isset($options['headers']) ? $options['headers'] : [];
154 | $options['headers'] = array_merge($this->getExtraApiHeaders(), $headers);
155 |
156 | return parent::makeRequest($url, $options, $parseResponse);
157 | }
158 |
159 | /**
160 | * @return array|null An array with valid access_token information.
161 | */
162 | protected function getAccessTokenData()
163 | {
164 | if (!$this->getIsAuthenticated()) {
165 | return null;
166 | }
167 |
168 | $token = $this->getProxy()->getAccessToken();
169 | if (!isset($token)) {
170 | return null;
171 | }
172 |
173 | return [
174 | 'access_token' => $token->getAccessToken(),
175 | 'refresh_token' => $token->getRefreshToken(),
176 | 'expires' => $token->getEndOfLife(),
177 | 'params' => $token->getExtraParams(),
178 | ];
179 | }
180 |
181 | /**
182 | * @param array $data
183 | * @return string|null
184 | */
185 | public function getAccessTokenResponseError($data)
186 | {
187 | return isset($data['error']) ? $data['error'] : null;
188 | }
189 |
190 | /**
191 | * Return any additional headers always needed for this service implementation's API calls.
192 | *
193 | * @return array
194 | */
195 | public function getExtraApiHeaders()
196 | {
197 | return [];
198 | }
199 | }
--------------------------------------------------------------------------------
/src/oauth1/ServiceProxy.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth1;
11 |
12 | use OAuth\Common\Consumer\CredentialsInterface;
13 | use OAuth\Common\Http\Client\ClientInterface;
14 | use OAuth\Common\Http\Exception\TokenResponseException;
15 | use OAuth\Common\Http\Uri\Uri;
16 | use OAuth\Common\Http\Uri\UriInterface;
17 | use OAuth\Common\Storage\TokenStorageInterface;
18 | use OAuth\Common\Token\TokenInterface;
19 | use OAuth\OAuth1\Service\AbstractService;
20 | use OAuth\OAuth1\Signature\SignatureInterface;
21 | use OAuth\OAuth1\Token\StdOAuth1Token;
22 |
23 | class ServiceProxy extends AbstractService
24 | {
25 |
26 | /**
27 | * @var Service the currently used service class
28 | */
29 | protected $service;
30 |
31 | /**
32 | * {@inheritDoc}
33 | */
34 | public function __construct(
35 | CredentialsInterface $credentials,
36 | ClientInterface $httpClient,
37 | TokenStorageInterface $storage,
38 | SignatureInterface $signature,
39 | UriInterface $baseApiUri = null,
40 | Service $service
41 | )
42 | {
43 | $this->service = $service;
44 | parent::__construct($credentials, $httpClient, $storage, $signature, $baseApiUri);
45 | }
46 |
47 | /**
48 | * @return string
49 | */
50 | public function service()
51 | {
52 | return $this->service->getServiceName();
53 | }
54 |
55 | /**
56 | * @return StdOAuth1Token
57 | */
58 | public function retrieveAccessToken()
59 | {
60 | return $this->storage->retrieveAccessToken($this->service());
61 | }
62 |
63 | /**
64 | *
65 | */
66 | public function hasValidAccessToken()
67 | {
68 | $serviceName = $this->service();
69 |
70 | if (!$this->storage->hasAccessToken($serviceName)) {
71 | return false;
72 | }
73 |
74 | /** @var $token StdOAuth1Token */
75 | $token = $this->storage->retrieveAccessToken($serviceName);
76 |
77 | $params = $token->getExtraParams();
78 | if (isset($params['is_request_token'])) {
79 | return false;
80 | }
81 |
82 | return $this->checkTokenLifetime($token);
83 | }
84 |
85 | /**
86 | * @param TokenInterface $token
87 | * @return bool
88 | */
89 | protected function checkTokenLifetime($token)
90 | {
91 | // assume that we have at least a minute to execute a queries.
92 | return $token->getEndOfLife() - 60 > time()
93 | || $token->getEndOfLife() === TokenInterface::EOL_NEVER_EXPIRES
94 | || $token->getEndOfLife() === TokenInterface::EOL_UNKNOWN;
95 | }
96 |
97 | /**
98 | * @return null|TokenInterface
99 | */
100 | public function getAccessToken()
101 | {
102 | if (!$this->hasValidAccessToken()) {
103 | return null;
104 | }
105 |
106 | $serviceName = $this->service();
107 | return $this->storage->retrieveAccessToken($serviceName);
108 | }
109 |
110 | /**
111 | * @return UriInterface
112 | */
113 | public function getRequestTokenEndpoint()
114 | {
115 | return new Uri($this->service->getRequestTokenEndpoint());
116 | }
117 |
118 | /**
119 | * @return UriInterface
120 | */
121 | public function getAuthorizationEndpoint()
122 | {
123 | return new Uri($this->service->getAuthorizationEndpoint());
124 | }
125 |
126 | /**
127 | * @return UriInterface
128 | */
129 | public function getAccessTokenEndpoint()
130 | {
131 | return new Uri($this->service->getAccessTokenEndpoint());
132 | }
133 |
134 | /**
135 | * We need a separate request token parser only to verify the `oauth_callback_confirmed` parameter. For the actual
136 | * parsing we can just use the default access token parser.
137 | *
138 | * @param string $responseBody
139 | * @return StdOAuth1Token
140 | * @throws TokenResponseException
141 | */
142 | protected function parseRequestTokenResponse($responseBody)
143 | {
144 | parse_str($responseBody, $data);
145 |
146 | if (!isset($data) || !is_array($data)) {
147 | throw new TokenResponseException('Unable to parse response.');
148 | } else if (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] != 'true') {
149 | throw new TokenResponseException('Error in retrieving token.');
150 | }
151 |
152 | $data['is_request_token'] = true;
153 | return $this->parseAccessTokenResponse($data);
154 | }
155 |
156 | /**
157 | * @param string|array $responseBody
158 | * @return StdOAuth1Token
159 | * @throws TokenResponseException
160 | */
161 | protected function parseAccessTokenResponse($responseBody)
162 | {
163 | if (!is_array($responseBody)) {
164 | parse_str($responseBody, $data);
165 |
166 | if (!isset($data) || !is_array($data)) {
167 | throw new TokenResponseException('Unable to parse response.');
168 | }
169 | } else {
170 | $data = $responseBody;
171 | }
172 |
173 | $error = $this->service->getAccessTokenResponseError($data);
174 | if (isset($error)) {
175 | throw new TokenResponseException('Error in retrieving token: "' . $error . '"');
176 | }
177 |
178 | $token = new StdOAuth1Token();
179 | $names = $this->service->getAccessTokenArgumentNames();
180 |
181 | $token->setRequestToken($data[$names['oauth_token']]);
182 | $token->setRequestTokenSecret($data[$names['oauth_token_secret']]);
183 | $token->setAccessToken($data[$names['oauth_token']]);
184 | $token->setAccessTokenSecret($data[$names['oauth_token_secret']]);
185 | unset($data[$names['oauth_token']], $data[$names['oauth_token_secret']]);
186 |
187 | if (isset($data[$names['oauth_expires_in']])) {
188 | $token->setLifeTime($data[$names['oauth_expires_in']]);
189 | unset($data[$names['oauth_expires_in']]);
190 | } else {
191 | $token->setLifetime($this->service->getTokenDefaultLifetime());
192 | }
193 |
194 | $token->setExtraParams($data);
195 |
196 | return $token;
197 | }
198 |
199 | /**
200 | * Return any additional headers always needed for this service implementation's API calls.
201 | *
202 | * @return array
203 | */
204 | protected function getExtraApiHeaders()
205 | {
206 | return $this->service->getExtraApiHeaders();
207 | }
208 | }
--------------------------------------------------------------------------------
/src/oauth2/ServiceProxy.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth2;
11 |
12 | use OAuth\Common\Consumer\CredentialsInterface;
13 | use OAuth\Common\Http\Client\ClientInterface;
14 | use OAuth\Common\Http\Exception\TokenResponseException;
15 | use OAuth\Common\Http\Uri\Uri;
16 | use OAuth\Common\Http\Uri\UriInterface;
17 | use OAuth\Common\Storage\TokenStorageInterface;
18 | use OAuth\Common\Token\TokenInterface;
19 | use OAuth\OAuth2\Service\AbstractService;
20 | use OAuth\OAuth2\Token\StdOAuth2Token;
21 |
22 | class ServiceProxy extends AbstractService
23 | {
24 |
25 | /**
26 | * @var Service the currently used service class
27 | */
28 | protected $service;
29 |
30 | /**
31 | * @param CredentialsInterface $credentials
32 | * @param ClientInterface $httpClient
33 | * @param TokenStorageInterface $storage
34 | * @param array $scopes
35 | * @param UriInterface $baseApiUri
36 | * @param Service $service
37 | */
38 | public function __construct(
39 | CredentialsInterface $credentials,
40 | ClientInterface $httpClient,
41 | TokenStorageInterface $storage,
42 | $scopes = [],
43 | UriInterface $baseApiUri = null,
44 | Service $service
45 | )
46 | {
47 | $this->service = $service;
48 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri, $service->getValidateState());
49 | }
50 |
51 | /**
52 | * @return string
53 | */
54 | public function service()
55 | {
56 | return $this->service->getServiceName();
57 | }
58 |
59 | /**
60 | * Validate scope
61 | *
62 | * @param string $scope
63 | * @return bool
64 | */
65 | public function isValidScope($scope)
66 | {
67 | $reflectionClass = new \ReflectionClass(get_class($this->service));
68 | return in_array($scope, $reflectionClass->getConstants(), true);
69 | }
70 |
71 | /**
72 | * @return bool
73 | */
74 | public function hasValidAccessToken()
75 | {
76 | $serviceName = $this->service();
77 |
78 | if (!$this->storage->hasAccessToken($serviceName)) {
79 | return false;
80 | }
81 |
82 | /** @var $token StdOAuth2Token */
83 | $token = $this->storage->retrieveAccessToken($serviceName);
84 | $valid = $this->checkTokenLifetime($token);
85 |
86 | if (!$valid) {
87 | $refreshToken = $token->getRefreshToken();
88 | if (isset($refreshToken)) {
89 | $token = $this->refreshAccessToken($token);
90 | return $this->checkTokenLifetime($token);
91 | }
92 | }
93 |
94 | return $valid;
95 | }
96 |
97 | /**
98 | * @param TokenInterface $token
99 | * @return bool
100 | */
101 | protected function checkTokenLifetime($token)
102 | {
103 | // assume that we have at least a minute to execute a queries.
104 | return $token->getEndOfLife() - 60 > time()
105 | || $token->getEndOfLife() === TokenInterface::EOL_NEVER_EXPIRES
106 | || $token->getEndOfLife() === TokenInterface::EOL_UNKNOWN;
107 | }
108 |
109 | /**
110 | * @return null|TokenInterface
111 | */
112 | public function getAccessToken()
113 | {
114 | if (!$this->hasValidAccessToken()) {
115 | return null;
116 | }
117 |
118 | $serviceName = $this->service();
119 | return $this->storage->retrieveAccessToken($serviceName);
120 | }
121 |
122 | /**
123 | * @return UriInterface
124 | */
125 | public function getAuthorizationEndpoint()
126 | {
127 | return new Uri($this->service->getAuthorizationEndpoint());
128 | }
129 |
130 | /**
131 | * @return UriInterface
132 | */
133 | public function getAccessTokenEndpoint()
134 | {
135 | return new Uri($this->service->getAccessTokenEndpoint());
136 | }
137 |
138 | /**
139 | * @param string $responseBody
140 | * @return StdOAuth2Token
141 | * @throws TokenResponseException
142 | */
143 | protected function parseAccessTokenResponse($responseBody)
144 | {
145 | $data = $this->service->parseAccessTokenResponse($responseBody);
146 |
147 | if (!isset($data) || !is_array($data)) {
148 | throw new TokenResponseException('Unable to parse response.');
149 | }
150 |
151 | $error = $this->service->getAccessTokenResponseError($data);
152 | if (isset($error)) {
153 | throw new TokenResponseException('Error in retrieving token: "' . $error . '"');
154 | }
155 |
156 | $token = new StdOAuth2Token();
157 | $names = $this->service->getAccessTokenArgumentNames();
158 |
159 | $token->setAccessToken($data[$names['access_token']]);
160 | unset($data[$names['access_token']]);
161 |
162 | if (isset($data[$names['expires_in']])) {
163 | $token->setLifeTime($data[$names['expires_in']]);
164 | unset($data[$names['expires_in']]);
165 | } else {
166 | $token->setLifetime($this->service->getTokenDefaultLifetime());
167 | }
168 |
169 | if (isset($data[$names['refresh_token']])) {
170 | $token->setRefreshToken($data[$names['refresh_token']]);
171 | unset($data[$names['refresh_token']]);
172 | }
173 |
174 | $token->setExtraParams($data);
175 |
176 | return $token;
177 | }
178 |
179 | /**
180 | * Return any additional headers always needed for this service implementation's OAuth calls.
181 | *
182 | * @return array
183 | */
184 | protected function getExtraOAuthHeaders()
185 | {
186 | return $this->service->getExtraOAuthHeaders();
187 | }
188 |
189 | /**
190 | * Return any additional headers always needed for this service implementation's API calls.
191 | *
192 | * @return array
193 | */
194 | protected function getExtraApiHeaders()
195 | {
196 | return $this->service->getExtraApiHeaders();
197 | }
198 |
199 | /**
200 | * Returns a class constant from ServiceInterface defining the authorization method used for the API
201 | * Header is the sane default.
202 | *
203 | * @return int
204 | */
205 | protected function getAuthorizationMethod()
206 | {
207 | return $this->service->getAuthorizationMethod();
208 | }
209 |
210 | /**
211 | * Returns the url to redirect to for authorization purposes.
212 | *
213 | * @param array $additionalParameters
214 | * @return Uri
215 | */
216 | public function getAuthorizationUri(array $additionalParameters = [])
217 | {
218 | $parameters = array_merge($additionalParameters, [
219 | 'type' => 'web_server',
220 | 'client_id' => $this->credentials->getConsumerId(),
221 | 'redirect_uri' => $this->credentials->getCallbackUrl(),
222 | 'response_type' => 'code',
223 | ]);
224 |
225 | $parameters['scope'] = implode($this->service->getScopeSeparator(), $this->scopes);
226 |
227 | if ($this->needsStateParameterInAuthUrl()) {
228 | if (!isset($parameters['state'])) {
229 | $parameters['state'] = $this->generateAuthorizationState();
230 | }
231 | $this->storeAuthorizationState($parameters['state']);
232 | }
233 |
234 | // Build the url
235 | $url = clone $this->getAuthorizationEndpoint();
236 | foreach ($parameters as $key => $val) {
237 | $url->addToQuery($key, $val);
238 | }
239 |
240 | return $url;
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/src/services/GoogleOAuth2Service.php:
--------------------------------------------------------------------------------
1 |
8 | * @link http://github.com/Nodge/yii2-eauth/
9 | * @license http://www.opensource.org/licenses/bsd-license.php
10 | */
11 |
12 | namespace nodge\eauth\services;
13 |
14 | use nodge\eauth\oauth2\Service;
15 |
16 | /**
17 | * Google provider class.
18 | *
19 | * @package application.extensions.eauth.services
20 | */
21 | class GoogleOAuth2Service extends Service
22 | {
23 |
24 | /**
25 | * Defined scopes - More scopes are listed here:
26 | * https://developers.google.com/oauthplayground/
27 | */
28 |
29 | // Basic
30 | const SCOPE_EMAIL = 'email';
31 | const SCOPE_PROFILE = 'profile';
32 |
33 | const SCOPE_USERINFO_EMAIL = 'https://www.googleapis.com/auth/userinfo.email';
34 | const SCOPE_USERINFO_PROFILE = 'https://www.googleapis.com/auth/userinfo.profile';
35 |
36 | // Google+
37 | const SCOPE_GPLUS_ME = 'https://www.googleapis.com/auth/plus.me';
38 | const SCOPE_GPLUS_LOGIN = 'https://www.googleapis.com/auth/plus.login';
39 |
40 | // Google Drive
41 | const SCOPE_DOCUMENTSLIST = 'https://docs.google.com/feeds/';
42 | const SCOPE_SPREADSHEETS = 'https://spreadsheets.google.com/feeds/';
43 | const SCOPE_GOOGLEDRIVE = 'https://www.googleapis.com/auth/drive';
44 | const SCOPE_DRIVE_APPS = 'https://www.googleapis.com/auth/drive.appdata';
45 | const SCOPE_DRIVE_APPS_READ_ONLY = 'https://www.googleapis.com/auth/drive.apps.readonly';
46 | const SCOPE_GOOGLEDRIVE_FILES = 'https://www.googleapis.com/auth/drive.file';
47 | const SCOPE_DRIVE_METADATA_READ_ONLY = 'https://www.googleapis.com/auth/drive.metadata.readonly';
48 | const SCOPE_DRIVE_READ_ONLY = 'https://www.googleapis.com/auth/drive.readonly';
49 | const SCOPE_DRIVE_SCRIPTS = 'https://www.googleapis.com/auth/drive.scripts';
50 |
51 | // Adwords
52 | const SCOPE_ADSENSE = 'https://www.googleapis.com/auth/adsense';
53 | const SCOPE_ADWORDS = 'https://adwords.google.com/api/adwords/';
54 | const SCOPE_GAN = 'https://www.googleapis.com/auth/gan'; // google affiliate network...?
55 |
56 | // Google Analytics
57 | const SCOPE_ANALYTICS = 'https://www.googleapis.com/auth/analytics';
58 | const SCOPE_ANALYTICS_EDIT = 'https://www.googleapis.com/auth/analytics.edit';
59 | const SCOPE_ANALYTICS_MANAGE_USERS = 'https://www.googleapis.com/auth/analytics.manage.users';
60 | const SCOPE_ANALYTICS_READ_ONLY = 'https://www.googleapis.com/auth/analytics.readonly';
61 |
62 | // Other services
63 | const SCOPE_BOOKS = 'https://www.googleapis.com/auth/books';
64 | const SCOPE_BLOGGER = 'https://www.googleapis.com/auth/blogger';
65 | const SCOPE_CALENDAR = 'https://www.googleapis.com/auth/calendar';
66 | const SCOPE_CONTACT = 'https://www.google.com/m8/feeds/';
67 | const SCOPE_CHROMEWEBSTORE = 'https://www.googleapis.com/auth/chromewebstore.readonly';
68 | const SCOPE_GMAIL = 'https://mail.google.com/mail/feed/atom';
69 | const SCOPE_PICASAWEB = 'https://picasaweb.google.com/data/';
70 | const SCOPE_SITES = 'https://sites.google.com/feeds/';
71 | const SCOPE_URLSHORTENER = 'https://www.googleapis.com/auth/urlshortener';
72 | const SCOPE_WEBMASTERTOOLS = 'https://www.google.com/webmasters/tools/feeds/';
73 | const SCOPE_TASKS = 'https://www.googleapis.com/auth/tasks';
74 |
75 | // Cloud services
76 | const SCOPE_CLOUDSTORAGE = 'https://www.googleapis.com/auth/devstorage.read_write';
77 | const SCOPE_CONTENTFORSHOPPING = 'https://www.googleapis.com/auth/structuredcontent'; // what even is this
78 | const SCOPE_USER_PROVISIONING = 'https://apps-apis.google.com/a/feeds/user/';
79 | const SCOPE_GROUPS_PROVISIONING = 'https://apps-apis.google.com/a/feeds/groups/';
80 | const SCOPE_NICKNAME_PROVISIONING = 'https://apps-apis.google.com/a/feeds/alias/';
81 |
82 | // Old
83 | const SCOPE_ORKUT = 'https://www.googleapis.com/auth/orkut';
84 | const SCOPE_GOOGLELATITUDE =
85 | 'https://www.googleapis.com/auth/latitude.all.best https://www.googleapis.com/auth/latitude.all.city';
86 | const SCOPE_OPENID = 'openid';
87 |
88 | // YouTube
89 | const SCOPE_YOUTUBE_GDATA = 'https://gdata.youtube.com';
90 | const SCOPE_YOUTUBE_ANALYTICS_MONETARY = 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly';
91 | const SCOPE_YOUTUBE_ANALYTICS = 'https://www.googleapis.com/auth/yt-analytics.readonly';
92 | const SCOPE_YOUTUBE = 'https://www.googleapis.com/auth/youtube';
93 | const SCOPE_YOUTUBE_READ_ONLY = 'https://www.googleapis.com/auth/youtube.readonly';
94 | const SCOPE_YOUTUBE_UPLOAD = 'https://www.googleapis.com/auth/youtube.upload';
95 | const SCOPE_YOUTUBE_PATNER = 'https://www.googleapis.com/auth/youtubepartner';
96 | const SCOPE_YOUTUBE_PARTNER_EDIT = 'https://www.googleapis.com/auth/youtubepartner-channel-edit';
97 |
98 | // Google Glass
99 | const SCOPE_GLASS_TIMELINE = 'https://www.googleapis.com/auth/glass.timeline';
100 | const SCOPE_GLASS_LOCATION = 'https://www.googleapis.com/auth/glass.location';
101 |
102 | protected $name = 'google_oauth';
103 | protected $title = 'Google';
104 | protected $type = 'OAuth2';
105 | protected $jsArguments = ['popup' => ['width' => 500, 'height' => 450]];
106 |
107 | protected $scopes = [self::SCOPE_USERINFO_PROFILE];
108 | protected $providerOptions = [
109 | 'authorize' => 'https://accounts.google.com/o/oauth2/auth',
110 | 'access_token' => 'https://accounts.google.com/o/oauth2/token',
111 | ];
112 |
113 | protected function fetchAttributes()
114 | {
115 | $info = $this->makeSignedRequest('https://www.googleapis.com/oauth2/v1/userinfo');
116 |
117 | $this->attributes['id'] = $info['id'];
118 | $this->attributes['name'] = $info['name'];
119 |
120 | if (!empty($info['link'])) {
121 | $this->attributes['url'] = $info['link'];
122 | }
123 |
124 | /*if (!empty($info['gender']))
125 | $this->attributes['gender'] = $info['gender'] == 'male' ? 'M' : 'F';
126 |
127 | if (!empty($info['picture']))
128 | $this->attributes['photo'] = $info['picture'];
129 |
130 | $info['given_name']; // first name
131 | $info['family_name']; // last name
132 | $info['birthday']; // format: 0000-00-00
133 | $info['locale']; // format: en*/
134 | }
135 |
136 | /**
137 | * Returns the protected resource.
138 | *
139 | * @param string $url url to request.
140 | * @param array $options HTTP request options. Keys: query, data, referer.
141 | * @param boolean $parseResponse Whether to parse response.
142 | * @return mixed the response.
143 | */
144 | public function makeSignedRequest($url, $options = [], $parseResponse = true)
145 | {
146 | if (!isset($options['query']['alt'])) {
147 | $options['query']['alt'] = 'json';
148 | }
149 | return parent::makeSignedRequest($url, $options, $parseResponse);
150 | }
151 |
152 | /**
153 | * Returns the error array.
154 | *
155 | * @param array $response
156 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
157 | */
158 | protected function fetchResponseError($response)
159 | {
160 | if (isset($response['error'])) {
161 | return [
162 | 'code' => $response['error']['code'],
163 | 'message' => $response['error']['message'],
164 | ];
165 | } else {
166 | return null;
167 | }
168 | }
169 | }
--------------------------------------------------------------------------------
/src/oauth/HttpClient.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth;
11 |
12 | use Yii;
13 | use OAuth\Common\Http\Client\AbstractClient;
14 | use OAuth\Common\Http\Exception\TokenResponseException;
15 | use OAuth\Common\Http\Uri\UriInterface;
16 |
17 | /**
18 | * Client implementation for cURL
19 | */
20 | class HttpClient extends AbstractClient
21 | {
22 |
23 | /**
24 | * If true, explicitly sets cURL to use SSL version 3. Use this if cURL
25 | * compiles with GnuTLS SSL.
26 | *
27 | * @var bool
28 | */
29 | protected $forceSSL3 = false;
30 |
31 | /**
32 | * If true and you are working in safe_mode environment or inside open_basedir
33 | * it will use streams instead of curl.
34 | *
35 | * @var bool
36 | */
37 | protected $useStreamsFallback = false;
38 |
39 | /**
40 | * @var UriInterface
41 | */
42 | protected $endpoint;
43 |
44 | /**
45 | * @var mixed
46 | */
47 | protected $requestBody;
48 |
49 | /**
50 | * @var array
51 | */
52 | protected $extraHeaders = [];
53 |
54 | /**
55 | * @var string
56 | */
57 | protected $method = 'POST';
58 |
59 | /**
60 | * @param bool $force
61 | */
62 | public function setForceSSL3($force)
63 | {
64 | $this->forceSSL3 = $force;
65 | }
66 |
67 | /**
68 | * @return boolean
69 | */
70 | public function getForceSSL3()
71 | {
72 | return $this->forceSSL3;
73 | }
74 |
75 | /**
76 | * @param bool $useStreamsFallback
77 | */
78 | public function setUseStreamsFallback($useStreamsFallback)
79 | {
80 | $this->useStreamsFallback = $useStreamsFallback;
81 | }
82 |
83 | /**
84 | * @return bool
85 | */
86 | public function getUseStreamsFallback()
87 | {
88 | return $this->useStreamsFallback;
89 | }
90 |
91 | /**
92 | * Any implementing HTTP providers should send a request to the provided endpoint with the parameters.
93 | * They should return, in string form, the response body and throw an exception on error.
94 | *
95 | * @param UriInterface $endpoint
96 | * @param mixed $requestBody
97 | * @param array $extraHeaders
98 | * @param string $method
99 | * @return string
100 | */
101 | public function retrieveResponse(UriInterface $endpoint, $requestBody, array $extraHeaders = [], $method = 'POST')
102 | {
103 | $this->endpoint = $endpoint;
104 | $this->requestBody = $requestBody;
105 | $this->extraHeaders = $extraHeaders;
106 | $this->method = $method;
107 |
108 | if ($this->useStreamsFallback && !$this->allowFollowLocation()) {
109 | return $this->streams();
110 | }
111 |
112 | return $this->curl();
113 | }
114 |
115 | /**
116 | * @return bool
117 | */
118 | protected function allowFollowLocation()
119 | {
120 | return !ini_get('safe_mode') && !ini_get('open_basedir');
121 | }
122 |
123 | /**
124 | *
125 | */
126 | protected function prepareRequest()
127 | {
128 | $this->method = strtoupper($this->method);
129 | $this->normalizeHeaders($this->extraHeaders);
130 |
131 | if ($this->method === 'GET' && !empty($this->requestBody)) {
132 | throw new \InvalidArgumentException('No body expected for "GET" request.');
133 | }
134 |
135 | if (!isset($this->extraHeaders['Content-type']) && $this->method === 'POST' && is_array($this->requestBody)) {
136 | $this->extraHeaders['Content-type'] = 'Content-type: application/x-www-form-urlencoded';
137 | }
138 |
139 | // Some of services requires User-Agent header (e.g. GitHub)
140 | if (!isset($this->extraHeaders['User-Agent'])) {
141 | $this->extraHeaders['User-Agent'] = 'User-Agent: yii2-eauth';
142 | }
143 |
144 | $this->extraHeaders['Host'] = 'Host: ' . $this->endpoint->getHost();
145 | $this->extraHeaders['Connection'] = 'Connection: close';
146 |
147 | if (YII_DEBUG) {
148 | Yii::trace('EAuth http request: ' . PHP_EOL . var_export([
149 | 'url' => $this->endpoint->getAbsoluteUri(),
150 | 'method' => $this->method,
151 | 'headers' => $this->extraHeaders,
152 | 'body' => $this->requestBody,
153 | ], true), __NAMESPACE__);
154 | }
155 |
156 | if (is_array($this->requestBody)) {
157 | $this->requestBody = http_build_query($this->requestBody, null, '&');
158 | }
159 | }
160 |
161 | /**
162 | * @return string
163 | * @throws TokenResponseException
164 | */
165 | protected function curl()
166 | {
167 | $this->prepareRequest();
168 |
169 | $ch = curl_init();
170 | curl_setopt($ch, CURLOPT_URL, $this->endpoint->getAbsoluteUri());
171 |
172 | if ($this->method === 'POST' || $this->method === 'PUT') {
173 | if ($this->method === 'PUT') {
174 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
175 | } else {
176 | curl_setopt($ch, CURLOPT_POST, true);
177 | }
178 | curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
179 | } else {
180 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
181 | }
182 |
183 | if ($this->allowFollowLocation() && $this->maxRedirects > 0) {
184 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
185 | curl_setopt($ch, CURLOPT_MAXREDIRS, $this->maxRedirects);
186 | }
187 |
188 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
189 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
190 | curl_setopt($ch, CURLOPT_HEADER, false);
191 | curl_setopt($ch, CURLOPT_HTTPHEADER, $this->extraHeaders);
192 |
193 | if ($this->forceSSL3) {
194 | curl_setopt($ch, CURLOPT_SSLVERSION, 3);
195 | }
196 |
197 | $response = curl_exec($ch);
198 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
199 |
200 | if (YII_DEBUG) {
201 | Yii::trace('EAuth http response: ' . PHP_EOL . var_export($response, true), __NAMESPACE__);
202 | }
203 |
204 | if (false === $response) {
205 | $errNo = curl_errno($ch);
206 | $errStr = curl_error($ch);
207 | curl_close($ch);
208 |
209 | if (empty($errStr)) {
210 | $errStr = 'Failed to request resource.';
211 | } else {
212 | $errStr = 'cURL Error # ' . $errNo . ': ' . $errStr;
213 | }
214 |
215 | Yii::error('EAuth curl error (' . $responseCode . '): ' . $errStr, __NAMESPACE__);
216 | throw new TokenResponseException($errStr, $responseCode);
217 | }
218 |
219 | curl_close($ch);
220 |
221 | return $response;
222 | }
223 |
224 | /**
225 | * @return string
226 | * @throws TokenResponseException
227 | */
228 | protected function streams()
229 | {
230 | $this->prepareRequest();
231 |
232 | $context = stream_context_create([
233 | 'http' => [
234 | 'method' => $this->method,
235 | 'header' => array_values($this->extraHeaders),
236 | 'content' => $this->requestBody,
237 | 'protocol_version' => '1.1',
238 | 'user_agent' => 'Yii2 EAuth Client',
239 | 'max_redirects' => $this->maxRedirects,
240 | 'timeout' => $this->timeout,
241 | ],
242 | ]);
243 |
244 | $level = error_reporting(0);
245 | $response = file_get_contents($this->endpoint->getAbsoluteUri(), false, $context);
246 | error_reporting($level);
247 |
248 | if (YII_DEBUG) {
249 | Yii::trace('EAuth http response: ' . PHP_EOL . var_export($response, true), __NAMESPACE__);
250 | }
251 |
252 | if (false === $response) {
253 | $lastError = error_get_last();
254 |
255 | if (is_null($lastError)) {
256 | $errStr = 'Failed to request resource.';
257 | } else {
258 | $errStr = $lastError['message'];
259 | }
260 |
261 | Yii::error('EAuth streams error: ' . $errStr, __NAMESPACE__);
262 | throw new TokenResponseException($errStr);
263 | }
264 |
265 | return $response;
266 | }
267 |
268 | }
269 |
--------------------------------------------------------------------------------
/src/EAuth.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | use Yii;
13 | use yii\base\Object;
14 | use yii\helpers\ArrayHelper;
15 | use yii\helpers\Url;
16 |
17 | /**
18 | * The EAuth class provides simple authentication via OpenID and OAuth providers.
19 | *
20 | * @package application.extensions.eauth
21 | */
22 | class EAuth extends Object
23 | {
24 |
25 | /**
26 | * @var array Authorization services and their settings.
27 | */
28 | protected $services = [];
29 |
30 | /**
31 | * @var boolean Whether to use popup window for the authorization dialog.
32 | */
33 | protected $popup = true;
34 |
35 | /**
36 | * @var string|bool Cache component name to use. False to disable cache.
37 | */
38 | public $cache = null;
39 |
40 | /**
41 | * @var integer the number of seconds in which the cached value will expire. 0 means never expire.
42 | */
43 | public $cacheExpire = 0;
44 |
45 | /**
46 | * @var string popup redirect view with custom js code
47 | */
48 | protected $redirectWidget = '\\nodge\\eauth\\RedirectWidget';
49 |
50 | /**
51 | * @var array TokenStorage class.
52 | */
53 | protected $tokenStorage = [
54 | 'class' => 'nodge\eauth\oauth\SessionTokenStorage',
55 | ];
56 |
57 | /**
58 | * @var array HttpClient class.
59 | */
60 | protected $httpClient = [
61 | 'class' => 'nodge\eauth\oauth\HttpClient',
62 | // 'useStreamsFallback' => false,
63 | ];
64 |
65 | /**
66 | * Initialize the component.
67 | */
68 | public function init()
69 | {
70 | parent::init();
71 |
72 | // set default cache on production environments
73 | if (!isset($this->cache) && YII_ENV_PROD) {
74 | $this->cache = 'cache';
75 | }
76 | }
77 |
78 | /**
79 | * @param array $services
80 | */
81 | public function setServices($services)
82 | {
83 | $this->services = $services;
84 | }
85 |
86 | /**
87 | * Returns services settings declared in the authorization classes.
88 | * For perfomance reasons it uses cache to store settings array.
89 | *
90 | * @return \stdClass[] services settings.
91 | */
92 | public function getServices()
93 | {
94 | $services = false;
95 | if (!empty($this->cache) && Yii::$app->has($this->cache)) {
96 | /** @var $cache \yii\caching\Cache */
97 | $cache = Yii::$app->get($this->cache);
98 | $services = $cache->get('EAuth.services');
99 | }
100 |
101 | if (false === $services || !is_array($services)) {
102 | $services = [];
103 | foreach ($this->services as $service => $options) {
104 | /** @var $class ServiceBase */
105 | $class = $this->getIdentity($service);
106 | $services[$service] = (object)[
107 | 'id' => $class->getServiceName(),
108 | 'title' => $class->getServiceTitle(),
109 | 'type' => $class->getServiceType(),
110 | 'jsArguments' => $class->getJsArguments(),
111 | ];
112 | }
113 | if (isset($cache)) {
114 | $cache->set('EAuth.services', $services, $this->cacheExpire);
115 | }
116 | }
117 | return $services;
118 | }
119 |
120 | /**
121 | * @param bool $usePopup
122 | */
123 | public function setPopup($usePopup)
124 | {
125 | $this->popup = $usePopup;
126 | }
127 |
128 | /**
129 | * @return bool
130 | */
131 | public function getPopup()
132 | {
133 | return $this->popup;
134 | }
135 |
136 | /**
137 | * @param string|bool $cache
138 | */
139 | public function setCache($cache)
140 | {
141 | $this->cache = $cache;
142 | }
143 |
144 | /**
145 | * @return string|bool
146 | */
147 | public function getCache()
148 | {
149 | return $this->cache;
150 | }
151 |
152 | /**
153 | * @param int $cacheExpire
154 | */
155 | public function setCacheExpire($cacheExpire)
156 | {
157 | $this->cacheExpire = $cacheExpire;
158 | }
159 |
160 | /**
161 | * @return int
162 | */
163 | public function getCacheExpire()
164 | {
165 | return $this->cacheExpire;
166 | }
167 |
168 | /**
169 | * @param string $redirectWidget
170 | */
171 | public function setRedirectWidget($redirectWidget)
172 | {
173 | $this->redirectWidget = $redirectWidget;
174 | }
175 |
176 | /**
177 | * @return string
178 | */
179 | public function getRedirectWidget()
180 | {
181 | return $this->redirectWidget;
182 | }
183 |
184 | /**
185 | * @param array $config
186 | */
187 | public function setTokenStorage(array $config)
188 | {
189 | $this->tokenStorage = ArrayHelper::merge($this->tokenStorage, $config);
190 | }
191 |
192 | /**
193 | * @return array
194 | */
195 | public function getTokenStorage()
196 | {
197 | return $this->tokenStorage;
198 | }
199 |
200 | /**
201 | * @param array $config
202 | */
203 | public function setHttpClient(array $config)
204 | {
205 | $this->httpClient = ArrayHelper::merge($this->httpClient, $config);
206 | }
207 |
208 | /**
209 | * @return array
210 | */
211 | public function getHttpClient()
212 | {
213 | return $this->httpClient;
214 | }
215 |
216 | /**
217 | * Returns the settings of the service.
218 | *
219 | * @param string $service the service name.
220 | * @return \stdClass the service settings.
221 | * @throws ErrorException
222 | */
223 | protected function getService($service)
224 | {
225 | $service = strtolower($service);
226 | $services = $this->getServices();
227 | if (!isset($services[$service])) {
228 | throw new ErrorException(Yii::t('eauth', 'Undefined service name: {service}.', ['service' => $service]), 500);
229 | }
230 | return $services[$service];
231 | }
232 |
233 | /**
234 | * Returns the type of the service.
235 | *
236 | * @param string $service the service name.
237 | * @return string the service type.
238 | */
239 | public function getServiceType($service)
240 | {
241 | $service = $this->getService($service);
242 | return $service->type;
243 | }
244 |
245 | /**
246 | * Returns the service identity class.
247 | *
248 | * @param string $service the service name.
249 | * @return IAuthService the identity class.
250 | * @throws ErrorException
251 | */
252 | public function getIdentity($service)
253 | {
254 | $service = strtolower($service);
255 | if (!isset($this->services[$service])) {
256 | throw new ErrorException(Yii::t('eauth', 'Undefined service name: {service}.', ['service' => $service]), 500);
257 | }
258 | $service = $this->services[$service];
259 |
260 | $service['component'] = $this;
261 |
262 | /** @var $identity IAuthService */
263 | $identity = Yii::createObject($service);
264 | return $identity;
265 | }
266 |
267 | /**
268 | * Redirects to url. If the authorization dialog opened in the popup window,
269 | * it will be closed instead of redirect. Set $jsRedirect=true if you want
270 | * to redirect anyway.
271 | *
272 | * @param mixed $url url to redirect. Can be route or normal url. See {@link CHtml::normalizeUrl}.
273 | * @param boolean $jsRedirect whether to use redirect while popup window is used. Defaults to true.
274 | * @param array $params
275 | */
276 | public function redirect($url, $jsRedirect = true, $params = [])
277 | {
278 | /** @var RedirectWidget $widget */
279 | $widget = Yii::createObject([
280 | 'class' => $this->redirectWidget,
281 | 'url' => Url::to($url),
282 | 'redirect' => $jsRedirect,
283 | 'params' => $params
284 | ]);
285 | ob_start();
286 | $widget->run();
287 | $output = ob_get_clean();
288 | $response = Yii::$app->getResponse();
289 | $response->content = $output;
290 | $response->send();
291 | exit();
292 | }
293 |
294 | /**
295 | * Serialize the identity class.
296 | *
297 | * @param ServiceBase $identity the class instance.
298 | * @return string serialized value.
299 | */
300 | public function toString($identity)
301 | {
302 | return serialize($identity);
303 | }
304 |
305 | /**
306 | * Serialize the identity class.
307 | *
308 | * @param string $identity serialized value.
309 | * @return ServiceBase the class instance.
310 | */
311 | public function fromString($identity)
312 | {
313 | return unserialize($identity);
314 | }
315 |
316 | }
317 |
--------------------------------------------------------------------------------
/src/oauth2/Service.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth\oauth2;
11 |
12 | use Yii;
13 | use yii\helpers\Url;
14 | use OAuth\Common\Exception\Exception as OAuthException;
15 | use OAuth\Common\Http\Uri\Uri;
16 | use OAuth\Common\Consumer\Credentials;
17 | use OAuth\OAuth2\Service\ServiceInterface;
18 | use nodge\eauth\EAuth;
19 | use nodge\eauth\ErrorException;
20 | use nodge\eauth\IAuthService;
21 | use nodge\eauth\oauth\ServiceBase;
22 |
23 | /**
24 | * EOAuthService is a base class for all OAuth providers.
25 | *
26 | * @package application.extensions.eauth
27 | */
28 | abstract class Service extends ServiceBase implements IAuthService
29 | {
30 |
31 | /**
32 | * @var string OAuth2 client id.
33 | */
34 | protected $clientId;
35 |
36 | /**
37 | * @var string OAuth2 client secret key.
38 | */
39 | protected $clientSecret;
40 |
41 | /**
42 | * @var array OAuth scopes.
43 | */
44 | protected $scopes = [];
45 |
46 | /**
47 | * @var string
48 | */
49 | protected $scopeSeparator = ' ';
50 |
51 | /**
52 | * @var array Provider options. Must contain the keys: authorize, access_token.
53 | */
54 | protected $providerOptions = [
55 | 'authorize' => '',
56 | 'access_token' => '',
57 | ];
58 |
59 | /**
60 | * @var string Error key name in _GET options.
61 | */
62 | protected $errorParam = 'error';
63 |
64 | /**
65 | * @var string Error description key name in _GET options.
66 | */
67 | protected $errorDescriptionParam = 'error_description';
68 |
69 | /**
70 | * @var string Error code for access_denied response.
71 | */
72 | protected $errorAccessDeniedCode = 'access_denied';
73 |
74 | /**
75 | * @var string The display name for popup window. False to disable display mode.
76 | */
77 | protected $popupDisplayName = 'popup';
78 |
79 | /**
80 | * @var bool Whether to use the State param to improve security.
81 | */
82 | protected $validateState = true;
83 |
84 | /**
85 | * @var ServiceProxy
86 | */
87 | private $_proxy;
88 |
89 | /**
90 | * Initialize the component.
91 | *
92 | * @param EAuth $component the component instance.
93 | * @param array $options properties initialization.
94 | */
95 | // public function init($component, $options = []) {
96 | // parent::init($component, $options);
97 | // }
98 |
99 | /**
100 | * @param string $id
101 | */
102 | public function setClientId($id)
103 | {
104 | $this->clientId = $id;
105 | }
106 |
107 | /**
108 | * @param string $secret
109 | */
110 | public function setClientSecret($secret)
111 | {
112 | $this->clientSecret = $secret;
113 | }
114 |
115 | /**
116 | * @param string|array $scopes
117 | */
118 | public function setScope($scopes)
119 | {
120 | if (!is_array($scopes)) {
121 | $scopes = [$scopes];
122 | }
123 |
124 | $resolvedScopes = [];
125 | $reflClass = new \ReflectionClass($this);
126 | $constants = $reflClass->getConstants();
127 |
128 | foreach ($scopes as $scope) {
129 | $key = strtoupper('SCOPE_' . $scope);
130 |
131 | // try to find a class constant with this name
132 | if (array_key_exists($key, $constants)) {
133 | $resolvedScopes[] = $constants[$key];
134 | } else {
135 | $resolvedScopes[] = $scope;
136 | }
137 | }
138 |
139 | $this->scopes = $resolvedScopes;
140 | }
141 |
142 | /**
143 | * @param bool $validate
144 | */
145 | public function setValidateState($validate)
146 | {
147 | $this->validateState = $validate;
148 | }
149 |
150 | /**
151 | * @return bool
152 | */
153 | public function getValidateState()
154 | {
155 | return $this->validateState;
156 | }
157 |
158 | /**
159 | * @return ServiceProxy
160 | */
161 | protected function getProxy()
162 | {
163 | if (!isset($this->_proxy)) {
164 | $tokenStorage = $this->getTokenStorage();
165 | $httpClient = $this->getHttpClient();
166 | $credentials = new Credentials($this->clientId, $this->clientSecret, $this->getCallbackUrl());
167 | $this->_proxy = new ServiceProxy($credentials, $httpClient, $tokenStorage, $this->scopes, null, $this);
168 | }
169 | return $this->_proxy;
170 | }
171 |
172 | /**
173 | * @return string the current url
174 | */
175 | protected function getCallbackUrl()
176 | {
177 | if (isset($_GET['redirect_uri'])) {
178 | $url = $_GET['redirect_uri'];
179 | }
180 | else {
181 | $route = Yii::$app->getRequest()->getQueryParams();
182 | array_unshift($route, '');
183 |
184 | // Can not use these params in OAuth2 callbacks
185 | foreach (['code', 'state', 'redirect_uri'] as $param) {
186 | if (isset($route[$param])) {
187 | unset($route[$param]);
188 | }
189 | }
190 |
191 | $url = Url::to($route, true);
192 | }
193 |
194 | return $url;
195 | }
196 |
197 | /**
198 | * Authenticate the user.
199 | *
200 | * @return boolean whether user was successfuly authenticated.
201 | * @throws ErrorException
202 | */
203 | public function authenticate()
204 | {
205 | if (!$this->checkError()) {
206 | return false;
207 | }
208 |
209 | try {
210 | $proxy = $this->getProxy();
211 |
212 | if (!empty($_GET['code'])) {
213 | // This was a callback request from a service, get the token
214 | $proxy->requestAccessToken($_GET['code']);
215 | $this->authenticated = true;
216 | } else if ($proxy->hasValidAccessToken()) {
217 | $this->authenticated = true;
218 | } else {
219 | /** @var $url Uri */
220 | $url = $proxy->getAuthorizationUri();
221 | Yii::$app->getResponse()->redirect($url->getAbsoluteUri())->send();
222 | }
223 | } catch (OAuthException $e) {
224 | throw new ErrorException($e->getMessage(), $e->getCode(), 1, $e->getFile(), $e->getLine(), $e);
225 | }
226 |
227 | return $this->getIsAuthenticated();
228 | }
229 |
230 | /**
231 | * Check request params for error code and message.
232 | *
233 | * @return bool
234 | * @throws ErrorException
235 | */
236 | protected function checkError()
237 | {
238 | if (isset($_GET[$this->errorParam])) {
239 | $error_code = $_GET[$this->errorParam];
240 | if ($error_code === $this->errorAccessDeniedCode) {
241 | // access_denied error (user canceled)
242 | $this->cancel();
243 | } else {
244 | $error = $error_code;
245 | if (isset($_GET[$this->errorDescriptionParam])) {
246 | $error = $_GET[$this->errorDescriptionParam] . ' (' . $error . ')';
247 | }
248 | throw new ErrorException($error);
249 | }
250 | return false;
251 | }
252 |
253 | return true;
254 | }
255 |
256 | /**
257 | * @return string
258 | */
259 | public function getAuthorizationEndpoint()
260 | {
261 | $url = $this->providerOptions['authorize'];
262 | if ($this->popupDisplayName !== false && $this->getIsInsidePopup()) {
263 | $url = new Uri($url);
264 | $url->addToQuery('display', $this->popupDisplayName);
265 | $url = $url->getAbsoluteUri();
266 | }
267 | return $url;
268 | }
269 |
270 | /**
271 | * @return string
272 | */
273 | public function getAccessTokenEndpoint()
274 | {
275 | return $this->providerOptions['access_token'];
276 | }
277 |
278 | /**
279 | * @param string $response
280 | * @return array
281 | */
282 | public function parseAccessTokenResponse($response)
283 | {
284 | return json_decode($response, true);
285 | }
286 |
287 | /**
288 | * @return array
289 | */
290 | public function getAccessTokenArgumentNames()
291 | {
292 | return [
293 | 'access_token' => 'access_token',
294 | 'expires_in' => 'expires_in',
295 | 'refresh_token' => 'refresh_token',
296 | ];
297 | }
298 |
299 | /**
300 | * Return any additional headers always needed for this service implementation's OAuth calls.
301 | *
302 | * @return array
303 | */
304 | public function getExtraOAuthHeaders()
305 | {
306 | return [];
307 | }
308 |
309 | /**
310 | * Returns a class constant from ServiceInterface defining the authorization method used for the API
311 | * Header is the sane default.
312 | *
313 | * @return int
314 | */
315 | public function getAuthorizationMethod()
316 | {
317 | return ServiceInterface::AUTHORIZATION_METHOD_HEADER_OAUTH;
318 | }
319 |
320 | /**
321 | * @return string
322 | */
323 | public function getScopeSeparator()
324 | {
325 | return $this->scopeSeparator;
326 | }
327 | }
--------------------------------------------------------------------------------
/src/ServiceBase.php:
--------------------------------------------------------------------------------
1 |
6 | * @link http://github.com/Nodge/yii2-eauth/
7 | * @license http://www.opensource.org/licenses/bsd-license.php
8 | */
9 |
10 | namespace nodge\eauth;
11 |
12 | use Yii;
13 | use yii\base\Object;
14 | use yii\helpers\Url;
15 | use yii\helpers\ArrayHelper;
16 | use OAuth\Common\Http\Uri\Uri;
17 | use OAuth\Common\Http\Client\ClientInterface;
18 |
19 | /**
20 | * EAuthServiceBase is a base class for providers.
21 | *
22 | * @package application.extensions.eauth
23 | */
24 | abstract class ServiceBase extends Object implements IAuthService
25 | {
26 |
27 | /**
28 | * @var string the service name.
29 | */
30 | protected $name;
31 |
32 | /**
33 | *
34 | * @var string the service title to display in views.
35 | */
36 | protected $title;
37 |
38 | /**
39 | * @var string the service type (e.g. OpenID, OAuth).
40 | */
41 | protected $type;
42 |
43 | /**
44 | * @var array arguments for the jQuery.eauth() javascript function.
45 | */
46 | protected $jsArguments = [];
47 |
48 | /**
49 | * @var array authorization attributes.
50 | * @see getAttribute
51 | * @see getItem
52 | */
53 | protected $attributes = [];
54 |
55 | /**
56 | * @var boolean whether user was successfuly authenticated.
57 | * @see getIsAuthenticated
58 | */
59 | protected $authenticated = false;
60 |
61 | /**
62 | * @var array HttpClient class. Null means default value from EAuth component config.
63 | */
64 | protected $httpClient;
65 |
66 | /**
67 | * @var boolean whether is attributes was fetched.
68 | */
69 | private $fetched = false;
70 |
71 | /**
72 | * @var EAuth the {@link EAuth} application component.
73 | */
74 | private $component;
75 |
76 | /**
77 | * @var string the redirect url after successful authorization.
78 | */
79 | private $redirectUrl = '';
80 |
81 | /**
82 | * @var string the redirect url after unsuccessful authorization (e.g. user canceled).
83 | */
84 | private $cancelUrl = '';
85 |
86 | /**
87 | * @var ClientInterface
88 | */
89 | private $_httpClient;
90 |
91 | /**
92 | * PHP getter magic method.
93 | * This method is overridden so that service attributes can be accessed like properties.
94 | *
95 | * @param string $name property name.
96 | * @return mixed property value.
97 | * @see getAttribute
98 | */
99 | public function __get($name)
100 | {
101 | if ($this->hasAttribute($name)) {
102 | return $this->getAttribute($name);
103 | } else {
104 | return parent::__get($name);
105 | }
106 | }
107 |
108 | /**
109 | * Checks if a attribute value is null.
110 | * This method overrides the parent implementation by checking
111 | * if the attribute is null or not.
112 | *
113 | * @param string $name the attribute name.
114 | * @return boolean whether the attribute value is null.
115 | */
116 | public function __isset($name)
117 | {
118 | if ($this->hasAttribute($name)) {
119 | return true;
120 | } else {
121 | return parent::__isset($name);
122 | }
123 | }
124 |
125 | /**
126 | * Initialize the component.
127 | * Sets the default {@link redirectUrl} and {@link cancelUrl}.
128 | */
129 | public function init()
130 | {
131 | parent::init();
132 |
133 | $this->setRedirectUrl(Yii::$app->getUser()->getReturnUrl());
134 |
135 | $service = Yii::$app->getRequest()->getQueryParam('service');
136 | $cancelUrl = Url::to(['', 'service' => $service], true);
137 |
138 | $this->setCancelUrl($cancelUrl);
139 | }
140 |
141 | /**
142 | * Returns service name(id).
143 | *
144 | * @return string the service name(id).
145 | */
146 | public function getServiceName()
147 | {
148 | return $this->name;
149 | }
150 |
151 | /**
152 | * Returns service title.
153 | *
154 | * @return string the service title.
155 | */
156 | public function getServiceTitle()
157 | {
158 | return Yii::t('eauth', $this->title);
159 | }
160 |
161 | /**
162 | * Returns service type (e.g. OpenID, OAuth).
163 | *
164 | * @return string the service type (e.g. OpenID, OAuth).
165 | */
166 | public function getServiceType()
167 | {
168 | return $this->type;
169 | }
170 |
171 | /**
172 | * Returns arguments for the jQuery.eauth() javascript function.
173 | *
174 | * @return array the arguments for the jQuery.eauth() javascript function.
175 | */
176 | public function getJsArguments()
177 | {
178 | return $this->jsArguments;
179 | }
180 |
181 | /**
182 | * Sets {@link EAuth} application component
183 | *
184 | * @param EAuth $component the application auth component.
185 | */
186 | public function setComponent($component)
187 | {
188 | $this->component = $component;
189 | }
190 |
191 | /**
192 | * Returns the {@link EAuth} application component.
193 | *
194 | * @return EAuth the {@link EAuth} application component.
195 | */
196 | public function getComponent()
197 | {
198 | return $this->component;
199 | }
200 |
201 | /**
202 | * Sets redirect url after successful authorization.
203 | *
204 | * @param string $url to redirect.
205 | */
206 | public function setRedirectUrl($url)
207 | {
208 | $this->redirectUrl = $url;
209 | }
210 |
211 | /**
212 | * @return string the redirect url after successful authorization.
213 | */
214 | public function getRedirectUrl()
215 | {
216 | return $this->redirectUrl;
217 | }
218 |
219 | /**
220 | * Sets redirect url after unsuccessful authorization (e.g. user canceled).
221 | *
222 | * @param string $url
223 | */
224 | public function setCancelUrl($url)
225 | {
226 | $this->cancelUrl = $url;
227 | }
228 |
229 | /**
230 | * @return string the redirect url after unsuccessful authorization (e.g. user canceled).
231 | */
232 | public function getCancelUrl()
233 | {
234 | return $this->cancelUrl;
235 | }
236 |
237 | /**
238 | * @param string $title
239 | */
240 | public function setTitle($title)
241 | {
242 | $this->title = $title;
243 | }
244 |
245 | /**
246 | * Authenticate the user.
247 | *
248 | * @return boolean whether user was successfuly authenticated.
249 | */
250 | public function authenticate()
251 | {
252 | return $this->getIsAuthenticated();
253 | }
254 |
255 | /**
256 | * Whether user was successfuly authenticated.
257 | *
258 | * @return boolean whether user was successfuly authenticated.
259 | */
260 | public function getIsAuthenticated()
261 | {
262 | return $this->authenticated;
263 | }
264 |
265 | /**
266 | * Redirect to the url. If url is null, {@link redirectUrl} will be used.
267 | *
268 | * @param string $url url to redirect.
269 | * @param array $params
270 | */
271 | public function redirect($url = null, $params = [])
272 | {
273 | $this->component->redirect(isset($url) ? $url : $this->redirectUrl, true, $params);
274 | }
275 |
276 | /**
277 | * Redirect to the {@link cancelUrl} or simply close the popup window.
278 | */
279 | public function cancel($url = null)
280 | {
281 | $this->component->redirect(isset($url) ? $url : $this->cancelUrl, !$this->component->popup);
282 | }
283 |
284 | /**
285 | * Fetch attributes array.
286 | *
287 | * @return boolean whether the attributes was successfully fetched.
288 | */
289 | protected function fetchAttributes()
290 | {
291 | return true;
292 | }
293 |
294 | /**
295 | * Fetch attributes array.
296 | * This function is internally used to handle fetched state.
297 | */
298 | protected function _fetchAttributes()
299 | {
300 | if (!$this->fetched) {
301 | $this->fetched = true;
302 | $result = $this->fetchAttributes();
303 | if (isset($result)) {
304 | $this->fetched = $result;
305 | }
306 | }
307 | }
308 |
309 | /**
310 | * Returns the user unique id.
311 | *
312 | * @return mixed the user id.
313 | */
314 | public function getId()
315 | {
316 | $this->_fetchAttributes();
317 | return $this->attributes['id'];
318 | }
319 |
320 | /**
321 | * Returns the array that contains all available authorization attributes.
322 | *
323 | * @return array the attributes.
324 | */
325 | public function getAttributes()
326 | {
327 | $this->_fetchAttributes();
328 | $attributes = [];
329 | foreach ($this->attributes as $key => $val) {
330 | $attributes[$key] = $this->getAttribute($key);
331 | }
332 | return $attributes;
333 | }
334 |
335 | /**
336 | * Returns the authorization attribute value.
337 | *
338 | * @param string $key the attribute name.
339 | * @param mixed $default the default value.
340 | * @return mixed the attribute value.
341 | */
342 | public function getAttribute($key, $default = null)
343 | {
344 | $this->_fetchAttributes();
345 | $getter = 'get' . $key;
346 | if (method_exists($this, $getter)) {
347 | return $this->$getter();
348 | } else {
349 | return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
350 | }
351 | }
352 |
353 | /**
354 | * Whether the authorization attribute exists.
355 | *
356 | * @param string $key the attribute name.
357 | * @return boolean true if attribute exists, false otherwise.
358 | */
359 | public function hasAttribute($key)
360 | {
361 | $this->_fetchAttributes();
362 | return isset($this->attributes[$key]);
363 | }
364 |
365 | /**
366 | * @return bool
367 | */
368 | public function getIsInsidePopup()
369 | {
370 | return isset($_GET['js']);
371 | }
372 |
373 | /**
374 | * @return ClientInterface
375 | */
376 | protected function getHttpClient()
377 | {
378 | if (!isset($this->_httpClient)) {
379 | $config = $this->httpClient;
380 | if (!isset($config)) {
381 | $config = $this->getComponent()->getHttpClient();
382 | }
383 | $this->_httpClient = Yii::createObject($config);
384 | }
385 | return $this->_httpClient;
386 | }
387 |
388 | /**
389 | * @param array $config
390 | */
391 | public function setHttpClient(array $config)
392 | {
393 | $this->httpClient = ArrayHelper::merge($this->httpClient, $config);
394 | }
395 |
396 | /**
397 | * Returns the public resource.
398 | *
399 | * @param string $url url to request.
400 | * @param array $options HTTP request options. Keys: query, data, headers.
401 | * @param boolean $parseResponse Whether to parse response.
402 | * @return mixed the response.
403 | * @throws ErrorException
404 | */
405 | public function makeRequest($url, $options = [], $parseResponse = true)
406 | {
407 | return $this->request($url, $options, $parseResponse, function ($url, $method, $headers, $data) {
408 | return $this->getHttpClient()->retrieveResponse($url, $data, $headers, $method);
409 | });
410 | }
411 |
412 | /**
413 | * @param string $url
414 | * @param array $options
415 | * @param boolean $parseResponse
416 | * @param callable $fn
417 | * @return mixed
418 | * @throws ErrorException
419 | */
420 | protected function request($url, $options, $parseResponse, $fn)
421 | {
422 | if (stripos($url, 'http') !== 0) {
423 | $url = $this->baseApiUrl . $url;
424 | }
425 |
426 | $url = new Uri($url);
427 | if (isset($options['query'])) {
428 | foreach ($options['query'] as $key => $value) {
429 | $url->addToQuery($key, $value);
430 | }
431 | }
432 |
433 | $data = isset($options['data']) ? $options['data'] : [];
434 | $method = !empty($data) ? 'POST' : 'GET';
435 | $headers = isset($options['headers']) ? $options['headers'] : [];
436 |
437 | $response = $fn($url, $method, $headers, $data);
438 |
439 | if ($parseResponse) {
440 | $response = $this->parseResponseInternal($response);
441 | }
442 |
443 | return $response;
444 | }
445 |
446 | /**
447 | * Parse response and check for errors.
448 | *
449 | * @param string $response
450 | * @return mixed
451 | * @throws ErrorException
452 | */
453 | protected function parseResponseInternal($response)
454 | {
455 | try {
456 | $result = $this->parseResponse($response);
457 | if (!isset($result)) {
458 | throw new ErrorException(Yii::t('eauth', 'Invalid response format.'), 500);
459 | }
460 |
461 | $error = $this->fetchResponseError($result);
462 | if (isset($error) && !empty($error['message'])) {
463 | throw new ErrorException($error['message'], $error['code']);
464 | }
465 |
466 | return $result;
467 | } catch (\Exception $e) {
468 | throw new ErrorException($e->getMessage(), $e->getCode());
469 | }
470 | }
471 |
472 | /**
473 | * @param string $response
474 | * @return mixed
475 | */
476 | protected function parseResponse($response)
477 | {
478 | return json_decode($response, true);
479 | }
480 |
481 | /**
482 | * Returns the error array.
483 | *
484 | * @param array $response
485 | * @return array the error array with 2 keys: code and message. Should be null if no errors.
486 | */
487 | protected function fetchResponseError($response)
488 | {
489 | if (isset($response['error'])) {
490 | return [
491 | 'code' => 500,
492 | 'message' => 'Unknown error occurred.',
493 | ];
494 | }
495 | return null;
496 | }
497 | }
498 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yii2 EAuth extension
2 | ====================
3 |
4 | EAuth extension allows to authenticate users with accounts on other websites.
5 | Supported protocols: OpenID, OAuth 1.0 and OAuth 2.0.
6 |
7 | 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.
8 |
9 | * [Demo](http://nodge.ru/yii-eauth/demo2/)
10 | * [Demo project](https://github.com/Nodge/yii2-eauth-demo/)
11 | * [Installation](#installation)
12 | * [Version for yii 1.1](https://github.com/Nodge/yii-eauth/)
13 |
14 | ### Why own extension and not a third-party service?
15 | The implementation of the authorization on your own server has several advantages:
16 |
17 | * Full control over the process: What will be written in the authorization window, what data we get, etc.
18 | * Ability to change the appearance of the widget.
19 | * When logging in via OAuth, it is possible to invoke methods on the API.
20 | * Fewer dependencies on third-party services - more reliable application.
21 |
22 |
23 | ### The extension allows you to:
24 |
25 | * Ignore the nuances of authorization through the different types of services and use the class based adapters for each service.
26 | * Get a unique user ID that can be used to register the user in your application.
27 | * Extend the standard authorization classes to obtain additional data about the user.
28 | * Work with the API of social networks by extending the authorization classes.
29 | * Set up a list of supported services, customize the appearance of the widget, use the popup window without closing your application.
30 |
31 |
32 | ### Extension includes:
33 |
34 | * The component that contains utility functions.
35 | * A widget that displays a list of services in the form of icons and allowing authorization in the popup window.
36 | * Base classes to create your own services.
37 | * Ready to authenticate via Google, Twitter, Facebook and other providers.
38 |
39 |
40 | ### Included services:
41 |
42 | * OpenID:
43 | * Yahoo
44 | * Steam
45 | * OAuth1:
46 | * Twitter
47 | * LinkedIn
48 | * OAuth2:
49 | * Google
50 | * Facebook
51 | * Live
52 | * GitHub
53 | * LinkedIn
54 | * Instagram
55 | * Yandex (ru)
56 | * VKontake (ru)
57 | * Mail.ru (ru)
58 | * Odnoklassniki (ru)
59 |
60 |
61 | ### Resources
62 |
63 | * [Yii EAuth](https://github.com/Nodge/yii2-eauth)
64 | * [Demo](http://nodge.ru/yii-eauth/demo2/)
65 | * [Demo project](https://github.com/Nodge/yii2-eauth-demo/)
66 | * [Yii Framework](http://yiiframework.com/)
67 | * [OpenID](http://openid.net/)
68 | * [OAuth](http://oauth.net/)
69 | * [OAuth 2.0](http://oauth.net/2/)
70 | * [LightOpenID](https://github.com/iignatov/LightOpenID)
71 | * [PHPoAuthLib](https://github.com/Lusitanian/PHPoAuthLib)
72 |
73 |
74 | ### Requirements
75 |
76 | * Yii 2.0 or above
77 | * curl php extension
78 | * LightOpenId
79 | * PHPoAuthLib
80 |
81 |
82 | # Installation
83 |
84 | This library can be found on [Packagist](https://packagist.org/packages/nodge/yii2-eauth).
85 | The recommended way to install this is through [composer](http://getcomposer.org).
86 |
87 | Edit your `composer.json` and add:
88 |
89 | ```json
90 | {
91 | "require": {
92 | "nodge/yii2-eauth": "~2.0"
93 | }
94 | }
95 | ```
96 |
97 | And install dependencies:
98 |
99 | ```bash
100 | $ curl -sS https://getcomposer.org/installer | php
101 | $ php composer.phar install
102 | ```
103 |
104 |
105 | # Usage
106 |
107 | ## Demo project
108 |
109 | The source code of the [demo](http://nodge.ru/yii-eauth/demo2/) is available [here](https://github.com/Nodge/yii2-eauth-demo/).
110 |
111 |
112 | ## Basic setup
113 |
114 | ### Configuration
115 |
116 | Add the following in your config:
117 |
118 | ```php
119 | [
122 | 'eauth' => [
123 | 'class' => 'nodge\eauth\EAuth',
124 | 'popup' => true, // Use the popup window instead of redirecting.
125 | 'cache' => false, // Cache component name or false to disable cache. Defaults to 'cache' on production environments.
126 | 'cacheExpire' => 0, // Cache lifetime. Defaults to 0 - means unlimited.
127 | 'httpClient' => [
128 | // uncomment this to use streams in safe_mode
129 | //'useStreamsFallback' => true,
130 | ],
131 | 'services' => [ // You can change the providers and their classes.
132 | 'google' => [
133 | // register your app here: https://code.google.com/apis/console/
134 | 'class' => 'nodge\eauth\services\GoogleOAuth2Service',
135 | 'clientId' => '...',
136 | 'clientSecret' => '...',
137 | 'title' => 'Google',
138 | ],
139 | 'twitter' => [
140 | // register your app here: https://dev.twitter.com/apps/new
141 | 'class' => 'nodge\eauth\services\TwitterOAuth1Service',
142 | 'key' => '...',
143 | 'secret' => '...',
144 | ],
145 | 'yandex' => [
146 | // register your app here: https://oauth.yandex.ru/client/my
147 | 'class' => 'nodge\eauth\services\YandexOAuth2Service',
148 | 'clientId' => '...',
149 | 'clientSecret' => '...',
150 | 'title' => 'Yandex',
151 | ],
152 | 'facebook' => [
153 | // register your app here: https://developers.facebook.com/apps/
154 | 'class' => 'nodge\eauth\services\FacebookOAuth2Service',
155 | 'clientId' => '...',
156 | 'clientSecret' => '...',
157 | ],
158 | 'yahoo' => [
159 | 'class' => 'nodge\eauth\services\YahooOpenIDService',
160 | //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
161 | ],
162 | 'linkedin' => [
163 | // register your app here: https://www.linkedin.com/secure/developer
164 | 'class' => 'nodge\eauth\services\LinkedinOAuth1Service',
165 | 'key' => '...',
166 | 'secret' => '...',
167 | 'title' => 'LinkedIn (OAuth1)',
168 | ],
169 | 'linkedin_oauth2' => [
170 | // register your app here: https://www.linkedin.com/secure/developer
171 | 'class' => 'nodge\eauth\services\LinkedinOAuth2Service',
172 | 'clientId' => '...',
173 | 'clientSecret' => '...',
174 | 'title' => 'LinkedIn (OAuth2)',
175 | ],
176 | 'github' => [
177 | // register your app here: https://github.com/settings/applications
178 | 'class' => 'nodge\eauth\services\GitHubOAuth2Service',
179 | 'clientId' => '...',
180 | 'clientSecret' => '...',
181 | ],
182 | 'live' => [
183 | // register your app here: https://account.live.com/developers/applications/index
184 | 'class' => 'nodge\eauth\services\LiveOAuth2Service',
185 | 'clientId' => '...',
186 | 'clientSecret' => '...',
187 | ],
188 | 'steam' => [
189 | 'class' => 'nodge\eauth\services\SteamOpenIDService',
190 | //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
191 | 'apiKey' => '...', // Optional. You can get it here: https://steamcommunity.com/dev/apikey
192 | ],
193 | 'instagram' => [
194 | // register your app here: https://instagram.com/developer/register/
195 | 'class' => 'nodge\eauth\services\InstagramOAuth2Service',
196 | 'clientId' => '...',
197 | 'clientSecret' => '...',
198 | ],
199 | 'vkontakte' => [
200 | // register your app here: https://vk.com/editapp?act=create&site=1
201 | 'class' => 'nodge\eauth\services\VKontakteOAuth2Service',
202 | 'clientId' => '...',
203 | 'clientSecret' => '...',
204 | ],
205 | 'mailru' => [
206 | // register your app here: http://api.mail.ru/sites/my/add
207 | 'class' => 'nodge\eauth\services\MailruOAuth2Service',
208 | 'clientId' => '...',
209 | 'clientSecret' => '...',
210 | ],
211 | 'odnoklassniki' => [
212 | // register your app here: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
213 | // ... or here: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
214 | 'class' => 'nodge\eauth\services\OdnoklassnikiOAuth2Service',
215 | 'clientId' => '...',
216 | 'clientSecret' => '...',
217 | 'clientPublic' => '...',
218 | 'title' => 'Odnoklas.',
219 | ],
220 | ],
221 | ],
222 |
223 | 'i18n' => [
224 | 'translations' => [
225 | 'eauth' => [
226 | 'class' => 'yii\i18n\PhpMessageSource',
227 | 'basePath' => '@eauth/messages',
228 | ],
229 | ],
230 | ],
231 |
232 | // (optionally) you can configure pretty urls
233 | 'urlManager' => [
234 | 'enablePrettyUrl' => true,
235 | 'showScriptName' => false,
236 | 'rules' => [
237 | 'login/' => 'site/login',
238 | ],
239 | ],
240 |
241 | // (optionally) you can configure logging
242 | 'log' => [
243 | 'targets' => [
244 | [
245 | 'class' => 'yii\log\FileTarget',
246 | 'logFile' => '@app/runtime/logs/eauth.log',
247 | 'categories' => ['nodge\eauth\*'],
248 | 'logVars' => [],
249 | ],
250 | ],
251 | ],
252 | ...
253 | ],
254 | ...
255 | ```
256 |
257 | ### User model
258 |
259 | You need to modify your User model to login with EAuth services.
260 | Example from demo project:
261 |
262 | ```php
263 | getSession()->has('user-'.$id)) {
272 | return new self(Yii::$app->getSession()->get('user-'.$id));
273 | }
274 | else {
275 | return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
276 | }
277 | }
278 |
279 | /**
280 | * @param \nodge\eauth\ServiceBase $service
281 | * @return User
282 | * @throws ErrorException
283 | */
284 | public static function findByEAuth($service) {
285 | if (!$service->getIsAuthenticated()) {
286 | throw new ErrorException('EAuth user should be authenticated before creating identity.');
287 | }
288 |
289 | $id = $service->getServiceName().'-'.$service->getId();
290 | $attributes = [
291 | 'id' => $id,
292 | 'username' => $service->getAttribute('name'),
293 | 'authKey' => md5($id),
294 | 'profile' => $service->getAttributes(),
295 | ];
296 | $attributes['profile']['service'] = $service->getServiceName();
297 | Yii::$app->getSession()->set('user-'.$id, $attributes);
298 | return new self($attributes);
299 | }
300 | ...
301 | ```
302 |
303 | Then you can access to EAuth attributes through:
304 |
305 | ```php
306 | getUser()->getIdentity();
308 | if (isset($identity->profile)) {
309 | VarDumper::dump($identity->profile, 10, true);
310 | }
311 | ```
312 |
313 | ### Controller
314 |
315 | Attach OpenID Controller behavior to disable CSRF validation for OpenID callbacks.
316 | Or you can disable CSRF validation by yourself.
317 |
318 | ```php
319 | [
324 | // required to disable csrf validation on OpenID requests
325 | 'class' => \nodge\eauth\openid\ControllerBehavior::className(),
326 | 'only' => ['login'],
327 | ],
328 | ];
329 | }
330 | ...
331 | ```
332 |
333 | Add the following to your Login action:
334 |
335 | ```php
336 | getRequest()->getQueryParam('service');
340 | if (isset($serviceName)) {
341 | /** @var $eauth \nodge\eauth\ServiceBase */
342 | $eauth = Yii::$app->get('eauth')->getIdentity($serviceName);
343 | $eauth->setRedirectUrl(Yii::$app->getUser()->getReturnUrl());
344 | $eauth->setCancelUrl(Yii::$app->getUrlManager()->createAbsoluteUrl('site/login'));
345 |
346 | try {
347 | if ($eauth->authenticate()) {
348 | // var_dump($eauth->getIsAuthenticated(), $eauth->getAttributes()); exit;
349 |
350 | $identity = User::findByEAuth($eauth);
351 | Yii::$app->getUser()->login($identity);
352 |
353 | // special redirect with closing popup window
354 | $eauth->redirect();
355 | }
356 | else {
357 | // close popup window and redirect to cancelUrl
358 | $eauth->cancel();
359 | }
360 | }
361 | catch (\nodge\eauth\ErrorException $e) {
362 | // save error to show it later
363 | Yii::$app->getSession()->setFlash('error', 'EAuthException: '.$e->getMessage());
364 |
365 | // close popup window and redirect to cancelUrl
366 | // $eauth->cancel();
367 | $eauth->redirect($eauth->getCancelUrl());
368 | }
369 | }
370 |
371 | // default authorization code through login/password ..
372 | }
373 | ...
374 | ```
375 |
376 | ### View
377 |
378 | ```php
379 | ...
380 | getSession()->hasFlash('error')) {
382 | echo ''.Yii::$app->getSession()->getFlash('error').'
';
383 | }
384 | ?>
385 | ...
386 | Do you already have an account on one of these sites? Click the logo to log in with it here:
387 | 'site/login']); ?>
388 | ...
389 | ```
390 |
391 |
392 | ## Extending
393 |
394 | To receive all the necessary data to your application, you can override the base class of any provider.
395 | Base classes are stored in `@eauth/src/services`.
396 | Examples of extended classes can be found in `@eauth/src/services/extended/`.
397 |
398 | After overriding the base class, you need to update your configuration file with a new class name.
399 |
400 |
401 | ## Working with OAuth API
402 |
403 | You can extend base classes with necessary methods and then write something like this:
404 |
405 | ```php
406 | eauth->getIdentity('facebook');
409 |
410 | // to get protected resources user should be authenticated:
411 | if ($eauth->getIsAuthenticated()) {
412 | $eauth->callProtectedApiMethod();
413 | $eauth->callAnotherProtectedApiMethod();
414 | }
415 |
416 | // or you can get public resources at any time:
417 | $eauth->callPublicApiMethod();
418 | $eauth->callAnotherPublicApiMethod();
419 | ```
420 |
421 | Example of an API call method:
422 |
423 | ```php
424 | makeSignedRequest($api_method, [
432 | 'query' => [ 'foo' => 'bar' ], // GET arguments
433 | 'data' => [ 'foo' => 'bar' ], // POST arguments
434 | 'headers' => [ 'X-Foo' => 'bar' ], // Extra HTTP headers
435 | ]);
436 |
437 | // you can get public resources with the same API:
438 | //$response = $this->makeRequest($api_method, $options);
439 |
440 | // process $response
441 | $data = process($response);
442 |
443 | // return results
444 | return $data;
445 | }
446 | }
447 | ```
448 |
449 | API calls are performed if the current user has a valid access token (saved during the authentication).
450 | You can save access_token to your database by using custom token storage in your config:
451 |
452 | ```php
453 | [
456 | 'eauth' => [
457 | 'class' => 'nodge\eauth\EAuth',
458 | 'tokenStorage' => [
459 | 'class' => '@app\eauth\DatabaseTokenStorage',
460 | ],
461 | ],
462 | ...
463 | ],
464 | ...
465 | ```
466 |
467 |
468 | ## Translation
469 |
470 | To use translations, add the following in your config:
471 |
472 | ```php
473 | [
476 | 'i18n' => [
477 | 'translations' => [
478 | 'eauth' => [
479 | 'class' => 'yii\i18n\PhpMessageSource',
480 | 'basePath' => '@eauth/messages',
481 | ],
482 | ],
483 | ],
484 | ...
485 | ],
486 | ...
487 | ```
488 |
489 | Available translations can be found in `@eauth/src/messages`.
490 |
491 |
492 | # License
493 |
494 | The extension was released under the [New BSD License](http://www.opensource.org/licenses/bsd-license.php), so you'll find the latest version on [GitHub](https://github.com/Nodge/yii2-eauth).
495 |
--------------------------------------------------------------------------------