Commit f91c1ae8773352ce6a24131a9a83ba59bdc73b40

Authored by Dmitryi
1 parent bb1ff629

new commit components

Компонент авторизации через соц сети вынес в папку common
Showing 76 changed files with 7942 additions and 18 deletions   Show diff stats
common/components/nodge/eauth/.gitignore 0 → 100644
  1 +vendor
  2 +composer.lock
  3 +composer.phar
0 4 \ No newline at end of file
... ...
common/components/nodge/eauth/CHANGELOG.md 0 → 100644
  1 +Yii2 EAuth Change Log
  2 +=====================
  3 +
  4 +### 2.3.0 (17.10.2015)
  5 +* Added InstagramOAuth2Service (#61)
  6 +* Fixed default token lifetime (#53)
  7 +* Replace array() with [] (#54)
  8 +* Remove deprecated Google OpenID service (#56)
  9 +* Remove deprecated Yandex OpenID service
  10 +
  11 +### 2.2.4 (27.07.2015)
  12 +* Fixed typo in `oauth2/Service.php` (#34)
  13 +* Added German translation
  14 +* Added `email` attribute to `LinkedinOAuth2Service.php`
  15 +
  16 +### 2.2.3 (15.07.2014)
  17 +* Added ability to call public api methods (without access token) (#28)
  18 +
  19 +### 2.2.2 (15.07.2014)
  20 +* Fixed wrong redirect_uri when popup is used
  21 +
  22 +### 2.2.1 (25.04.2014)
  23 +* Fix missing query params in callback urls (#26)
  24 +* Follow Yii2 code style
  25 +
  26 +### 2.2.0 (19.04.2014)
  27 +* Support for PHPoAuthLib v0.3 (#22)
  28 +* Support for Yii2 beta
  29 +* Internal state implementation replaced to PHPoAuthLib storage
  30 +
  31 +### 2.1.5 (24.03.2014)
  32 +* Fixed Yii2 refactor (#17)
  33 +* PSR-4
  34 +
  35 +### 2.1.4 (11.03.2014)
  36 +* Fixed wrong callbackUrl in oauth\ServiceBase when UrlManager uses prettyUrl=false and showScript=false (#12)
  37 +* Fixed Yii::t() calls according to Yii2 i18n Named Placeholders (#14)
  38 +* Fixed Yii2 refactor #2630 (#15)
  39 +
  40 +### 2.1.3 (30.01.2014)
  41 +* Yii2 update (Request methods has been refactored).
  42 +
  43 +### 2.1.2 (17.01.2014)
  44 +* Fixed typo in oauth2\ServiceProxy
  45 +
  46 +### 2.1.1 (07.01.2014)
  47 +* Fixed scope validation for OAuth services.
  48 +
  49 +### 2.1.0 (22.12.2013)
  50 +* Reorganize project with new namespace.
  51 +* Assets bundle has been moved.
  52 +* Fixed typo in HttpClient (#8).
  53 +* Added default User-Agent header to HttpClient.
  54 +* Disabled CSRF validation for OpenID callbacks.
  55 +* Optimized icons file.
  56 +* Added SteamOpenIDService.
  57 +* Improved redirect widget.
  58 +
  59 +### 2.0.3 (26.10.2013)
  60 +* Fixed redirect_uri when not using url rule (#2).
  61 +* Fixed hasValidAccessToken() method for OAuth1 services (#3).
  62 +* Fixed auto login cookie (#4).
  63 +
  64 +### 2.0.2 (12.10.2013)
  65 +* Fixed ServiceProxy constructor to match its interface (#1).
  66 +* Added HttpClient with logging support and curl/streams fallback.
  67 +* TokenStorage and HttpClient are configurable now.
  68 +
  69 +### 2.0.1 (08.09.2013)
  70 +* Fixed package versions in the composer.json.
  71 +* Fixed directories names.
  72 +* Added support for custom scope separator in OAuth2 services.
  73 +* Added support for additional headers for OAuth2 requests.
  74 +* Added method to get error from access token response.
  75 +* Added GitHubOAuth2Service.
  76 +* Added LinkedinOAuth2Service.
  77 +* Added MailruOAuth2Service.
  78 +* Added OdnoklassnikiOAuth2Service.
  79 +* Added LiveOAuth2Service.
  80 +* Added YahooOpenIDService.
  81 +
  82 +### Version 2.0.0 (03.09.2013)
  83 +* Use curl for http requests by default.
  84 +* getIsAuthenticated() function now looks up for existing access token for all OAuth services.
  85 +* Added support for oauth_expires_in to OAuth1 services.
  86 +* Added error handlers to OAuth1 services.
  87 +* Added support for refresh tokens to OAuth2 ServiceProxy.
  88 +* Added an option to disable OAuth2 state validation.
  89 +
  90 +### 31.08.2013
  91 +* Reorganize directories. Separate root directory by service type.
  92 +* Fixed OAuthService::getCallbackUrl(). Now returns url without GET arguments.
  93 +* Fixed typos in OAuth services.
  94 +* Fixed OpenID loadAttributes functions.
  95 +* OAuth2 display mode handling moved to the base class.
  96 +* Added OAuthService::getAccessTokenData() method to access to valid access_token and related data.
  97 +* Added token default lifetime setting.
  98 +* Added "state" argument handling for OAuth2 services to improve security.
  99 +* Updated OpenID library. Fixed error with stream requests.
  100 +* Added VKontakteOAuth2Service.
  101 +* Added GoogleOAuth2Service.
  102 +* Added GoogleOAuth2Service.
  103 +* Added YandexOAuth2Service.
  104 +* Added session token storage using Yii session.
  105 +
  106 +### 30.08.2013
  107 +* Initial release for Yii2.
... ...
common/components/nodge/eauth/LICENSE 0 → 100644
  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.
0 9 \ No newline at end of file
... ...
common/components/nodge/eauth/README.md 0 → 100644
  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 +<?php
  120 +...
  121 + 'components' => [
  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 + ],
  192 + 'instagram' => [
  193 + // register your app here: https://instagram.com/developer/register/
  194 + 'class' => 'nodge\eauth\services\InstagramOAuth2Service',
  195 + 'clientId' => '...',
  196 + 'clientSecret' => '...',
  197 + ],
  198 + 'vkontakte' => [
  199 + // register your app here: https://vk.com/editapp?act=create&site=1
  200 + 'class' => 'nodge\eauth\services\VKontakteOAuth2Service',
  201 + 'clientId' => '...',
  202 + 'clientSecret' => '...',
  203 + ],
  204 + 'mailru' => [
  205 + // register your app here: http://api.mail.ru/sites/my/add
  206 + 'class' => 'nodge\eauth\services\MailruOAuth2Service',
  207 + 'clientId' => '...',
  208 + 'clientSecret' => '...',
  209 + ],
  210 + 'odnoklassniki' => [
  211 + // register your app here: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
  212 + // ... or here: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
  213 + 'class' => 'nodge\eauth\services\OdnoklassnikiOAuth2Service',
  214 + 'clientId' => '...',
  215 + 'clientSecret' => '...',
  216 + 'clientPublic' => '...',
  217 + 'title' => 'Odnoklas.',
  218 + ],
  219 + ],
  220 + ],
  221 +
  222 + 'i18n' => [
  223 + 'translations' => [
  224 + 'eauth' => [
  225 + 'class' => 'yii\i18n\PhpMessageSource',
  226 + 'basePath' => '@eauth/messages',
  227 + ],
  228 + ],
  229 + ],
  230 +
  231 + // (optionally) you can configure pretty urls
  232 + 'urlManager' => [
  233 + 'enablePrettyUrl' => true,
  234 + 'showScriptName' => false,
  235 + 'rules' => [
  236 + 'login/<service:google|facebook|etc>' => 'site/login',
  237 + ],
  238 + ],
  239 +
  240 + // (optionally) you can configure logging
  241 + 'log' => [
  242 + 'targets' => [
  243 + [
  244 + 'class' => 'yii\log\FileTarget',
  245 + 'logFile' => '@app/runtime/logs/eauth.log',
  246 + 'categories' => ['nodge\eauth\*'],
  247 + 'logVars' => [],
  248 + ],
  249 + ],
  250 + ],
  251 + ...
  252 + ],
  253 +...
  254 +```
  255 +
  256 +### User model
  257 +
  258 +You need to modify your User model to login with EAuth services.
  259 +Example from demo project:
  260 +
  261 +```php
  262 +<?php
  263 +...
  264 + /**
  265 + * @var array EAuth attributes
  266 + */
  267 + public $profile;
  268 +
  269 + public static function findIdentity($id) {
  270 + if (Yii::$app->getSession()->has('user-'.$id)) {
  271 + return new self(Yii::$app->getSession()->get('user-'.$id));
  272 + }
  273 + else {
  274 + return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
  275 + }
  276 + }
  277 +
  278 + /**
  279 + * @param \nodge\eauth\ServiceBase $service
  280 + * @return User
  281 + * @throws ErrorException
  282 + */
  283 + public static function findByEAuth($service) {
  284 + if (!$service->getIsAuthenticated()) {
  285 + throw new ErrorException('EAuth user should be authenticated before creating identity.');
  286 + }
  287 +
  288 + $id = $service->getServiceName().'-'.$service->getId();
  289 + $attributes = [
  290 + 'id' => $id,
  291 + 'username' => $service->getAttribute('name'),
  292 + 'authKey' => md5($id),
  293 + 'profile' => $service->getAttributes(),
  294 + ];
  295 + $attributes['profile']['service'] = $service->getServiceName();
  296 + Yii::$app->getSession()->set('user-'.$id, $attributes);
  297 + return new self($attributes);
  298 + }
  299 +...
  300 +```
  301 +
  302 +Then you can access to EAuth attributes through:
  303 +
  304 +```php
  305 +<?php
  306 + $identity = Yii::$app->getUser()->getIdentity();
  307 + if (isset($identity->profile)) {
  308 + VarDumper::dump($identity->profile, 10, true);
  309 + }
  310 +```
  311 +
  312 +### Controller
  313 +
  314 +Attach OpenID Controller behavior to disable CSRF validation for OpenID callbacks.
  315 +Or you can disable CSRF validation by yourself.
  316 +
  317 +```php
  318 +<?php
  319 +...
  320 + public function behaviors() {
  321 + return [
  322 + 'eauth' => [
  323 + // required to disable csrf validation on OpenID requests
  324 + 'class' => \nodge\eauth\openid\ControllerBehavior::className(),
  325 + 'only' => ['login'],
  326 + ],
  327 + ];
  328 + }
  329 +...
  330 +```
  331 +
  332 +Add the following to your Login action:
  333 +
  334 +```php
  335 +<?php
  336 +...
  337 + public function actionLogin() {
  338 + $serviceName = Yii::$app->getRequest()->getQueryParam('service');
  339 + if (isset($serviceName)) {
  340 + /** @var $eauth \nodge\eauth\ServiceBase */
  341 + $eauth = Yii::$app->get('eauth')->getIdentity($serviceName);
  342 + $eauth->setRedirectUrl(Yii::$app->getUser()->getReturnUrl());
  343 + $eauth->setCancelUrl(Yii::$app->getUrlManager()->createAbsoluteUrl('site/login'));
  344 +
  345 + try {
  346 + if ($eauth->authenticate()) {
  347 +// var_dump($eauth->getIsAuthenticated(), $eauth->getAttributes()); exit;
  348 +
  349 + $identity = User::findByEAuth($eauth);
  350 + Yii::$app->getUser()->login($identity);
  351 +
  352 + // special redirect with closing popup window
  353 + $eauth->redirect();
  354 + }
  355 + else {
  356 + // close popup window and redirect to cancelUrl
  357 + $eauth->cancel();
  358 + }
  359 + }
  360 + catch (\nodge\eauth\ErrorException $e) {
  361 + // save error to show it later
  362 + Yii::$app->getSession()->setFlash('error', 'EAuthException: '.$e->getMessage());
  363 +
  364 + // close popup window and redirect to cancelUrl
  365 +// $eauth->cancel();
  366 + $eauth->redirect($eauth->getCancelUrl());
  367 + }
  368 + }
  369 +
  370 + // default authorization code through login/password ..
  371 + }
  372 +...
  373 +```
  374 +
  375 +### View
  376 +
  377 +```php
  378 +...
  379 +<?php
  380 + if (Yii::$app->getSession()->hasFlash('error')) {
  381 + echo '<div class="alert alert-danger">'.Yii::$app->getSession()->getFlash('error').'</div>';
  382 + }
  383 +?>
  384 +...
  385 +<p class="lead">Do you already have an account on one of these sites? Click the logo to log in with it here:</p>
  386 +<?php echo \nodge\eauth\Widget::widget(['action' => 'site/login']); ?>
  387 +...
  388 +```
  389 +
  390 +
  391 +## Extending
  392 +
  393 +To receive all the necessary data to your application, you can override the base class of any provider.
  394 +Base classes are stored in `@eauth/src/services`.
  395 +Examples of extended classes can be found in `@eauth/src/services/extended/`.
  396 +
  397 +After overriding the base class, you need to update your configuration file with a new class name.
  398 +
  399 +
  400 +## Working with OAuth API
  401 +
  402 +You can extend base classes with necessary methods and then write something like this:
  403 +
  404 +```php
  405 +<?php
  406 + /** @var $eauth EAuthServiceBase */
  407 + $eauth = Yii::$app->eauth->getIdentity('facebook');
  408 +
  409 + // to get protected resources user should be authenticated:
  410 + if ($eauth->getIsAuthenticated()) {
  411 + $eauth->callProtectedApiMethod();
  412 + $eauth->callAnotherProtectedApiMethod();
  413 + }
  414 +
  415 + // or you can get public resources at any time:
  416 + $eauth->callPublicApiMethod();
  417 + $eauth->callAnotherPublicApiMethod();
  418 +```
  419 +
  420 +Example of an API call method:
  421 +
  422 +```php
  423 +<?php
  424 + class FacebookOAuth2Service extends \nodge\eauth\services\FacebookOAuth2Service
  425 + {
  426 + public function fooApiMethod($bar) {
  427 + $api_method = 'me'; // ex. for Facebook this results to https://graph.facebook.com/me
  428 +
  429 + // get protected resource
  430 + $response = $this->makeSignedRequest($api_method, [
  431 + 'query' => [ 'foo' => 'bar' ], // GET arguments
  432 + 'data' => [ 'foo' => 'bar' ], // POST arguments
  433 + 'headers' => [ 'X-Foo' => 'bar' ], // Extra HTTP headers
  434 + ]);
  435 +
  436 + // you can get public resources with the same API:
  437 + //$response = $this->makeRequest($api_method, $options);
  438 +
  439 + // process $response
  440 + $data = process($response);
  441 +
  442 + // return results
  443 + return $data;
  444 + }
  445 + }
  446 +```
  447 +
  448 +API calls are performed if the current user has a valid access token (saved during the authentication).
  449 +You can save access_token to your database by using custom token storage in your config:
  450 +
  451 +```php
  452 +<?php
  453 +...
  454 + 'components' => [
  455 + 'eauth' => [
  456 + 'class' => 'nodge\eauth\EAuth',
  457 + 'tokenStorage' => [
  458 + 'class' => '@app\eauth\DatabaseTokenStorage',
  459 + ],
  460 + ],
  461 + ...
  462 + ],
  463 +...
  464 +```
  465 +
  466 +
  467 +## Translation
  468 +
  469 +To use translations, add the following in your config:
  470 +
  471 +```php
  472 +<?php
  473 +...
  474 + 'components' => [
  475 + 'i18n' => [
  476 + 'translations' => [
  477 + 'eauth' => [
  478 + 'class' => 'yii\i18n\PhpMessageSource',
  479 + 'basePath' => '@eauth/messages',
  480 + ],
  481 + ],
  482 + ],
  483 + ...
  484 + ],
  485 +...
  486 +```
  487 +
  488 +Available translations can be found in `@eauth/src/messages`.
  489 +
  490 +
  491 +# License
  492 +
  493 +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).
... ...
common/components/nodge/eauth/composer.json 0 → 100644
  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 + "common\modules\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": "common\modules\nodge\\eauth\\Bootstrap"
  32 + }
  33 +}
0 34 \ No newline at end of file
... ...
common/components/nodge/eauth/src/Bootstrap.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Extension class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\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 +}
0 29 \ No newline at end of file
... ...
common/components/nodge/eauth/src/EAuth.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * EAuth class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\components\nodge\eauth\src;
  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 +}
... ...
common/components/nodge/eauth/src/ErrorException.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * ErrorException class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\eauth;
  11 +
  12 +class ErrorException extends \yii\base\ErrorException
  13 +{
  14 +
  15 +}
0 16 \ No newline at end of file
... ...
common/components/nodge/eauth/src/IAuthService.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * IAuthService interface file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\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 +}
0 130 \ No newline at end of file
... ...
common/components/nodge/eauth/src/RedirectWidget.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * AuthRedirectWidget class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\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 +}
... ...
common/components/nodge/eauth/src/ServiceBase.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * ServiceBase class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\eauth;
  11 +
  12 +use Yii;
  13 +use yii\base\Object;
  14 +use yii\helpers\Url;
  15 +
  16 +/**
  17 + * EAuthServiceBase is a base class for providers.
  18 + *
  19 + * @package application.extensions.eauth
  20 + */
  21 +abstract class ServiceBase extends Object implements IAuthService
  22 +{
  23 +
  24 + /**
  25 + * @var string the service name.
  26 + */
  27 + protected $name;
  28 +
  29 + /**
  30 + *
  31 + * @var string the service title to display in views.
  32 + */
  33 + protected $title;
  34 +
  35 + /**
  36 + * @var string the service type (e.g. OpenID, OAuth).
  37 + */
  38 + protected $type;
  39 +
  40 + /**
  41 + * @var array arguments for the jQuery.eauth() javascript function.
  42 + */
  43 + protected $jsArguments = [];
  44 +
  45 + /**
  46 + * @var array authorization attributes.
  47 + * @see getAttribute
  48 + * @see getItem
  49 + */
  50 + protected $attributes = [];
  51 +
  52 + /**
  53 + * @var boolean whether user was successfuly authenticated.
  54 + * @see getIsAuthenticated
  55 + */
  56 + protected $authenticated = false;
  57 +
  58 + /**
  59 + * @var boolean whether is attributes was fetched.
  60 + */
  61 + private $fetched = false;
  62 +
  63 + /**
  64 + * @var EAuth the {@link EAuth} application component.
  65 + */
  66 + private $component;
  67 +
  68 + /**
  69 + * @var string the redirect url after successful authorization.
  70 + */
  71 + private $redirectUrl = '';
  72 +
  73 + /**
  74 + * @var string the redirect url after unsuccessful authorization (e.g. user canceled).
  75 + */
  76 + private $cancelUrl = '';
  77 +
  78 + /**
  79 + * PHP getter magic method.
  80 + * This method is overridden so that service attributes can be accessed like properties.
  81 + *
  82 + * @param string $name property name.
  83 + * @return mixed property value.
  84 + * @see getAttribute
  85 + */
  86 + public function __get($name)
  87 + {
  88 + if ($this->hasAttribute($name)) {
  89 + return $this->getAttribute($name);
  90 + } else {
  91 + return parent::__get($name);
  92 + }
  93 + }
  94 +
  95 + /**
  96 + * Checks if a attribute value is null.
  97 + * This method overrides the parent implementation by checking
  98 + * if the attribute is null or not.
  99 + *
  100 + * @param string $name the attribute name.
  101 + * @return boolean whether the attribute value is null.
  102 + */
  103 + public function __isset($name)
  104 + {
  105 + if ($this->hasAttribute($name)) {
  106 + return true;
  107 + } else {
  108 + return parent::__isset($name);
  109 + }
  110 + }
  111 +
  112 + /**
  113 + * Initialize the component.
  114 + * Sets the default {@link redirectUrl} and {@link cancelUrl}.
  115 + */
  116 + public function init()
  117 + {
  118 + parent::init();
  119 +
  120 + $this->setRedirectUrl(Yii::$app->getUser()->getReturnUrl());
  121 +
  122 + $service = Yii::$app->getRequest()->getQueryParam('service');
  123 + $cancelUrl = Url::to(['', 'service' => $service], true);
  124 +
  125 + $this->setCancelUrl($cancelUrl);
  126 + }
  127 +
  128 + /**
  129 + * Returns service name(id).
  130 + *
  131 + * @return string the service name(id).
  132 + */
  133 + public function getServiceName()
  134 + {
  135 + return $this->name;
  136 + }
  137 +
  138 + /**
  139 + * Returns service title.
  140 + *
  141 + * @return string the service title.
  142 + */
  143 + public function getServiceTitle()
  144 + {
  145 + return Yii::t('eauth', $this->title);
  146 + }
  147 +
  148 + /**
  149 + * Returns service type (e.g. OpenID, OAuth).
  150 + *
  151 + * @return string the service type (e.g. OpenID, OAuth).
  152 + */
  153 + public function getServiceType()
  154 + {
  155 + return $this->type;
  156 + }
  157 +
  158 + /**
  159 + * Returns arguments for the jQuery.eauth() javascript function.
  160 + *
  161 + * @return array the arguments for the jQuery.eauth() javascript function.
  162 + */
  163 + public function getJsArguments()
  164 + {
  165 + return $this->jsArguments;
  166 + }
  167 +
  168 + /**
  169 + * Sets {@link EAuth} application component
  170 + *
  171 + * @param EAuth $component the application auth component.
  172 + */
  173 + public function setComponent($component)
  174 + {
  175 + $this->component = $component;
  176 + }
  177 +
  178 + /**
  179 + * Returns the {@link EAuth} application component.
  180 + *
  181 + * @return EAuth the {@link EAuth} application component.
  182 + */
  183 + public function getComponent()
  184 + {
  185 + return $this->component;
  186 + }
  187 +
  188 + /**
  189 + * Sets redirect url after successful authorization.
  190 + *
  191 + * @param string $url to redirect.
  192 + */
  193 + public function setRedirectUrl($url)
  194 + {
  195 + $this->redirectUrl = $url;
  196 + }
  197 +
  198 + /**
  199 + * @return string the redirect url after successful authorization.
  200 + */
  201 + public function getRedirectUrl()
  202 + {
  203 + return $this->redirectUrl;
  204 + }
  205 +
  206 + /**
  207 + * Sets redirect url after unsuccessful authorization (e.g. user canceled).
  208 + *
  209 + * @param string $url
  210 + */
  211 + public function setCancelUrl($url)
  212 + {
  213 + $this->cancelUrl = $url;
  214 + }
  215 +
  216 + /**
  217 + * @return string the redirect url after unsuccessful authorization (e.g. user canceled).
  218 + */
  219 + public function getCancelUrl()
  220 + {
  221 + return $this->cancelUrl;
  222 + }
  223 +
  224 + /**
  225 + * @param string $title
  226 + */
  227 + public function setTitle($title)
  228 + {
  229 + $this->title = $title;
  230 + }
  231 +
  232 + /**
  233 + * Authenticate the user.
  234 + *
  235 + * @return boolean whether user was successfuly authenticated.
  236 + */
  237 + public function authenticate()
  238 + {
  239 + return $this->getIsAuthenticated();
  240 + }
  241 +
  242 + /**
  243 + * Whether user was successfuly authenticated.
  244 + *
  245 + * @return boolean whether user was successfuly authenticated.
  246 + */
  247 + public function getIsAuthenticated()
  248 + {
  249 + return $this->authenticated;
  250 + }
  251 +
  252 + /**
  253 + * Redirect to the url. If url is null, {@link redirectUrl} will be used.
  254 + *
  255 + * @param string $url url to redirect.
  256 + * @param array $params
  257 + */
  258 + public function redirect($url = null, $params = [])
  259 + {
  260 + $this->component->redirect(isset($url) ? $url : $this->redirectUrl, true, $params);
  261 + }
  262 +
  263 + /**
  264 + * Redirect to the {@link cancelUrl} or simply close the popup window.
  265 + */
  266 + public function cancel($url = null)
  267 + {
  268 + $this->component->redirect(isset($url) ? $url : $this->cancelUrl, !$this->component->popup);
  269 + }
  270 +
  271 + /**
  272 + * Fetch attributes array.
  273 + *
  274 + * @return boolean whether the attributes was successfully fetched.
  275 + */
  276 + protected function fetchAttributes()
  277 + {
  278 + return true;
  279 + }
  280 +
  281 + /**
  282 + * Fetch attributes array.
  283 + * This function is internally used to handle fetched state.
  284 + */
  285 + protected function _fetchAttributes()
  286 + {
  287 + if (!$this->fetched) {
  288 + $this->fetched = true;
  289 + $result = $this->fetchAttributes();
  290 + if (isset($result)) {
  291 + $this->fetched = $result;
  292 + }
  293 + }
  294 + }
  295 +
  296 + /**
  297 + * Returns the user unique id.
  298 + *
  299 + * @return mixed the user id.
  300 + */
  301 + public function getId()
  302 + {
  303 + $this->_fetchAttributes();
  304 + return $this->attributes['id'];
  305 + }
  306 +
  307 + /**
  308 + * Returns the array that contains all available authorization attributes.
  309 + *
  310 + * @return array the attributes.
  311 + */
  312 + public function getAttributes()
  313 + {
  314 + $this->_fetchAttributes();
  315 + $attributes = [];
  316 + foreach ($this->attributes as $key => $val) {
  317 + $attributes[$key] = $this->getAttribute($key);
  318 + }
  319 + return $attributes;
  320 + }
  321 +
  322 + /**
  323 + * Returns the authorization attribute value.
  324 + *
  325 + * @param string $key the attribute name.
  326 + * @param mixed $default the default value.
  327 + * @return mixed the attribute value.
  328 + */
  329 + public function getAttribute($key, $default = null)
  330 + {
  331 + $this->_fetchAttributes();
  332 + $getter = 'get' . $key;
  333 + if (method_exists($this, $getter)) {
  334 + return $this->$getter();
  335 + } else {
  336 + return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
  337 + }
  338 + }
  339 +
  340 + /**
  341 + * Whether the authorization attribute exists.
  342 + *
  343 + * @param string $key the attribute name.
  344 + * @return boolean true if attribute exists, false otherwise.
  345 + */
  346 + public function hasAttribute($key)
  347 + {
  348 + $this->_fetchAttributes();
  349 + return isset($this->attributes[$key]);
  350 + }
  351 +
  352 + /**
  353 + * @return bool
  354 + */
  355 + public function getIsInsidePopup()
  356 + {
  357 + return isset($_GET['js']);
  358 + }
  359 +}
... ...
common/components/nodge/eauth/src/Widget.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Widget class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\modules\nodge\eauth\src\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 +}
... ...
common/components/nodge/eauth/src/assets/WidgetAssetBundle.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * @link http://www.yiiframework.com/
  4 + * @copyright Copyright (c) 2008 Yii Software LLC
  5 + * @license http://www.yiiframework.com/license/
  6 + */
  7 +
  8 +namespace nodge\eauth\assets;
  9 +
  10 +use yii\web\AssetBundle;
  11 +
  12 +/**
  13 + * @author Qiang Xue <qiang.xue@gmail.com>
  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 +}
... ...
common/components/nodge/eauth/src/assets/css/eauth.css 0 → 100644
  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 +}
0 104 \ No newline at end of file
... ...
common/components/nodge/eauth/src/assets/images/auth-src.png 0 → 100644

19 KB

common/components/nodge/eauth/src/assets/images/auth.png 0 → 100644

6.18 KB

common/components/nodge/eauth/src/assets/js/eauth.js 0 → 100644
  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);
... ...
common/components/nodge/eauth/src/messages/blank/eauth.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 + 'Undefined service name: {service}.' => '{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 +];
0 24 \ No newline at end of file
... ...
common/components/nodge/eauth/src/messages/de/eauth.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 + 'Undefined service name: {service}.' => '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 +];
0 24 \ No newline at end of file
... ...
common/components/nodge/eauth/src/messages/en/eauth.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 + 'Undefined service name: {service}.' => '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 +];
0 24 \ No newline at end of file
... ...
common/components/nodge/eauth/src/messages/ru/eauth.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 + 'Undefined service name: {service}.' => 'Авторизация с помощью {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 +];
0 24 \ No newline at end of file
... ...
common/components/nodge/eauth/src/messages/uk/eauth.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 + 'Undefined service name: {service}.' => 'Авторизація за допомогою {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 +];
... ...
common/components/nodge/eauth/src/oauth/HttpClient.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * HttpClient class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  172 +
  173 + if ($this->method === 'POST' || $this->method === 'PUT') {
  174 + if ($this->method === 'PUT') {
  175 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
  176 + } else {
  177 + curl_setopt($ch, CURLOPT_POST, true);
  178 + }
  179 + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody);
  180 + } else {
  181 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
  182 + }
  183 +
  184 + if ($this->allowFollowLocation() && $this->maxRedirects > 0) {
  185 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  186 + curl_setopt($ch, CURLOPT_MAXREDIRS, $this->maxRedirects);
  187 + }
  188 +
  189 + curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
  190 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  191 + curl_setopt($ch, CURLOPT_HEADER, false);
  192 + curl_setopt($ch, CURLOPT_HTTPHEADER, $this->extraHeaders);
  193 +
  194 + if ($this->forceSSL3) {
  195 + curl_setopt($ch, CURLOPT_SSLVERSION, 3);
  196 + }
  197 +
  198 + $response = curl_exec($ch);
  199 + $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  200 +
  201 + if (YII_DEBUG) {
  202 + Yii::trace('EAuth http response: ' . PHP_EOL . var_export($response, true), __NAMESPACE__);
  203 + }
  204 +
  205 + if (false === $response) {
  206 + $errNo = curl_errno($ch);
  207 + $errStr = curl_error($ch);
  208 + curl_close($ch);
  209 +
  210 + if (empty($errStr)) {
  211 + $errStr = 'Failed to request resource.';
  212 + } else {
  213 + $errStr = 'cURL Error # ' . $errNo . ': ' . $errStr;
  214 + }
  215 +
  216 + Yii::error('EAuth curl error (' . $responseCode . '): ' . $errStr, __NAMESPACE__);
  217 + throw new TokenResponseException($errStr, $responseCode);
  218 + }
  219 +
  220 + curl_close($ch);
  221 +
  222 + return $response;
  223 + }
  224 +
  225 + /**
  226 + * @return string
  227 + * @throws TokenResponseException
  228 + */
  229 + protected function streams()
  230 + {
  231 + $this->prepareRequest();
  232 +
  233 + $context = stream_context_create([
  234 + 'http' => [
  235 + 'method' => $this->method,
  236 + 'header' => array_values($this->extraHeaders),
  237 + 'content' => $this->requestBody,
  238 + 'protocol_version' => '1.1',
  239 + 'user_agent' => 'Yii2 EAuth Client',
  240 + 'max_redirects' => $this->maxRedirects,
  241 + 'timeout' => $this->timeout,
  242 + ],
  243 + ]);
  244 +
  245 + $level = error_reporting(0);
  246 + $response = file_get_contents($this->endpoint->getAbsoluteUri(), false, $context);
  247 + error_reporting($level);
  248 +
  249 + if (YII_DEBUG) {
  250 + Yii::trace('EAuth http response: ' . PHP_EOL . var_export($response, true), __NAMESPACE__);
  251 + }
  252 +
  253 + if (false === $response) {
  254 + $lastError = error_get_last();
  255 +
  256 + if (is_null($lastError)) {
  257 + $errStr = 'Failed to request resource.';
  258 + } else {
  259 + $errStr = $lastError['message'];
  260 + }
  261 +
  262 + Yii::error('EAuth streams error: ' . $errStr, __NAMESPACE__);
  263 + throw new TokenResponseException($errStr);
  264 + }
  265 +
  266 + return $response;
  267 + }
  268 +
  269 +}
... ...
common/components/nodge/eauth/src/oauth/ServiceBase.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OAuthService class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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\Uri\Uri;
  14 +use OAuth\Common\Http\Client\ClientInterface;
  15 +use OAuth\Common\Token\TokenInterface;
  16 +use OAuth\Common\Storage\TokenStorageInterface;
  17 +use nodge\eauth\EAuth;
  18 +use nodge\eauth\IAuthService;
  19 +use nodge\eauth\ErrorException;
  20 +use yii\helpers\ArrayHelper;
  21 +use yii\helpers\Url;
  22 +
  23 +/**
  24 + * EOAuthService is a base class for all OAuth providers.
  25 + *
  26 + * @package application.extensions.eauth
  27 + */
  28 +abstract class ServiceBase extends \nodge\eauth\ServiceBase implements IAuthService
  29 +{
  30 +
  31 + /**
  32 + * @var string Base url for API calls.
  33 + */
  34 + protected $baseApiUrl;
  35 +
  36 + /**
  37 + * @var int Default token lifetime. Used when service wont provide expires_in param.
  38 + */
  39 + protected $tokenDefaultLifetime = null;
  40 +
  41 + /**
  42 + * @var array TokenStorage class. Null means default value from EAuth component config.
  43 + */
  44 + protected $tokenStorage;
  45 +
  46 + /**
  47 + * @var array HttpClient class. Null means default value from EAuth component config.
  48 + */
  49 + protected $httpClient;
  50 +
  51 + /**
  52 + * @var TokenStorageInterface
  53 + */
  54 + private $_tokenStorage;
  55 +
  56 + /**
  57 + * @var ClientInterface
  58 + */
  59 + private $_httpClient;
  60 +
  61 + /**
  62 + * Initialize the component.
  63 + *
  64 + * @param EAuth $component the component instance.
  65 + * @param array $options properties initialization.
  66 + */
  67 +// public function init($component, $options = []) {
  68 +// parent::init($component, $options);
  69 +// }
  70 +
  71 + /**
  72 + * For OAuth we can check existing access token.
  73 + * Useful for API calls.
  74 + *
  75 + * @return bool
  76 + * @throws ErrorException
  77 + */
  78 + public function getIsAuthenticated()
  79 + {
  80 + if (!$this->authenticated) {
  81 + try {
  82 + $proxy = $this->getProxy();
  83 + $this->authenticated = $proxy->hasValidAccessToken();
  84 + } catch (\OAuth\Common\Exception\Exception $e) {
  85 + throw new ErrorException($e->getMessage(), $e->getCode(), 1, $e->getFile(), $e->getLine(), $e);
  86 + }
  87 + }
  88 + return parent::getIsAuthenticated();
  89 + }
  90 +
  91 + /**
  92 + * @return \nodge\eauth\oauth1\ServiceProxy|\nodge\eauth\oauth2\ServiceProxy
  93 + */
  94 + abstract protected function getProxy();
  95 +
  96 + /**
  97 + * @return string the current url
  98 + */
  99 + protected function getCallbackUrl()
  100 + {
  101 + return Url::to('', true);
  102 + }
  103 +
  104 + /**
  105 + * @param array $config
  106 + */
  107 + public function setTokenStorage(array $config)
  108 + {
  109 + $this->tokenStorage = ArrayHelper::merge($this->tokenStorage, $config);
  110 + }
  111 +
  112 + /**
  113 + * @return TokenStorageInterface
  114 + */
  115 + protected function getTokenStorage()
  116 + {
  117 + if (!isset($this->_tokenStorage)) {
  118 + $config = $this->tokenStorage;
  119 + if (!isset($config)) {
  120 + $config = $this->getComponent()->getTokenStorage();
  121 + }
  122 + $this->_tokenStorage = Yii::createObject($config);
  123 + }
  124 + return $this->_tokenStorage;
  125 + }
  126 +
  127 + /**
  128 + * @param array $config
  129 + */
  130 + public function setHttpClient(array $config)
  131 + {
  132 + $this->httpClient = ArrayHelper::merge($this->httpClient, $config);
  133 + }
  134 +
  135 + /**
  136 + * @return ClientInterface
  137 + */
  138 + protected function getHttpClient()
  139 + {
  140 + if (!isset($this->_httpClient)) {
  141 + $config = $this->httpClient;
  142 + if (!isset($config)) {
  143 + $config = $this->getComponent()->getHttpClient();
  144 + }
  145 + $this->_httpClient = Yii::createObject($config);
  146 + }
  147 + return $this->_httpClient;
  148 + }
  149 +
  150 + /**
  151 + * @return int
  152 + */
  153 + public function getTokenDefaultLifetime()
  154 + {
  155 + return $this->tokenDefaultLifetime;
  156 + }
  157 +
  158 + /**
  159 + * Returns the protected resource.
  160 + *
  161 + * @param string $url url to request.
  162 + * @param array $options HTTP request options. Keys: query, data, headers.
  163 + * @param boolean $parseResponse Whether to parse response.
  164 + * @return mixed the response.
  165 + * @throws ErrorException
  166 + */
  167 + public function makeSignedRequest($url, $options = [], $parseResponse = true)
  168 + {
  169 + if (!$this->getIsAuthenticated()) {
  170 + throw new ErrorException(Yii::t('eauth', 'Unable to complete the signed request because the user was not authenticated.'), 401);
  171 + }
  172 +
  173 + if (stripos($url, 'http') !== 0) {
  174 + $url = $this->baseApiUrl . $url;
  175 + }
  176 +
  177 + $url = new Uri($url);
  178 + if (isset($options['query'])) {
  179 + foreach ($options['query'] as $key => $value) {
  180 + $url->addToQuery($key, $value);
  181 + }
  182 + }
  183 +
  184 + $data = isset($options['data']) ? $options['data'] : [];
  185 + $method = !empty($data) ? 'POST' : 'GET';
  186 + $headers = isset($options['headers']) ? $options['headers'] : [];
  187 +
  188 + $response = $this->getProxy()->request($url, $method, $data, $headers);
  189 +
  190 + if ($parseResponse) {
  191 + $response = $this->parseResponseInternal($response);
  192 + }
  193 +
  194 + return $response;
  195 + }
  196 +
  197 + /**
  198 + * Returns the public resource.
  199 + *
  200 + * @param string $url url to request.
  201 + * @param array $options HTTP request options. Keys: query, data, headers.
  202 + * @param boolean $parseResponse Whether to parse response.
  203 + * @return mixed the response.
  204 + */
  205 + public function makeRequest($url, $options = [], $parseResponse = true) {
  206 + if (stripos($url, 'http') !== 0) {
  207 + $url = $this->baseApiUrl . $url;
  208 + }
  209 +
  210 + $url = new Uri($url);
  211 + if (isset($options['query'])) {
  212 + foreach ($options['query'] as $key => $value) {
  213 + $url->addToQuery($key, $value);
  214 + }
  215 + }
  216 +
  217 + $data = isset($options['data']) ? $options['data'] : [];
  218 + $method = !empty($data) ? 'POST' : 'GET';
  219 +
  220 + $headers = isset($options['headers']) ? $options['headers'] : [];
  221 + $headers = array_merge($this->getProxy()->getExtraApiHeaders(), $headers);
  222 +
  223 + $response = $this->getHttpClient()->retrieveResponse($url, $data, $headers, $method);
  224 + if ($parseResponse) {
  225 + $response = $this->parseResponseInternal($response);
  226 + }
  227 +
  228 + return $response;
  229 + }
  230 +
  231 + /**
  232 + * Parse response and check for errors.
  233 + *
  234 + * @param string $response
  235 + * @return mixed
  236 + * @throws ErrorException
  237 + */
  238 + protected function parseResponseInternal($response)
  239 + {
  240 + try {
  241 + $result = $this->parseResponse($response);
  242 + if (!isset($result)) {
  243 + throw new ErrorException(Yii::t('eauth', 'Invalid response format.'), 500);
  244 + }
  245 +
  246 + $error = $this->fetchResponseError($result);
  247 + if (isset($error) && !empty($error['message'])) {
  248 + throw new ErrorException($error['message'], $error['code']);
  249 + }
  250 +
  251 + return $result;
  252 + } catch (\Exception $e) {
  253 + throw new ErrorException($e->getMessage(), $e->getCode());
  254 + }
  255 + }
  256 +
  257 + /**
  258 + * @param string $response
  259 + * @return mixed
  260 + */
  261 + protected function parseResponse($response)
  262 + {
  263 + return json_decode($response, true);
  264 + }
  265 +
  266 + /**
  267 + * Returns the error array.
  268 + *
  269 + * @param array $response
  270 + * @return array the error array with 2 keys: code and message. Should be null if no errors.
  271 + */
  272 + protected function fetchResponseError($response)
  273 + {
  274 + if (isset($response['error'])) {
  275 + return [
  276 + 'code' => 500,
  277 + 'message' => 'Unknown error occurred.',
  278 + ];
  279 + }
  280 + return null;
  281 + }
  282 +
  283 + /**
  284 + * @return array|null An array with valid access_token information.
  285 + */
  286 + protected function getAccessTokenData()
  287 + {
  288 + if (!$this->getIsAuthenticated()) {
  289 + return null;
  290 + }
  291 +
  292 + $token = $this->getProxy()->getAccessToken();
  293 + if (!isset($token)) {
  294 + return null;
  295 + }
  296 +
  297 + return [
  298 + 'access_token' => $token->getAccessToken(),
  299 + 'refresh_token' => $token->getRefreshToken(),
  300 + 'expires' => $token->getEndOfLife(),
  301 + 'params' => $token->getExtraParams(),
  302 + ];
  303 + }
  304 +
  305 + /**
  306 + * @param array $data
  307 + * @return string|null
  308 + */
  309 + public function getAccessTokenResponseError($data)
  310 + {
  311 + return isset($data['error']) ? $data['error'] : null;
  312 + }
  313 +}
0 314 \ No newline at end of file
... ...
common/components/nodge/eauth/src/oauth/SessionTokenStorage.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * SessionTokenStorage class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
... ...
common/components/nodge/eauth/src/oauth1/Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OAuth1 Service class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
0 165 \ No newline at end of file
... ...
common/components/nodge/eauth/src/oauth1/ServiceProxy.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OAuth1 ServiceProxy class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
0 199 \ No newline at end of file
... ...
common/components/nodge/eauth/src/oauth2/Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OAuth2 Service class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 + * Return any additional headers always needed for this service implementation's API calls.
  311 + *
  312 + * @return array
  313 + */
  314 + public function getExtraApiHeaders()
  315 + {
  316 + return [];
  317 + }
  318 +
  319 + /**
  320 + * Returns a class constant from ServiceInterface defining the authorization method used for the API
  321 + * Header is the sane default.
  322 + *
  323 + * @return int
  324 + */
  325 + public function getAuthorizationMethod()
  326 + {
  327 + return ServiceInterface::AUTHORIZATION_METHOD_HEADER_OAUTH;
  328 + }
  329 +
  330 + /**
  331 + * @return string
  332 + */
  333 + public function getScopeSeparator()
  334 + {
  335 + return $this->scopeSeparator;
  336 + }
  337 +}
0 338 \ No newline at end of file
... ...
common/components/nodge/eauth/src/oauth2/ServiceProxy.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OAuth2 ServiceProxy class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
... ...
common/components/nodge/eauth/src/openid/ControllerBehavior.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * ControllerBehavior class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
... ...
common/components/nodge/eauth/src/openid/Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OpenID Service class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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->request();
  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 request()
  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 +}
... ...
common/components/nodge/eauth/src/services/FacebookOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * FacebookOAuth2Service class file.
  4 + *
  5 + * Register application: https://developers.facebook.com/apps/
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +namespace common\components\nodge\eauth\src\services;
  12 +use nodge\eauth\oauth2\Service;
  13 +/**
  14 + * Facebook provider class.
  15 + *
  16 + * @package application.extensions.eauth.services
  17 + */
  18 +class FacebookOAuth2Service extends Service
  19 +{
  20 + /**
  21 + * Full list of scopes may be found here:
  22 + * https://developers.facebook.com/docs/authentication/permissions/
  23 + */
  24 + const SCOPE_EMAIL = 'email';
  25 + const SCOPE_USER_BIRTHDAY = 'user_birthday';
  26 + const SCOPE_USER_HOMETOWN = 'user_hometown';
  27 + const SCOPE_USER_LOCATION = 'user_location';
  28 + const SCOPE_USER_PHOTOS = 'user_photos';
  29 + protected $name = 'facebook';
  30 + protected $title = 'Facebook';
  31 + protected $type = 'OAuth2';
  32 + protected $jsArguments = ['popup' => ['width' => 585, 'height' => 290]];
  33 + protected $scopes = [];
  34 + protected $providerOptions = [
  35 + 'authorize' => 'https://www.facebook.com/dialog/oauth',
  36 + 'access_token' => 'https://graph.facebook.com/oauth/access_token',
  37 + ];
  38 + protected $baseApiUrl = 'https://graph.facebook.com/';
  39 + protected $errorParam = 'error_code';
  40 + protected $errorDescriptionParam = 'error_message';
  41 + protected function fetchAttributes()
  42 + {
  43 + $info = $this->makeSignedRequest('me');
  44 + $this->attributes['id'] = $info['id'];
  45 + $this->attributes['name'] = $info['name'];
  46 + $this->attributes['url'] = $info['link'];
  47 + return true;
  48 + }
  49 + /**
  50 + * @return array
  51 + */
  52 + public function getAccessTokenArgumentNames()
  53 + {
  54 + $names = parent::getAccessTokenArgumentNames();
  55 + $names['expires_in'] = 'expires';
  56 + return $names;
  57 + }
  58 + /**
  59 + * @param string $response
  60 + * @return array
  61 + */
  62 + public function parseAccessTokenResponse($response)
  63 + {
  64 + // Facebook gives us a query string or json
  65 + if ($response[0] === '{') {
  66 + return json_decode($response, true);
  67 + }
  68 + else {
  69 + parse_str($response, $data);
  70 + return $data;
  71 + }
  72 + }
  73 + /**
  74 + * Returns the error array.
  75 + *
  76 + * @param array $response
  77 + * @return array the error array with 2 keys: code and message. Should be null if no errors.
  78 + */
  79 + protected function fetchResponseError($response)
  80 + {
  81 + if (isset($response['error'])) {
  82 + return [
  83 + 'code' => $response['error']['code'],
  84 + 'message' => $response['error']['message'],
  85 + ];
  86 + } else {
  87 + return null;
  88 + }
  89 + }
  90 + /**
  91 + * @param array $data
  92 + * @return string|null
  93 + */
  94 + public function getAccessTokenResponseError($data)
  95 + {
  96 + $error = $this->fetchResponseError($data);
  97 + if (!$error) {
  98 + return null;
  99 + }
  100 + return $error['code'].': '.$error['message'];
  101 + }
  102 +}
0 103 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/GitHubOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * GithubOAuth2Service class file.
  4 + *
  5 + * Register application: https://github.com/settings/applications
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 108 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/GoogleOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * GoogleOAuth2Service class file.
  4 + *
  5 + * Register application: https://code.google.com/apis/console/
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 170 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/InstagramOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * FacebookOAuth2Service class file.
  4 + *
  5 + * Register application: https://instagram.com/developer/register/
  6 + *
  7 + * @author PhucPNT. <mail@phucpnt.com>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 91 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/LinkedinOAuth1Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * LinkedinOAuthService class file.
  4 + *
  5 + * Register application: https://www.linkedin.com/secure/developer
  6 + * Note: Integration URL should be filled with a valid callback url.
  7 + *
  8 + * @author Maxim Zemskov <nodge@yandex.ru>
  9 + * @link http://github.com/Nodge/yii2-eauth/
  10 + * @license http://www.opensource.org/licenses/bsd-license.php
  11 + */
  12 +
  13 +namespace common\components\nodge\eauth\src\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 +}
0 74 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/LinkedinOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * LinkedinOAuth2Service class file.
  4 + *
  5 + * Register application: https://www.linkedin.com/secure/developer
  6 + * Note: Integration URL should be filled with a valid callback url.
  7 + *
  8 + * @author Maxim Zemskov <nodge@yandex.ru>
  9 + * @link http://github.com/Nodge/yii2-eauth/
  10 + * @license http://www.opensource.org/licenses/bsd-license.php
  11 + */
  12 +
  13 +namespace common\components\nodge\eauth\src\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 + $this->attributes['email'] = $info['emailAddress'];
  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 +}
... ...
common/components/nodge/eauth/src/services/LiveOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * LiveOAuth2Service class file.
  4 + *
  5 + * Register application: https://account.live.com/developers/applications/index
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 86 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/MailruOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * MailruOAuth2Service class file.
  4 + *
  5 + * Register application: http://api.mail.ru/sites/my/add
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 99 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/OdnoklassnikiOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * OdnoklassnikiOAuthService class file.
  4 + *
  5 + * Register application: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
  6 + * Manage your applications: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
  7 + * Note: Enabling this service a little more difficult because of the authorization policy of the service.
  8 + *
  9 + * @author Maxim Zemskov <nodge@yandex.ru>
  10 + * @link http://github.com/Nodge/yii2-eauth/
  11 + * @license http://www.opensource.org/licenses/bsd-license.php
  12 + */
  13 +
  14 +namespace common\components\nodge\eauth\src\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' => 'http://www.odnoklassniki.ru/oauth/authorize',
  40 + 'access_token' => 'http://api.odnoklassniki.ru/oauth/token.do',
  41 + ];
  42 + protected $baseApiUrl = 'http://api.odnoklassniki.ru/fb.do';
  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 +}
... ...
common/components/nodge/eauth/src/services/SteamOpenIDService.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * SteamOpenIDService class file.
  4 + *
  5 + * @author Dmitry Ananichev <a@qozz.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\components\nodge\eauth\src\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 +
  29 + protected function fetchAttributes()
  30 + {
  31 + if (isset($this->attributes['id'])) {
  32 + $urlChunks = explode('/', $this->attributes['id']);
  33 + if ($count = count($urlChunks)) {
  34 + $name = $urlChunks[$count - 1];
  35 + $this->attributes['name'] = $name;
  36 + }
  37 + }
  38 + }
  39 +
  40 +}
0 41 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/TwitterOAuth1Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * TwitterOAuthService class file.
  4 + *
  5 + * Register application: https://dev.twitter.com/apps/new
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 72 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/VKontakteOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * VKontakteOAuth2Service class file.
  4 + *
  5 + * Register application: http://vk.com/editapp?act=create&site=1
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +
  27 + protected $name = 'vkontakte';
  28 + protected $title = 'VK.com';
  29 + protected $type = 'OAuth2';
  30 + protected $jsArguments = ['popup' => ['width' => 585, 'height' => 350]];
  31 +
  32 + protected $scopes = [self::SCOPE_FRIENDS];
  33 + protected $providerOptions = [
  34 + 'authorize' => 'http://api.vk.com/oauth/authorize',
  35 + 'access_token' => 'https://api.vk.com/oauth/access_token',
  36 + ];
  37 + protected $baseApiUrl = 'https://api.vk.com/method/';
  38 +
  39 + protected function fetchAttributes()
  40 + {
  41 + $tokenData = $this->getAccessTokenData();
  42 + $info = $this->makeSignedRequest('users.get.json', [
  43 + 'query' => [
  44 + 'uids' => $tokenData['params']['user_id'],
  45 + 'fields' => '', // uid, first_name and last_name is always available
  46 + 'fields' => 'nickname, sex, bdate, city, country, timezone, photo, photo_medium, photo_big, photo_rec',
  47 + ],
  48 + ]);
  49 +
  50 + $info = $info['response'][0];
  51 +
  52 + $this->attributes['id'] = $info['uid'];
  53 + $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
  54 + $this->attributes['url'] = 'http://vk.com/id' . $info['uid'];
  55 +
  56 + if (!empty($info['nickname']))
  57 + $this->attributes['username'] = $info['nickname'];
  58 + else
  59 + $this->attributes['username'] = 'id'.$info['uid'];
  60 +
  61 + $this->attributes['gender'] = $info['sex'] == 1 ? 'F' : 'M';
  62 +
  63 + $this->attributes['city'] = $info['city'];
  64 + $this->attributes['country'] = $info['country'];
  65 +
  66 + $this->attributes['timezone'] = timezone_name_from_abbr('', $info['timezone']*3600, date('I'));;
  67 +
  68 + $this->attributes['photo'] = $info['photo'];
  69 + $this->attributes['photo_medium'] = $info['photo_medium'];
  70 + $this->attributes['photo_big'] = $info['photo_big'];
  71 + $this->attributes['photo_rec'] = $info['photo_rec'];
  72 +
  73 + return true;
  74 + }
  75 +
  76 + /**
  77 + * Returns the error array.
  78 + *
  79 + * @param array $response
  80 + * @return array the error array with 2 keys: code and message. Should be null if no errors.
  81 + */
  82 + protected function fetchResponseError($response)
  83 + {
  84 + if (isset($response['error'])) {
  85 + return [
  86 + 'code' => is_string($response['error']) ? 0 : $response['error']['error_code'],
  87 +// 'message' => is_string($response['error']) ? $response['error'] : $response['error']['error_msg'],
  88 +// 'message' => is_string($response['error']) ? $response['error'] : $response['error']['error_msg'],
  89 + ];
  90 + } else {
  91 + return null;
  92 + }
  93 + }
  94 +
  95 + /**
  96 + * @param array $data
  97 + * @return string|null
  98 + */
  99 + public function getAccessTokenResponseError($data)
  100 + {
  101 + if (!isset($data['error'])) {
  102 + return null;
  103 + }
  104 + $error = $data['error'];
  105 + if (isset($data['error_description'])) {
  106 + $error .= ': ' . $data['error_description'];
  107 + }
  108 + return $error;
  109 + }
  110 +
  111 + /**
  112 + * Returns a class constant from ServiceInterface defining the authorization method used for the API.
  113 + *
  114 + * @return int
  115 + */
  116 + public function getAuthorizationMethod()
  117 + {
  118 + return ServiceInterface::AUTHORIZATION_METHOD_QUERY_STRING;
  119 + }
  120 +
  121 +}
0 122 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/YahooOpenIDService.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * YahooOpenIDService class file.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  6 + * @link http://github.com/Nodge/yii2-eauth/
  7 + * @license http://www.opensource.org/licenses/bsd-license.php
  8 + */
  9 +
  10 +namespace common\components\nodge\eauth\src\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 +}
0 45 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/YandexOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * YandexOAuth2Service class file.
  4 + *
  5 + * Register application: https://oauth.yandex.ru/client/my
  6 + *
  7 + * @author Maxim Zemskov <nodge@yandex.ru>
  8 + * @link http://github.com/Nodge/yii2-eauth/
  9 + * @license http://www.opensource.org/licenses/bsd-license.php
  10 + */
  11 +
  12 +namespace common\components\nodge\eauth\src\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 +}
0 52 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/extended/FacebookOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 + return true;
  32 + }
  33 +}
... ...
common/components/nodge/eauth/src/services/extended/GitHubOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
0 32 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/extended/MailruOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
... ...
common/components/nodge/eauth/src/services/extended/OdnoklassnikiOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
... ...
common/components/nodge/eauth/src/services/extended/TwitterOAuth1Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +}
0 49 \ No newline at end of file
... ...
common/components/nodge/eauth/src/services/extended/VKontakteOAuth2Service.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * An example of extending the provider class.
  4 + *
  5 + * @author Maxim Zemskov <nodge@yandex.ru>
  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 +
  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 + ],
  26 + ]);
  27 +
  28 + $info = $info['response'][0];
  29 +
  30 + $this->attributes = $info;
  31 + $this->attributes['id'] = $info['uid'];
  32 + $this->attributes['name'] = $info['first_name'] . ' ' . $info['last_name'];
  33 + $this->attributes['url'] = 'http://vk.com/id' . $info['uid'];
  34 +
  35 + if (!empty($info['nickname'])) {
  36 + $this->attributes['username'] = $info['nickname'];
  37 + } else {
  38 + $this->attributes['username'] = 'id' . $info['uid'];
  39 + }
  40 +
  41 + $this->attributes['gender'] = $info['sex'] == 1 ? 'F' : 'M';
  42 +
  43 + if (!empty($info['timezone'])) {
  44 + $this->attributes['timezone'] = timezone_name_from_abbr('', $info['timezone'] * 3600, date('I'));
  45 + }
  46 +
  47 + return true;
  48 + }
  49 +}
... ...
common/components/nodge/eauth/src/views/redirect.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\web\View;
  4 +
  5 +/** @var $this View */
  6 +/** @var $url string */
  7 +/** @var $redirect bool */
  8 +/** @var $url string */
  9 +
  10 +?><!DOCTYPE html>
  11 +<html>
  12 +<head>
  13 + <script type="text/javascript">
  14 + <?php
  15 + $code = 'if (window.opener) {';
  16 + $code .= 'window.close();';
  17 + if ($redirect) {
  18 + $code .= 'window.opener.location = \''.addslashes($url).'\';';
  19 + }
  20 + $code .= '}';
  21 + $code .= 'else {';
  22 + if ($redirect) {
  23 + $code .= 'window.location = \''.addslashes($url).'\';';
  24 + }
  25 + $code .= '}';
  26 + echo $code;
  27 + ?>
  28 + </script>
  29 +</head>
  30 +<body>
  31 +
  32 +<h2 id="title" style="display:none;">
  33 + <?php echo \Yii::t('eauth', 'Redirecting back to the application...'); ?>
  34 +</h2>
  35 +
  36 +<h3 id="link">
  37 + <a href="<?php echo $url; ?>">
  38 + <?php echo \Yii::t('eauth', 'Click here to return to the application.'); ?>
  39 + </a>
  40 +</h3>
  41 +
  42 +<script type="text/javascript">
  43 + document.getElementById('title').style.display = '';
  44 + document.getElementById('link').style.display = 'none';
  45 +</script>
  46 +
  47 +</body>
  48 +</html>
0 49 \ No newline at end of file
... ...
common/components/nodge/eauth/src/views/widget.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\helpers\Html;
  4 +use yii\web\View;
  5 +
  6 +/** @var $this View */
  7 +/** @var $id string */
  8 +/** @var $services stdClass[] See EAuth::getServices() */
  9 +/** @var $action string */
  10 +/** @var $popup bool */
  11 +/** @var $assetBundle string Alias to AssetBundle */
  12 +
  13 +Yii::createObject(['class' => $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 +<div class="eauth" id="<?php echo $id; ?>">
  26 + <ul class="eauth-list">
  27 + <?php
  28 + foreach ($services as $name => $service) {
  29 + echo '<li class="eauth-service eauth-service-id-' . $service->id . '">';
  30 + echo Html::a($service->title, [$action, 'service' => $name], [
  31 + 'class' => 'eauth-service-link',
  32 + 'data-eauth-service' => $service->id,
  33 + ]);
  34 + echo '</li>';
  35 + }
  36 + ?>
  37 + </ul>
  38 +</div>
... ...
common/components/nodge/lightopenid/CHANGELOG.md 0 → 100644
  1 +# LightOpenID Change Log
  2 +
  3 +
  4 +## v1.1.2 (January 15, 2013)
  5 +
  6 +`fix` Fixed a bug in the proxy configuration.
  7 +
  8 +
  9 +## v1.1.1 (December 21, 2012)
  10 +
  11 +`add` Added support for overriding the initial URL XRDS lookup.
  12 +
  13 +
  14 +## v1.1.0 (December 02, 2012)
  15 +
  16 +`add` Added support for connecting through a proxy.
  17 +`add` Added support for an OpenID+OAuth hybrid protocol.
  18 +`add` Added SSL-validation support for HEAD-requests.
  19 +`fix` Fixed a bug in the attribute exchange implementation.
  20 +`fix` Fixed a bug in stream defaults after a HEAD request.
  21 +
  22 +
  23 +## v1.0.0 (June 08, 2012)
  24 +`fix` Fixed a bug causing validation failure when using streams.
... ...
common/components/nodge/lightopenid/LICENSE 0 → 100644
  1 +Copyright (c) 2010, Mewp
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
0 20 \ No newline at end of file
... ...
common/components/nodge/lightopenid/README.md 0 → 100644
  1 +# LightOpenID
  2 +
  3 +Lightweight PHP5 library for easy OpenID authentication.
  4 +
  5 +* `Version....:` [**1.1.2** :arrow_double_down:][1]
  6 + ( *see [the change log][2] for details* )
  7 +* `Released on:` January 15, 2013
  8 +* `Source code:` [Gitorious :link:][3]
  9 + &nbsp;
  10 + [GitHub :octocat:][4]
  11 +* `Homepage...:` http://code.google.com/p/lightopenid/
  12 +* `Author.....:` Mewp (http://mewp.s4w.pl/)
  13 +
  14 +[1]: https://github.com/iignatov/LightOpenID/archive/master.zip
  15 +[2]: http://github.com/iignatov/LightOpenID/blob/master/CHANGELOG.md
  16 +[3]: http://gitorious.org/lightopenid
  17 +[4]: http://github.com/iignatov/LightOpenID
  18 +
  19 +
  20 +## Quick start
  21 +
  22 +### Sign-on with OpenID in just 2 steps:
  23 +
  24 + 1. Authentication with the provider:
  25 +
  26 + ```php
  27 + $openid = new LightOpenID('my-host.example.org');
  28 +
  29 + $openid->identity = 'ID supplied by user';
  30 +
  31 + header('Location: ' . $openid->authUrl());
  32 + ```
  33 + 2. Verification:
  34 +
  35 + ```php
  36 + $openid = new LightOpenID('my-host.example.org');
  37 +
  38 + if ($openid->mode) {
  39 + echo $openid->validate() ? 'Logged in.' : 'Failed!';
  40 + }
  41 + ```
  42 +
  43 +### Support for AX and SREG extensions:
  44 +
  45 + To use the AX and SREG extensions, specify `$openid->required` and/or `$openid->optional`
  46 + before calling `$openid->authUrl()`. These are arrays, with values being AX schema paths
  47 + (the 'path' part of the URL). For example:
  48 +
  49 + ```php
  50 + $openid->required = array('namePerson/friendly', 'contact/email');
  51 + $openid->optional = array('namePerson/first');
  52 + ```
  53 +
  54 + Note that if the server supports only SREG or OpenID 1.1, these are automaticaly mapped
  55 + to SREG names. To get the values use:
  56 +
  57 + ```php
  58 + $openid->getAttributes();
  59 + ```
  60 +
  61 + For more information see [USAGE.md](http://github.com/iignatov/LightOpenID/blob/master/USAGE.md).
  62 +
  63 +
  64 +## Requirements
  65 +
  66 +This library requires PHP >= 5.1.2 with cURL or HTTP/HTTPS stream wrappers enabled.
  67 +
  68 +
  69 +## Features
  70 +
  71 +* Easy to use - you can code a functional client in less than ten lines of code.
  72 +* Uses cURL if avaiable, PHP-streams otherwise.
  73 +* Supports both OpenID 1.1 and 2.0.
  74 +* Supports Yadis discovery.
  75 +* Supports only stateless/dumb protocol.
  76 +* Works with PHP >= 5.
  77 +* Generates no errors with `error_reporting(E_ALL | E_STRICT)`.
  78 +
  79 +
  80 +## Links
  81 +
  82 +* [JavaScript OpenID Selector](http://code.google.com/p/openid-selector/) -
  83 + simple user interface that can be used with LightOpenID.
  84 +* [HybridAuth](http://hybridauth.sourceforge.net/) -
  85 + easy to install and use social sign on PHP library, which uses LightOpenID.
  86 +* [OpenID Dev Specifications](http://openid.net/developers/specs/) -
  87 + documentation for the OpenID extensions and related topics.
  88 +
  89 +
  90 +## License
  91 +
  92 +[LightOpenID](http://github.com/iignatov/LightOpenID)
  93 +is an open source software available under the
  94 +[MIT License](http://opensource.org/licenses/mit-license.php).
... ...
common/components/nodge/lightopenid/USAGE.md 0 → 100644
  1 +# LightOpenID Quick Start
  2 +
  3 +
  4 +## Sign-on with OpenID is a two step process:
  5 +
  6 + 1. Step one is authentication with the provider:
  7 +
  8 + ```php
  9 + $openid = new LightOpenID('my-host.example.org');
  10 +
  11 + $openid->identity = 'ID supplied by the user';
  12 +
  13 + header('Location: ' . $openid->authUrl());
  14 + ```
  15 +
  16 + The provider then sends various parameters via GET, one of which is `openid_mode`.
  17 +
  18 + 2. Step two is verification:
  19 +
  20 + ```php
  21 + $openid = new LightOpenID('my-host.example.org');
  22 +
  23 + if ($openid->mode) {
  24 + echo $openid->validate() ? 'Logged in.' : 'Failed!';
  25 + }
  26 + ```
  27 +
  28 +
  29 +### Notes:
  30 +
  31 + Change 'my-host.example.org' to your domain name. Do NOT use `$_SERVER['HTTP_HOST']`
  32 + for that, unless you know what you're doing.
  33 +
  34 + Optionally, you can set `$returnUrl` and `$realm` (or `$trustRoot`, which is an alias).
  35 + The default values for those are:
  36 +
  37 + ```php
  38 + $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
  39 + $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI'];
  40 + ```
  41 +
  42 + If you don't know their meaning, refer to any OpenID tutorial, or specification.
  43 +
  44 +
  45 +## Basic configuration options:
  46 +
  47 +<table>
  48 + <tr>
  49 + <th>name</th>
  50 + <th>description</th>
  51 + </tr>
  52 + <tr>
  53 + <td>identity</td>
  54 + <td>
  55 + Sets (or gets) the identity supplied by an user. Set it
  56 + before calling authUrl(), and get after validate().
  57 + </td>
  58 + </tr>
  59 + <tr>
  60 + <td>returnUrl</td>
  61 + <td>
  62 + Users will be redirected to this url after they complete
  63 + authentication with their provider. Default: current url.
  64 + </td>
  65 + </tr>
  66 + <tr>
  67 + <td>realm</td>
  68 + <td>
  69 + The realm user is signing into. Providers usually say
  70 + "You are sgning into $realm". Must be in the same domain
  71 + as returnUrl. Usually, this should be the host part of
  72 + your site's url. And that's the default.
  73 + </td>
  74 + </tr>
  75 + <tr>
  76 + <td>required and optional</td>
  77 + <td>
  78 + Attempts to fetch more information about an user.
  79 + See <a href="#common-ax-attributes">Common AX attributes</a>.
  80 + </td>
  81 + </tr>
  82 + <tr>
  83 + <td>verify_peer</td>
  84 + <td>
  85 + When using https, attempts to verify peer's certificate.
  86 + See <a href="http://php.net/manual/en/function.curl-setopt.php">CURLOPT_SSL_VERIFYPEER</a>.
  87 + </td>
  88 + </tr>
  89 + <tr>
  90 + <td>cainfo and capath</td>
  91 + <td>
  92 + When verify_peer is true, sets the CA info file and directory.
  93 + See <a href="http://php.net/manual/en/function.curl-setopt.php">CURLOPT_SSL_CAINFO</a>
  94 + and <a href="http://php.net/manual/en/function.curl-setopt.php">CURLOPT_SSL_CAPATH</a>.
  95 + </td>
  96 + </tr>
  97 +</table>
  98 +
  99 +
  100 +## AX and SREG extensions are supported:
  101 +
  102 + To use them, specify `$openid->required` and/or `$openid->optional` before calling
  103 + `$openid->authUrl()`. These are arrays, with values being AX schema paths (the 'path'
  104 + part of the URL). For example:
  105 +
  106 + ```php
  107 + $openid->required = array('namePerson/friendly', 'contact/email');
  108 + $openid->optional = array('namePerson/first');
  109 + ```
  110 +
  111 + Note that if the server supports only SREG or OpenID 1.1, these are automaticaly mapped
  112 + to SREG names, so that user doesn't have to know anything about the server.
  113 + To get the values, use `$openid->getAttributes()`.
  114 +
  115 +
  116 +### Common AX attributes
  117 +
  118 + Here is a list of the more common AX attributes (from [axschema.org](http://www.axschema.org/types/)):
  119 +
  120 + Name | Meaning
  121 + ------------------------|---------------
  122 + namePerson/friendly | Alias/Username
  123 + contact/email | Email
  124 + namePerson | Full name
  125 + birthDate | Birth date
  126 + person/gender | Gender
  127 + contact/postalCode/home | Postal code
  128 + contact/country/home | Country
  129 + pref/language | Language
  130 + pref/timezone | Time zone
  131 +
  132 + Note that even if you mark some field as required, there is no guarantee that you'll get any
  133 + information from a provider. Not all providers support all of these attributes, and some don't
  134 + support these extensions at all.
  135 +
  136 + Google, for example, completely ignores optional parameters, and for the required ones, it supports,
  137 + according to [it's website](http://code.google.com/apis/accounts/docs/OpenID.html):
  138 +
  139 + * namePerson/first (first name)
  140 + * namePerson/last (last name)
  141 + * contact/country/home
  142 + * contact/email
  143 + * pref/language
  144 +
... ...
common/components/nodge/lightopenid/composer.json 0 → 100644
  1 +{
  2 + "name": "nodge/lightopenid",
  3 + "description": "Lightweight PHP5 library for easy OpenID authentication.",
  4 + "keywords": ["openid", "authentication"],
  5 + "homepage": "https://github.com/Nodge/LightOpenID",
  6 + "type": "library",
  7 + "license": "MIT License",
  8 + "authors": [
  9 + {
  10 + "name": "Mewp",
  11 + "homepage": "http://code.google.com/p/lightopenid/"
  12 + },
  13 + {
  14 + "name": "Ignat Ignatov",
  15 + "homepage": "https://github.com/iignatov/LightOpenID"
  16 + }
  17 + ],
  18 + "require": {
  19 + "php": ">=5.2"
  20 + },
  21 + "autoload": {
  22 + "classmap": ["openid.php", "provider/provider.php"]
  23 + }
  24 +}
0 25 \ No newline at end of file
... ...
common/components/nodge/lightopenid/example-google.php 0 → 100644
  1 +<?php
  2 +# Logging in with Google accounts requires setting special identity,
  3 +# so this example shows how to do it.
  4 +require 'openid.php';
  5 +
  6 +try {
  7 + # Change 'example.org' to your domain name.
  8 + $domain = 'example.org';
  9 + $openid = new LightOpenID($domain);
  10 +
  11 + if (!$openid->mode) {
  12 + if (isset($_GET['login'])) {
  13 + $openid->identity = 'https://www.google.com/accounts/o8/id';
  14 + header('Location: ' . $openid->authUrl());
  15 + }
  16 +?>
  17 +<form action="?login" method="post">
  18 + <button>Login with Google</button>
  19 +</form>
  20 +<?php
  21 + } elseif($openid->mode == 'cancel') {
  22 + echo 'User has canceled authentication!';
  23 + } else {
  24 + echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.';
  25 + }
  26 +} catch(ErrorException $e) {
  27 + echo $e->getMessage();
  28 +}
... ...
common/components/nodge/lightopenid/example-google_apps.php 0 → 100644
  1 +<?php
  2 +# Logging in with Google Apps accounts requires setting special identity
  3 +# and XRDS override, so this example shows how to do it.
  4 +require 'openid.php';
  5 +
  6 +try {
  7 + # Change 'example.org' to your domain name.
  8 + $domain = 'example.org';
  9 + $openid = new LightOpenID($domain);
  10 + $openid->xrdsOverride = array(
  11 + '#^http://' . $domain . '/openid\?id=\d+$#',
  12 + 'https://www.google.com/accounts/o8/site-xrds?hd=' . $domain
  13 + );
  14 +
  15 + if (!$openid->mode) {
  16 + if (isset($_GET['login'])) {
  17 + $openid->identity = 'https://www.google.com/accounts/o8/site-xrds?hd=' . $domain;
  18 + header('Location: ' . $openid->authUrl());
  19 + }
  20 +?>
  21 +<form action="?login" method="post">
  22 + <button>Login with Google</button>
  23 +</form>
  24 +<?php
  25 + } elseif($openid->mode == 'cancel') {
  26 + echo 'User has canceled authentication!';
  27 + } else {
  28 + echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.';
  29 + }
  30 +} catch(ErrorException $e) {
  31 + echo $e->getMessage();
  32 +}
... ...
common/components/nodge/lightopenid/example.php 0 → 100644
  1 +<?php
  2 +require 'openid.php';
  3 +try {
  4 + # Change 'localhost' to your domain name.
  5 + $openid = new LightOpenID('localhost');
  6 + if(!$openid->mode) {
  7 + if(isset($_POST['openid_identifier'])) {
  8 + $openid->identity = $_POST['openid_identifier'];
  9 + # The following two lines request email, full name, and a nickname
  10 + # from the provider. Remove them if you don't need that data.
  11 + $openid->required = array('contact/email');
  12 + $openid->optional = array('namePerson', 'namePerson/friendly');
  13 + header('Location: ' . $openid->authUrl());
  14 + }
  15 +?>
  16 +<form action="" method="post">
  17 + OpenID: <input type="text" name="openid_identifier" /> <button>Submit</button>
  18 +</form>
  19 +<?php
  20 + } elseif($openid->mode == 'cancel') {
  21 + echo 'User has canceled authentication!';
  22 + } else {
  23 + echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.';
  24 + print_r($openid->getAttributes());
  25 + }
  26 +} catch(ErrorException $e) {
  27 + echo $e->getMessage();
  28 +}
... ...
common/components/nodge/lightopenid/openid.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * This class provides a simple interface for OpenID 1.1/2.0 authentication.
  4 + *
  5 + * It requires PHP >= 5.1.2 with cURL or HTTP/HTTPS stream wrappers enabled.
  6 + *
  7 + * @version v1.1.2 2013-01-15
  8 + * @link http://gitorious.org/lightopenid Official Repo
  9 + * @link http://github.com/iignatov/LightOpenID GitHub Clone
  10 + * @author Mewp
  11 + * @copyright Copyright (c) 2010, Mewp
  12 + * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13 + */
  14 +class LightOpenID
  15 +{
  16 + public $returnUrl
  17 + , $required = array()
  18 + , $optional = array()
  19 + , $verify_peer = null
  20 + , $capath = null
  21 + , $cainfo = null
  22 + , $data
  23 + , $oauth = array();
  24 + private $identity, $claimed_id;
  25 + protected $server, $version, $trustRoot, $aliases, $identifier_select = false
  26 + , $ax = false, $sreg = false, $setup_url = null, $headers = array(), $proxy = null
  27 + , $xrds_override_pattern = null, $xrds_override_replacement = null;
  28 + static protected $ax_to_sreg = array(
  29 + 'namePerson/friendly' => 'nickname',
  30 + 'contact/email' => 'email',
  31 + 'namePerson' => 'fullname',
  32 + 'birthDate' => 'dob',
  33 + 'person/gender' => 'gender',
  34 + 'contact/postalCode/home' => 'postcode',
  35 + 'contact/country/home' => 'country',
  36 + 'pref/language' => 'language',
  37 + 'pref/timezone' => 'timezone',
  38 + );
  39 +
  40 + function __construct($host, $proxy = null)
  41 + {
  42 + $this->trustRoot = (strpos($host, '://') ? $host : 'http://' . $host);
  43 + if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
  44 + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
  45 + && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
  46 + ) {
  47 + $this->trustRoot = (strpos($host, '://') ? $host : 'https://' . $host);
  48 + }
  49 +
  50 + if(($host_end = strpos($this->trustRoot, '/', 8)) !== false) {
  51 + $this->trustRoot = substr($this->trustRoot, 0, $host_end);
  52 + }
  53 +
  54 + $this->set_proxy($proxy);
  55 +
  56 + $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
  57 + $this->returnUrl = $this->trustRoot . $uri;
  58 +
  59 + $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
  60 +
  61 + if(!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
  62 + throw new ErrorException('You must have either https wrappers or curl enabled.');
  63 + }
  64 + }
  65 +
  66 + function __set($name, $value)
  67 + {
  68 + switch ($name) {
  69 + case 'identity':
  70 + if (strlen($value = trim((String) $value))) {
  71 + if (preg_match('#^xri:/*#i', $value, $m)) {
  72 + $value = substr($value, strlen($m[0]));
  73 + } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
  74 + $value = "http://$value";
  75 + }
  76 + if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
  77 + $value .= '/';
  78 + }
  79 + }
  80 + $this->$name = $this->claimed_id = $value;
  81 + break;
  82 + case 'trustRoot':
  83 + case 'realm':
  84 + $this->trustRoot = trim($value);
  85 + break;
  86 + case 'xrdsOverride':
  87 + if (is_array($value)) {
  88 + list($pattern, $replacement) = $value;
  89 + $this->xrds_override_pattern = $pattern;
  90 + $this->xrds_override_replacement = $replacement;
  91 + } else {
  92 + trigger_error('Invalid value specified for "xrdsOverride".', E_USER_ERROR);
  93 + }
  94 + break;
  95 + }
  96 + }
  97 +
  98 + function __get($name)
  99 + {
  100 + switch ($name) {
  101 + case 'identity':
  102 + # We return claimed_id instead of identity,
  103 + # because the developer should see the claimed identifier,
  104 + # i.e. what he set as identity, not the op-local identifier (which is what we verify)
  105 + return $this->claimed_id;
  106 + case 'trustRoot':
  107 + case 'realm':
  108 + return $this->trustRoot;
  109 + case 'mode':
  110 + return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
  111 + }
  112 + }
  113 +
  114 + function set_proxy($proxy)
  115 + {
  116 + if (!empty($proxy)) {
  117 + // When the proxy is a string - try to parse it.
  118 + if (!is_array($proxy)) {
  119 + $proxy = parse_url($proxy);
  120 + }
  121 +
  122 + // Check if $proxy is valid after the parsing.
  123 + if ($proxy && !empty($proxy['host'])) {
  124 + // Make sure that a valid port number is specified.
  125 + if (array_key_exists('port', $proxy)) {
  126 + if (!is_int($proxy['port'])) {
  127 + $proxy['port'] = is_numeric($proxy['port']) ? intval($proxy['port']) : 0;
  128 + }
  129 +
  130 + if ($proxy['port'] <= 0) {
  131 + throw new ErrorException('The specified proxy port number is invalid.');
  132 + }
  133 + }
  134 +
  135 + $this->proxy = $proxy;
  136 + }
  137 + }
  138 + }
  139 +
  140 + /**
  141 + * Checks if the server specified in the url exists.
  142 + *
  143 + * @param $url url to check
  144 + * @return true, if the server exists; false otherwise
  145 + */
  146 + function hostExists($url)
  147 + {
  148 + if (strpos($url, '/') === false) {
  149 + $server = $url;
  150 + } else {
  151 + $server = @parse_url($url, PHP_URL_HOST);
  152 + }
  153 +
  154 + if (!$server) {
  155 + return false;
  156 + }
  157 +
  158 + return !!gethostbynamel($server);
  159 + }
  160 +
  161 + protected function request_curl($url, $method='GET', $params=array(), $update_claimed_id)
  162 + {
  163 + $params = http_build_query($params, '', '&');
  164 + $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
  165 + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  166 + curl_setopt($curl, CURLOPT_HEADER, false);
  167 + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  168 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  169 + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
  170 +
  171 + if (!empty($this->proxy)) {
  172 + curl_setopt($curl, CURLOPT_PROXY, $this->proxy['host']);
  173 +
  174 + if (!empty($this->proxy['port'])) {
  175 + curl_setopt($curl, CURLOPT_PROXYPORT, $this->proxy['port']);
  176 + }
  177 +
  178 + if (!empty($this->proxy['user'])) {
  179 + curl_setopt($curl, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
  180 + }
  181 + }
  182 +
  183 + if($this->verify_peer !== null) {
  184 + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
  185 + if($this->capath) {
  186 + curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
  187 + }
  188 +
  189 + if($this->cainfo) {
  190 + curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
  191 + }
  192 + }
  193 +
  194 + if ($method == 'POST') {
  195 + curl_setopt($curl, CURLOPT_POST, true);
  196 + curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
  197 + } elseif ($method == 'HEAD') {
  198 + curl_setopt($curl, CURLOPT_HEADER, true);
  199 + curl_setopt($curl, CURLOPT_NOBODY, true);
  200 + } else {
  201 + curl_setopt($curl, CURLOPT_HEADER, true);
  202 + curl_setopt($curl, CURLOPT_HTTPGET, true);
  203 + }
  204 + $response = curl_exec($curl);
  205 +
  206 + if($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
  207 + curl_setopt($curl, CURLOPT_HTTPGET, true);
  208 + $response = curl_exec($curl);
  209 + $response = substr($response, 0, strpos($response, "\r\n\r\n"));
  210 + }
  211 +
  212 + if($method == 'HEAD' || $method == 'GET') {
  213 + $header_response = $response;
  214 +
  215 + # If it's a GET request, we want to only parse the header part.
  216 + if($method == 'GET') {
  217 + $header_response = substr($response, 0, strpos($response, "\r\n\r\n"));
  218 + }
  219 +
  220 + $headers = array();
  221 + foreach(explode("\n", $header_response) as $header) {
  222 + $pos = strpos($header,':');
  223 + if ($pos !== false) {
  224 + $name = strtolower(trim(substr($header, 0, $pos)));
  225 + $headers[$name] = trim(substr($header, $pos+1));
  226 + }
  227 + }
  228 +
  229 + if($update_claimed_id) {
  230 + # Updating claimed_id in case of redirections.
  231 + $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
  232 + if($effective_url != $url) {
  233 + $this->identity = $this->claimed_id = $effective_url;
  234 + }
  235 + }
  236 +
  237 + if($method == 'HEAD') {
  238 + return $headers;
  239 + } else {
  240 + $this->headers = $headers;
  241 + }
  242 + }
  243 +
  244 + if (curl_errno($curl)) {
  245 + throw new ErrorException(curl_error($curl), curl_errno($curl));
  246 + }
  247 +
  248 + return $response;
  249 + }
  250 +
  251 + protected function parse_header_array($array, $update_claimed_id)
  252 + {
  253 + $headers = array();
  254 + foreach($array as $header) {
  255 + $pos = strpos($header,':');
  256 + if ($pos !== false) {
  257 + $name = strtolower(trim(substr($header, 0, $pos)));
  258 + $headers[$name] = trim(substr($header, $pos+1));
  259 +
  260 + # Following possible redirections. The point is just to have
  261 + # claimed_id change with them, because the redirections
  262 + # are followed automatically.
  263 + # We ignore redirections with relative paths.
  264 + # If any known provider uses them, file a bug report.
  265 + if($name == 'location' && $update_claimed_id) {
  266 + if(strpos($headers[$name], 'http') === 0) {
  267 + $this->identity = $this->claimed_id = $headers[$name];
  268 + } elseif($headers[$name][0] == '/') {
  269 + $parsed_url = parse_url($this->claimed_id);
  270 + $this->identity =
  271 + $this->claimed_id = $parsed_url['scheme'] . '://'
  272 + . $parsed_url['host']
  273 + . $headers[$name];
  274 + }
  275 + }
  276 + }
  277 + }
  278 + return $headers;
  279 + }
  280 +
  281 + protected function request_streams($url, $method='GET', $params=array(), $update_claimed_id)
  282 + {
  283 + if(!$this->hostExists($url)) {
  284 + throw new ErrorException("Could not connect to $url.", 404);
  285 + }
  286 +
  287 + $params = http_build_query($params, '', '&');
  288 + switch($method) {
  289 + case 'GET':
  290 + $opts = array(
  291 + 'http' => array(
  292 + 'method' => 'GET',
  293 + 'header' => 'Accept: application/xrds+xml, */*',
  294 + 'ignore_errors' => true,
  295 + ), 'ssl' => array(
  296 + 'CN_match' => parse_url($url, PHP_URL_HOST),
  297 + ),
  298 + );
  299 + $url = $url . ($params ? '?' . $params : '');
  300 + if (!empty($this->proxy)) {
  301 + $opts['http']['proxy'] = $this->proxy_url();
  302 + }
  303 + break;
  304 + case 'POST':
  305 + $opts = array(
  306 + 'http' => array(
  307 + 'method' => 'POST',
  308 + 'header' => 'Content-type: application/x-www-form-urlencoded',
  309 + 'content' => $params,
  310 + 'ignore_errors' => true,
  311 + ), 'ssl' => array(
  312 + 'CN_match' => parse_url($url, PHP_URL_HOST),
  313 + ),
  314 + );
  315 + if (!empty($this->proxy)) {
  316 + $opts['http']['proxy'] = $this->proxy_url();
  317 + }
  318 + break;
  319 + case 'HEAD':
  320 + // We want to send a HEAD request, but since get_headers() doesn't
  321 + // accept $context parameter, we have to change the defaults.
  322 + $default = stream_context_get_options(stream_context_get_default());
  323 +
  324 + // PHP does not reset all options. Instead, it just sets the options
  325 + // available in the passed array, therefore set the defaults manually.
  326 + $default += array(
  327 + 'http' => array(),
  328 + 'ssl' => array()
  329 + );
  330 + $default['http'] += array(
  331 + 'method' => 'GET',
  332 + 'header' => '',
  333 + 'ignore_errors' => false
  334 + );
  335 + $default['ssl'] += array(
  336 + 'CN_match' => ''
  337 + );
  338 +
  339 + $opts = array(
  340 + 'http' => array(
  341 + 'method' => 'HEAD',
  342 + 'header' => 'Accept: application/xrds+xml, */*',
  343 + 'ignore_errors' => true,
  344 + ),
  345 + 'ssl' => array(
  346 + 'CN_match' => parse_url($url, PHP_URL_HOST)
  347 + )
  348 + );
  349 +
  350 + // Enable validation of the SSL certificates.
  351 + if ($this->verify_peer) {
  352 + $default['ssl'] += array(
  353 + 'verify_peer' => false,
  354 + 'capath' => '',
  355 + 'cafile' => ''
  356 + );
  357 + $opts['ssl'] += array(
  358 + 'verify_peer' => true,
  359 + 'capath' => $this->capath,
  360 + 'cafile' => $this->cainfo
  361 + );
  362 + }
  363 +
  364 + // Change the stream context options.
  365 + stream_context_get_default($opts);
  366 +
  367 + $headers = get_headers($url . ($params ? '?' . $params : ''));
  368 +
  369 + // Restore the stream context options.
  370 + stream_context_get_default($default);
  371 +
  372 + if (!empty($headers)) {
  373 + if (intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) {
  374 + // The server doesn't support HEAD - emulate it with a GET.
  375 + $args = func_get_args();
  376 + $args[1] = 'GET';
  377 + call_user_func_array(array($this, 'request_streams'), $args);
  378 + $headers = $this->headers;
  379 + } else {
  380 + $headers = $this->parse_header_array($headers, $update_claimed_id);
  381 + }
  382 + } else {
  383 + $headers = array();
  384 + }
  385 +
  386 + return $headers;
  387 + }
  388 +
  389 + if ($this->verify_peer) {
  390 + $opts['ssl'] += array(
  391 + 'verify_peer' => true,
  392 + 'capath' => $this->capath,
  393 + 'cafile' => $this->cainfo
  394 + );
  395 + }
  396 +
  397 + $context = stream_context_create ($opts);
  398 + $data = file_get_contents($url, false, $context);
  399 + # This is a hack for providers who don't support HEAD requests.
  400 + # It just creates the headers array for the last request in $this->headers.
  401 + if(isset($http_response_header)) {
  402 + $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id);
  403 + }
  404 +
  405 + return $data;
  406 + }
  407 +
  408 + protected function request($url, $method='GET', $params=array(), $update_claimed_id=false)
  409 + {
  410 + if (function_exists('curl_init')
  411 + && (!in_array('https', stream_get_wrappers()) || !ini_get('safe_mode') && !ini_get('open_basedir'))
  412 + ) {
  413 + return $this->request_curl($url, $method, $params, $update_claimed_id);
  414 + }
  415 + return $this->request_streams($url, $method, $params, $update_claimed_id);
  416 + }
  417 +
  418 + protected function proxy_url()
  419 + {
  420 + $result = '';
  421 +
  422 + if (!empty($this->proxy)) {
  423 + $result = $this->proxy['host'];
  424 +
  425 + if (!empty($this->proxy['port'])) {
  426 + $result = $result . ':' . $this->proxy['port'];
  427 + }
  428 +
  429 + if (!empty($this->proxy['user'])) {
  430 + $result = $this->proxy['user'] . ':' . $this->proxy['pass'] . '@' . $result;
  431 + }
  432 +
  433 + $result = 'http://' . $result;
  434 + }
  435 +
  436 + return $result;
  437 + }
  438 +
  439 + protected function build_url($url, $parts)
  440 + {
  441 + if (isset($url['query'], $parts['query'])) {
  442 + $parts['query'] = $url['query'] . '&' . $parts['query'];
  443 + }
  444 +
  445 + $url = $parts + $url;
  446 + $url = $url['scheme'] . '://'
  447 + . (empty($url['username'])?''
  448 + :(empty($url['password'])? "{$url['username']}@"
  449 + :"{$url['username']}:{$url['password']}@"))
  450 + . $url['host']
  451 + . (empty($url['port'])?'':":{$url['port']}")
  452 + . (empty($url['path'])?'':$url['path'])
  453 + . (empty($url['query'])?'':"?{$url['query']}")
  454 + . (empty($url['fragment'])?'':"#{$url['fragment']}");
  455 + return $url;
  456 + }
  457 +
  458 + /**
  459 + * Helper function used to scan for <meta>/<link> tags and extract information
  460 + * from them
  461 + */
  462 + protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
  463 + {
  464 + preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
  465 + preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
  466 +
  467 + $result = array_merge($matches1[1], $matches2[1]);
  468 + return empty($result)?false:$result[0];
  469 + }
  470 +
  471 + /**
  472 + * Performs Yadis and HTML discovery. Normally not used.
  473 + * @param $url Identity URL.
  474 + * @return String OP Endpoint (i.e. OpenID provider address).
  475 + * @throws ErrorException
  476 + */
  477 + function discover($url)
  478 + {
  479 + if (!$url) throw new ErrorException('No identity supplied.');
  480 + # Use xri.net proxy to resolve i-name identities
  481 + if (!preg_match('#^https?:#', $url)) {
  482 + $url = "https://xri.net/$url";
  483 + }
  484 +
  485 + # We save the original url in case of Yadis discovery failure.
  486 + # It can happen when we'll be lead to an XRDS document
  487 + # which does not have any OpenID2 services.
  488 + $originalUrl = $url;
  489 +
  490 + # A flag to disable yadis discovery in case of failure in headers.
  491 + $yadis = true;
  492 +
  493 + # Allows optional regex replacement of the URL, e.g. to use Google Apps
  494 + # as an OpenID provider without setting up XRDS on the domain hosting.
  495 + if (!is_null($this->xrds_override_pattern) && !is_null($this->xrds_override_replacement)) {
  496 + $url = preg_replace($this->xrds_override_pattern, $this->xrds_override_replacement, $url);
  497 + }
  498 +
  499 + # We'll jump a maximum of 5 times, to avoid endless redirections.
  500 + for ($i = 0; $i < 5; $i ++) {
  501 + if ($yadis) {
  502 + $headers = $this->request($url, 'HEAD', array(), true);
  503 +
  504 + $next = false;
  505 + if (isset($headers['x-xrds-location'])) {
  506 + $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
  507 + $next = true;
  508 + }
  509 +
  510 + if (isset($headers['content-type'])
  511 + && (strpos($headers['content-type'], 'application/xrds+xml') !== false
  512 + || strpos($headers['content-type'], 'text/xml') !== false)
  513 + ) {
  514 + # Apparently, some providers return XRDS documents as text/html.
  515 + # While it is against the spec, allowing this here shouldn't break
  516 + # compatibility with anything.
  517 + # ---
  518 + # Found an XRDS document, now let's find the server, and optionally delegate.
  519 + $content = $this->request($url, 'GET');
  520 +
  521 + preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m);
  522 + foreach($m[1] as $content) {
  523 + $content = ' ' . $content; # The space is added, so that strpos doesn't return 0.
  524 +
  525 + # OpenID 2
  526 + $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#');
  527 + if(preg_match('#<Type>\s*'.$ns.'(server|signon)\s*</Type>#s', $content, $type)) {
  528 + if ($type[1] == 'server') $this->identifier_select = true;
  529 +
  530 + preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
  531 + preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate);
  532 + if (empty($server)) {
  533 + return false;
  534 + }
  535 + # Does the server advertise support for either AX or SREG?
  536 + $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>');
  537 + $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
  538 + || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
  539 +
  540 + $server = $server[1];
  541 + if (isset($delegate[2])) $this->identity = trim($delegate[2]);
  542 + $this->version = 2;
  543 +
  544 + $this->server = $server;
  545 + return $server;
  546 + }
  547 +
  548 + # OpenID 1.1
  549 + $ns = preg_quote('http://openid.net/signon/1.1', '#');
  550 + if (preg_match('#<Type>\s*'.$ns.'\s*</Type>#s', $content)) {
  551 +
  552 + preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
  553 + preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
  554 + if (empty($server)) {
  555 + return false;
  556 + }
  557 + # AX can be used only with OpenID 2.0, so checking only SREG
  558 + $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
  559 + || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
  560 +
  561 + $server = $server[1];
  562 + if (isset($delegate[1])) $this->identity = $delegate[1];
  563 + $this->version = 1;
  564 +
  565 + $this->server = $server;
  566 + return $server;
  567 + }
  568 + }
  569 +
  570 + $next = true;
  571 + $yadis = false;
  572 + $url = $originalUrl;
  573 + $content = null;
  574 + break;
  575 + }
  576 + if ($next) continue;
  577 +
  578 + # There are no relevant information in headers, so we search the body.
  579 + $content = $this->request($url, 'GET', array(), true);
  580 +
  581 + if (isset($this->headers['x-xrds-location'])) {
  582 + $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location'])));
  583 + continue;
  584 + }
  585 +
  586 + $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
  587 + if ($location) {
  588 + $url = $this->build_url(parse_url($url), parse_url($location));
  589 + continue;
  590 + }
  591 + }
  592 +
  593 + if (!$content) $content = $this->request($url, 'GET');
  594 +
  595 + # At this point, the YADIS Discovery has failed, so we'll switch
  596 + # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
  597 + $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
  598 + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
  599 + $this->version = 2;
  600 +
  601 + if (!$server) {
  602 + # The same with openid 1.1
  603 + $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
  604 + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
  605 + $this->version = 1;
  606 + }
  607 +
  608 + if ($server) {
  609 + # We found an OpenID2 OP Endpoint
  610 + if ($delegate) {
  611 + # We have also found an OP-Local ID.
  612 + $this->identity = $delegate;
  613 + }
  614 + $this->server = $server;
  615 + return $server;
  616 + }
  617 +
  618 + throw new ErrorException("No OpenID Server found at $url", 404);
  619 + }
  620 + throw new ErrorException('Endless redirection!', 500);
  621 + }
  622 +
  623 + protected function sregParams()
  624 + {
  625 + $params = array();
  626 + # We always use SREG 1.1, even if the server is advertising only support for 1.0.
  627 + # That's because it's fully backwards compatibile with 1.0, and some providers
  628 + # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
  629 + $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
  630 + if ($this->required) {
  631 + $params['openid.sreg.required'] = array();
  632 + foreach ($this->required as $required) {
  633 + if (!isset(self::$ax_to_sreg[$required])) continue;
  634 + $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
  635 + }
  636 + $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
  637 + }
  638 +
  639 + if ($this->optional) {
  640 + $params['openid.sreg.optional'] = array();
  641 + foreach ($this->optional as $optional) {
  642 + if (!isset(self::$ax_to_sreg[$optional])) continue;
  643 + $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
  644 + }
  645 + $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
  646 + }
  647 + return $params;
  648 + }
  649 +
  650 + protected function axParams()
  651 + {
  652 + $params = array();
  653 + if ($this->required || $this->optional) {
  654 + $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
  655 + $params['openid.ax.mode'] = 'fetch_request';
  656 + $this->aliases = array();
  657 + $counts = array();
  658 + $required = array();
  659 + $optional = array();
  660 + foreach (array('required','optional') as $type) {
  661 + foreach ($this->$type as $alias => $field) {
  662 + if (is_int($alias)) $alias = strtr($field, '/', '_');
  663 + $this->aliases[$alias] = 'http://axschema.org/' . $field;
  664 + if (empty($counts[$alias])) $counts[$alias] = 0;
  665 + $counts[$alias] += 1;
  666 + ${$type}[] = $alias;
  667 + }
  668 + }
  669 + foreach ($this->aliases as $alias => $ns) {
  670 + $params['openid.ax.type.' . $alias] = $ns;
  671 + }
  672 + foreach ($counts as $alias => $count) {
  673 + if ($count == 1) continue;
  674 + $params['openid.ax.count.' . $alias] = $count;
  675 + }
  676 +
  677 + # Don't send empty ax.requied and ax.if_available.
  678 + # Google and possibly other providers refuse to support ax when one of these is empty.
  679 + if($required) {
  680 + $params['openid.ax.required'] = implode(',', $required);
  681 + }
  682 + if($optional) {
  683 + $params['openid.ax.if_available'] = implode(',', $optional);
  684 + }
  685 + }
  686 + return $params;
  687 + }
  688 +
  689 + protected function authUrl_v1($immediate)
  690 + {
  691 + $returnUrl = $this->returnUrl;
  692 + # If we have an openid.delegate that is different from our claimed id,
  693 + # we need to somehow preserve the claimed id between requests.
  694 + # The simplest way is to just send it along with the return_to url.
  695 + if($this->identity != $this->claimed_id) {
  696 + $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
  697 + }
  698 +
  699 + $params = array(
  700 + 'openid.return_to' => $returnUrl,
  701 + 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
  702 + 'openid.identity' => $this->identity,
  703 + 'openid.trust_root' => $this->trustRoot,
  704 + ) + $this->sregParams();
  705 +
  706 + return $this->build_url(parse_url($this->server)
  707 + , array('query' => http_build_query($params, '', '&')));
  708 + }
  709 +
  710 + protected function authUrl_v2($immediate)
  711 + {
  712 + $params = array(
  713 + 'openid.ns' => 'http://specs.openid.net/auth/2.0',
  714 + 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
  715 + 'openid.return_to' => $this->returnUrl,
  716 + 'openid.realm' => $this->trustRoot,
  717 + );
  718 +
  719 + if ($this->ax) {
  720 + $params += $this->axParams();
  721 + }
  722 +
  723 + if ($this->sreg) {
  724 + $params += $this->sregParams();
  725 + }
  726 +
  727 + if (!$this->ax && !$this->sreg) {
  728 + # If OP doesn't advertise either SREG, nor AX, let's send them both
  729 + # in worst case we don't get anything in return.
  730 + $params += $this->axParams() + $this->sregParams();
  731 + }
  732 +
  733 + if (!empty($this->oauth) && is_array($this->oauth)) {
  734 + $params['openid.ns.oauth'] = 'http://specs.openid.net/extensions/oauth/1.0';
  735 + $params['openid.oauth.consumer'] = str_replace(array('http://', 'https://'), '', $this->trustRoot);
  736 + $params['openid.oauth.scope'] = implode(' ', $this->oauth);
  737 + }
  738 +
  739 + if ($this->identifier_select) {
  740 + $params['openid.identity'] = $params['openid.claimed_id']
  741 + = 'http://specs.openid.net/auth/2.0/identifier_select';
  742 + } else {
  743 + $params['openid.identity'] = $this->identity;
  744 + $params['openid.claimed_id'] = $this->claimed_id;
  745 + }
  746 +
  747 + return $this->build_url(parse_url($this->server)
  748 + , array('query' => http_build_query($params, '', '&')));
  749 + }
  750 +
  751 + /**
  752 + * Returns authentication url. Usually, you want to redirect your user to it.
  753 + * @return String The authentication url.
  754 + * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1.
  755 + * @throws ErrorException
  756 + */
  757 + function authUrl($immediate = false)
  758 + {
  759 + if ($this->setup_url && !$immediate) return $this->setup_url;
  760 + if (!$this->server) $this->discover($this->identity);
  761 +
  762 + if ($this->version == 2) {
  763 + return $this->authUrl_v2($immediate);
  764 + }
  765 + return $this->authUrl_v1($immediate);
  766 + }
  767 +
  768 + /**
  769 + * Performs OpenID verification with the OP.
  770 + * @return Bool Whether the verification was successful.
  771 + * @throws ErrorException
  772 + */
  773 + function validate()
  774 + {
  775 + # If the request was using immediate mode, a failure may be reported
  776 + # by presenting user_setup_url (for 1.1) or reporting
  777 + # mode 'setup_needed' (for 2.0). Also catching all modes other than
  778 + # id_res, in order to avoid throwing errors.
  779 + if(isset($this->data['openid_user_setup_url'])) {
  780 + $this->setup_url = $this->data['openid_user_setup_url'];
  781 + return false;
  782 + }
  783 + if($this->mode != 'id_res') {
  784 + return false;
  785 + }
  786 +
  787 + $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
  788 + $params = array(
  789 + 'openid.assoc_handle' => $this->data['openid_assoc_handle'],
  790 + 'openid.signed' => $this->data['openid_signed'],
  791 + 'openid.sig' => $this->data['openid_sig'],
  792 + );
  793 +
  794 + if (isset($this->data['openid_ns'])) {
  795 + # We're dealing with an OpenID 2.0 server, so let's set an ns
  796 + # Even though we should know location of the endpoint,
  797 + # we still need to verify it by discovery, so $server is not set here
  798 + $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
  799 + } elseif (isset($this->data['openid_claimed_id'])
  800 + && $this->data['openid_claimed_id'] != $this->data['openid_identity']
  801 + ) {
  802 + # If it's an OpenID 1 provider, and we've got claimed_id,
  803 + # we have to append it to the returnUrl, like authUrl_v1 does.
  804 + $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
  805 + . 'openid.claimed_id=' . $this->claimed_id;
  806 + }
  807 +
  808 + if ($this->data['openid_return_to'] != $this->returnUrl) {
  809 + # The return_to url must match the url of current request.
  810 + # I'm assuing that noone will set the returnUrl to something that doesn't make sense.
  811 + return false;
  812 + }
  813 +
  814 + $server = $this->discover($this->claimed_id);
  815 +
  816 + foreach (explode(',', $this->data['openid_signed']) as $item) {
  817 + # Checking whether magic_quotes_gpc is turned on, because
  818 + # the function may fail if it is. For example, when fetching
  819 + # AX namePerson, it might containg an apostrophe, which will be escaped.
  820 + # In such case, validation would fail, since we'd send different data than OP
  821 + # wants to verify. stripslashes() should solve that problem, but we can't
  822 + # use it when magic_quotes is off.
  823 + $value = $this->data['openid_' . str_replace('.','_',$item)];
  824 + $params['openid.' . $item] = function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ? stripslashes($value) : $value;
  825 +
  826 + }
  827 +
  828 + $params['openid.mode'] = 'check_authentication';
  829 +
  830 + $response = $this->request($server, 'POST', $params);
  831 +
  832 + return preg_match('/is_valid\s*:\s*true/i', $response);
  833 + }
  834 +
  835 + protected function getAxAttributes()
  836 + {
  837 + $result = array();
  838 +
  839 + if ($alias = $this->getNamespaceAlias('http://openid.net/srv/ax/1.0', 'ax')) {
  840 + $prefix = 'openid_' . $alias;
  841 + $length = strlen('http://axschema.org/');
  842 +
  843 + foreach (explode(',', $this->data['openid_signed']) as $key) {
  844 + $keyMatch = $alias . '.type.';
  845 +
  846 + if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
  847 + continue;
  848 + }
  849 +
  850 + $key = substr($key, strlen($keyMatch));
  851 + $idv = $prefix . '_value_' . $key;
  852 + $idc = $prefix . '_count_' . $key;
  853 + $key = substr($this->getItem($prefix . '_type_' . $key), $length);
  854 +
  855 + if (!empty($key)) {
  856 + if (($count = intval($this->getItem($idc))) > 0) {
  857 + $value = array();
  858 +
  859 + for ($i = 1; $i <= $count; $i++) {
  860 + $value[] = $this->getItem($idv . '_' . $i);
  861 + }
  862 +
  863 + $value = ($count == 1) ? reset($value) : $value;
  864 + } else {
  865 + $value = $this->getItem($idv);
  866 + }
  867 +
  868 + if (!is_null($value)) {
  869 + $result[$key] = $value;
  870 + }
  871 + }
  872 + }
  873 + } else {
  874 + // No alias for the AX schema has been found,
  875 + // so there is no AX data in the OP's response.
  876 + }
  877 +
  878 + return $result;
  879 + }
  880 +
  881 + protected function getSregAttributes()
  882 + {
  883 + $attributes = array();
  884 + $sreg_to_ax = array_flip(self::$ax_to_sreg);
  885 + foreach (explode(',', $this->data['openid_signed']) as $key) {
  886 + $keyMatch = 'sreg.';
  887 + if (strncmp($key, $keyMatch, strlen($keyMatch)) !== 0) {
  888 + continue;
  889 + }
  890 + $key = substr($key, strlen($keyMatch));
  891 + if (!isset($sreg_to_ax[$key])) {
  892 + # The field name isn't part of the SREG spec, so we ignore it.
  893 + continue;
  894 + }
  895 + $attributes[$sreg_to_ax[$key]] = $this->data['openid_sreg_' . $key];
  896 + }
  897 + return $attributes;
  898 + }
  899 +
  900 + /**
  901 + * Gets AX/SREG attributes provided by OP. should be used only after successful validaton.
  902 + * Note that it does not guarantee that any of the required/optional parameters will be present,
  903 + * or that there will be no other attributes besides those specified.
  904 + * In other words. OP may provide whatever information it wants to.
  905 + * * SREG names will be mapped to AX names.
  906 + * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email'
  907 + * @see http://www.axschema.org/types/
  908 + */
  909 + function getAttributes()
  910 + {
  911 + if (isset($this->data['openid_ns'])
  912 + && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
  913 + ) { # OpenID 2.0
  914 + # We search for both AX and SREG attributes, with AX taking precedence.
  915 + return $this->getAxAttributes() + $this->getSregAttributes();
  916 + }
  917 + return $this->getSregAttributes();
  918 + }
  919 +
  920 + /**
  921 + * Gets an OAuth request token if the OpenID+OAuth hybrid protocol has been used.
  922 + *
  923 + * In order to use the OpenID+OAuth hybrid protocol, you need to add at least one
  924 + * scope to the $openid->oauth array before you get the call to getAuthUrl(), e.g.:
  925 + * $openid->oauth[] = 'https://www.googleapis.com/auth/plus.me';
  926 + *
  927 + * Furthermore the registered consumer name must fit the OpenID realm.
  928 + * To register an OpenID consumer at Google use: https://www.google.com/accounts/ManageDomains
  929 + *
  930 + * @return string|bool OAuth request token on success, FALSE if no token was provided.
  931 + */
  932 + function getOAuthRequestToken()
  933 + {
  934 + $alias = $this->getNamespaceAlias('http://specs.openid.net/extensions/oauth/1.0');
  935 +
  936 + return !empty($alias) ? $this->data['openid_' . $alias . '_request_token'] : false;
  937 + }
  938 +
  939 + /**
  940 + * Gets the alias for the specified namespace, if it's present.
  941 + *
  942 + * @param string $namespace The namespace for which an alias is needed.
  943 + * @param string $hint Common alias of this namespace, used for optimization.
  944 + * @return string|null The namespace alias if found, otherwise - NULL.
  945 + */
  946 + private function getNamespaceAlias($namespace, $hint = null)
  947 + {
  948 + $result = null;
  949 +
  950 + if (empty($hint) || $this->getItem('openid_ns_' . $hint) != $namespace) {
  951 + // The common alias is either undefined or points to
  952 + // some other extension - search for another alias..
  953 + $prefix = 'openid_ns_';
  954 + $length = strlen($prefix);
  955 +
  956 + foreach ($this->data as $key => $val) {
  957 + if (strncmp($key, $prefix, $length) === 0 && $val === $namespace) {
  958 + $result = trim(substr($key, $length));
  959 + break;
  960 + }
  961 + }
  962 + } else {
  963 + $result = $hint;
  964 + }
  965 +
  966 + return $result;
  967 + }
  968 +
  969 + /**
  970 + * Gets an item from the $data array by the specified id.
  971 + *
  972 + * @param string $id The id of the desired item.
  973 + * @return string|null The item if found, otherwise - NULL.
  974 + */
  975 + private function getItem($id)
  976 + {
  977 + return isset($this->data[$id]) ? $this->data[$id] : null;
  978 + }
  979 +}
0 980 \ No newline at end of file
... ...
common/components/nodge/lightopenid/provider/example-mysql.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * This example shows several things:
  4 + * - How a setup interface should look like.
  5 + * - How to use a mysql table for authentication
  6 + * - How to store associations in mysql table, instead of php sessions.
  7 + * - How to store realm authorizations.
  8 + * - How to send AX/SREG parameters.
  9 + * For the example to work, you need to create the necessary tables:
  10 +CREATE TABLE Users (
  11 + id INT NOT NULL auto_increment PRIMARY KEY,
  12 + login VARCHAR(32) NOT NULL,
  13 + password CHAR(40) NOT NULL,
  14 + firstName VARCHAR(32) NOT NULL,
  15 + lastName VARCHAR(32) NOT NULL
  16 +);
  17 +
  18 +CREATE TABLE AllowedSites (
  19 + user INT NOT NULL,
  20 + realm TEXT NOT NULL,
  21 + attributes TEXT NOT NULL,
  22 + INDEX(user)
  23 +);
  24 +
  25 +CREATE TABLE Associations (
  26 + id INT NOT NULL PRIMARY KEY,
  27 + data TEXT NOT NULL
  28 +);
  29 + *
  30 + * This is only an example. Don't use it in your code as-is.
  31 + * It has several security flaws, which you shouldn't copy (like storing plaintext login and password in forms).
  32 + *
  33 + * This setup could be very easily flooded with many associations,
  34 + * since non-private ones aren't automatically deleted.
  35 + * You could prevent this by storing a date of association and removing old ones,
  36 + * or by setting $this->dh = false;
  37 + * However, the latter one would disable stateful mode, unless connecting via HTTPS.
  38 + */
  39 +require 'provider.php';
  40 +
  41 +mysql_connect();
  42 +mysql_select_db('test');
  43 +
  44 +function getUserData($handle=null)
  45 +{
  46 + if(isset($_POST['login'],$_POST['password'])) {
  47 + $login = mysql_real_escape_string($_POST['login']);
  48 + $password = sha1($_POST['password']);
  49 + $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'");
  50 + if($data = mysql_fetch_assoc($q)) {
  51 + return $data;
  52 + }
  53 + if($handle) {
  54 + echo 'Wrong login/password.';
  55 + }
  56 + }
  57 + if($handle) {
  58 + ?>
  59 + <form action="" method="post">
  60 + <input type="hidden" name="openid.assoc_handle" value="<?php echo $handle?>">
  61 + Login: <input type="text" name="login"><br>
  62 + Password: <input type="password" name="password"><br>
  63 + <button>Submit</button>
  64 + </form>
  65 + <?php
  66 + die();
  67 + }
  68 +}
  69 +
  70 +class MysqlProvider extends LightOpenIDProvider
  71 +{
  72 + private $attrMap = array(
  73 + 'namePerson/first' => 'First name',
  74 + 'namePerson/last' => 'Last name',
  75 + 'namePerson/friendly' => 'Nickname (login)'
  76 + );
  77 +
  78 + private $attrFieldMap = array(
  79 + 'namePerson/first' => 'firstName',
  80 + 'namePerson/last' => 'lastName',
  81 + 'namePerson/friendly' => 'login'
  82 + );
  83 +
  84 + function setup($identity, $realm, $assoc_handle, $attributes)
  85 + {
  86 + $data = getUserData($assoc_handle);
  87 + echo '<form action="" method="post">'
  88 + . '<input type="hidden" name="openid.assoc_handle" value="' . $assoc_handle . '">'
  89 + . '<input type="hidden" name="login" value="' . $_POST['login'] .'">'
  90 + . '<input type="hidden" name="password" value="' . $_POST['password'] .'">'
  91 + . "<b>$realm</b> wishes to authenticate you.";
  92 + if($attributes['required'] || $attributes['optional']) {
  93 + echo " It also requests following information (required fields marked with *):"
  94 + . '<ul>';
  95 +
  96 + foreach($attributes['required'] as $attr) {
  97 + if(isset($this->attrMap[$attr])) {
  98 + echo '<li>'
  99 + . '<input type="checkbox" name="attributes[' . $attr . ']"> '
  100 + . $this->attrMap[$attr] . '(*)</li>';
  101 + }
  102 + }
  103 +
  104 + foreach($attributes['optional'] as $attr) {
  105 + if(isset($this->attrMap[$attr])) {
  106 + echo '<li>'
  107 + . '<input type="checkbox" name="attributes[' . $attr . ']"> '
  108 + . $this->attrMap[$attr] . '</li>';
  109 + }
  110 + }
  111 + echo '</ul>';
  112 + }
  113 + echo '<br>'
  114 + . '<button name="once">Allow once</button> '
  115 + . '<button name="always">Always allow</button> '
  116 + . '<button name="cancel">cancel</button> '
  117 + . '</form>';
  118 + }
  119 +
  120 + function checkid($realm, &$attributes)
  121 + {
  122 + if(isset($_POST['cancel'])) {
  123 + $this->cancel();
  124 + }
  125 +
  126 + $data = getUserData();
  127 + if(!$data) {
  128 + return false;
  129 + }
  130 + $realm = mysql_real_escape_string($realm);
  131 + $q = mysql_query("SELECT attributes FROM AllowedSites WHERE user = '{$data['id']}' AND realm = '$realm'");
  132 +
  133 + $attrs = array();
  134 + if($attrs = mysql_fetch_row($q)) {
  135 + $attrs = explode(',', $attributes[0]);
  136 + } elseif(isset($_POST['attributes'])) {
  137 + $attrs = array_keys($_POST['attributes']);
  138 + } elseif(!isset($_POST['once']) && !isset($_POST['always'])) {
  139 + return false;
  140 + }
  141 +
  142 + $attributes = array();
  143 + foreach($attrs as $attr) {
  144 + if(isset($this->attrFieldMap[$attr])) {
  145 + $attributes[$attr] = $data[$this->attrFieldMap[$attr]];
  146 + }
  147 + }
  148 +
  149 + if(isset($_POST['always'])) {
  150 + $attrs = mysql_real_escape_string(implode(',', array_keys($attributes)));
  151 + mysql_query("REPLACE INTO AllowedSites VALUES('{$data['id']}', '$realm', '$attrs')");
  152 + }
  153 +
  154 + return $this->serverLocation . '?' . $data['login'];
  155 + }
  156 +
  157 + function assoc_handle()
  158 + {
  159 + # We generate an integer assoc handle, because it's just faster to look up an integer later.
  160 + $q = mysql_query("SELECT MAX(id) FROM Associations");
  161 + $result = mysql_fetch_row($q);
  162 + return $q[0]+1;
  163 + }
  164 +
  165 + function setAssoc($handle, $data)
  166 + {
  167 + $data = mysql_real_escape_string(serialize($data));
  168 + mysql_query("REPLACE INTO Associations VALUES('$handle', '$data')");
  169 + }
  170 +
  171 + function getAssoc($handle)
  172 + {
  173 + if(!is_numeric($handle)) {
  174 + return false;
  175 + }
  176 + $q = mysql_query("SELECT data FROM Associations WHERE id = '$handle'");
  177 + $data = mysql_fetch_row($q);
  178 + if(!$data) {
  179 + return false;
  180 + }
  181 + return unserialize($data[0]);
  182 + }
  183 +
  184 + function delAssoc($handle)
  185 + {
  186 + if(!is_numeric($handle)) {
  187 + return false;
  188 + }
  189 + mysql_query("DELETE FROM Associations WHERE id = '$handle'");
  190 + }
  191 +
  192 +}
  193 +$op = new MysqlProvider;
  194 +$op->server();
... ...
common/components/nodge/lightopenid/provider/example.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * This example shows how to create a basic provider usin HTTP Authentication.
  4 + * This is only an example. You shouldn't use it as-is in your code.
  5 + */
  6 +require 'provider.php';
  7 +
  8 +class BasicProvider extends LightOpenIDProvider
  9 +{
  10 + public $select_id = true;
  11 + public $login = '';
  12 + public $password = '';
  13 +
  14 + function __construct()
  15 + {
  16 + parent::__construct();
  17 +
  18 + # If we use select_id, we must disable it for identity pages,
  19 + # so that an RP can discover it and get proper data (i.e. without select_id)
  20 + if(isset($_GET['id'])) {
  21 + $this->select_id = false;
  22 + }
  23 + }
  24 +
  25 + function setup($identity, $realm, $assoc_handle, $attributes)
  26 + {
  27 + header('WWW-Authenticate: Basic realm="' . $this->data['openid_realm'] . '"');
  28 + header('HTTP/1.0 401 Unauthorized');
  29 + }
  30 +
  31 + function checkid($realm, &$attributes)
  32 + {
  33 + if(!isset($_SERVER['PHP_AUTH_USER'])) {
  34 + return false;
  35 + }
  36 +
  37 + if ($_SERVER['PHP_AUTH_USER'] == $this->login
  38 + && $_SERVER['PHP_AUTH_PW'] == $this->password
  39 + ) {
  40 + # Returning identity
  41 + # It can be any url that leads here, or to any other place that hosts
  42 + # an XRDS document pointing here.
  43 + return $this->serverLocation . '?id=' . $this->login;
  44 + }
  45 +
  46 + return false;
  47 + }
  48 +
  49 +}
  50 +$op = new BasicProvider;
  51 +$op->login = 'test';
  52 +$op->password = 'test';
  53 +$op->server();
... ...
common/components/nodge/lightopenid/provider/provider.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Using this class, you can easily set up an OpenID Provider.
  4 + * It's independent of LightOpenID class.
  5 + * It requires either GMP or BCMath for session encryption,
  6 + * but will work without them (although either via SSL, or in stateless mode only).
  7 + * Also, it requires PHP >= 5.1.2
  8 + *
  9 + * This is an alpha version, using it in production code is not recommended,
  10 + * until you are *sure* that it works and is secure.
  11 + *
  12 + * Please send me messages about your testing results
  13 + * (even if successful, so I know that it has been tested).
  14 + * Also, if you think there's a way to make it easier to use, tell me -- it's an alpha for a reason.
  15 + * Same thing applies to bugs in code, suggestions,
  16 + * and everything else you'd like to say about the library.
  17 + *
  18 + * There's no usage documentation here, see the examples.
  19 + *
  20 + * @author Mewp
  21 + * @copyright Copyright (c) 2010, Mewp
  22 + * @license http://www.opensource.org/licenses/mit-license.php MIT
  23 + */
  24 +ini_set('error_log','log');
  25 +abstract class LightOpenIDProvider
  26 +{
  27 + # URL-s to XRDS and server location.
  28 + public $xrdsLocation, $serverLocation;
  29 +
  30 + # Should we operate in server, or signon mode?
  31 + public $select_id = false;
  32 +
  33 + # Lifetime of an association.
  34 + protected $assoc_lifetime = 600;
  35 +
  36 + # Variables below are either set automatically, or are constant.
  37 + # -----
  38 + # Can we support DH?
  39 + protected $dh = true;
  40 + protected $ns = 'http://specs.openid.net/auth/2.0';
  41 + protected $data, $assoc;
  42 +
  43 + # Default DH parameters as defined in the specification.
  44 + protected $default_modulus;
  45 + protected $default_gen = 'Ag==';
  46 +
  47 + # AX <-> SREG transform
  48 + protected $ax_to_sreg = array(
  49 + 'namePerson/friendly' => 'nickname',
  50 + 'contact/email' => 'email',
  51 + 'namePerson' => 'fullname',
  52 + 'birthDate' => 'dob',
  53 + 'person/gender' => 'gender',
  54 + 'contact/postalCode/home' => 'postcode',
  55 + 'contact/country/home' => 'country',
  56 + 'pref/language' => 'language',
  57 + 'pref/timezone' => 'timezone',
  58 + );
  59 +
  60 + # Math
  61 + private $add, $mul, $pow, $mod, $div, $powmod;
  62 + # -----
  63 +
  64 + # ------------------------------------------------------------------------ #
  65 + # Functions you probably want to implement when extending the class.
  66 +
  67 + /**
  68 + * Checks whether an user is authenticated.
  69 + * The function should determine what fields it wants to send to the RP,
  70 + * and put them in the $attributes array.
  71 + * @param Array $attributes
  72 + * @param String $realm Realm used for authentication.
  73 + * @return String OP-local identifier of an authenticated user, or an empty value.
  74 + */
  75 + abstract function checkid($realm, &$attributes);
  76 +
  77 + /**
  78 + * Displays an user interface for inputting user's login and password.
  79 + * Attributes are always AX field namespaces, with stripped host part.
  80 + * For example, the $attributes array may be:
  81 + * array( 'required' => array('namePerson/friendly', 'contact/email'),
  82 + * 'optional' => array('pref/timezone', 'pref/language')
  83 + * @param String $identity Discovered identity string. May be used to extract login, unless using $this->select_id
  84 + * @param String $realm Realm used for authentication.
  85 + * @param String Association handle. must be sent as openid.assoc_handle in $_GET or $_POST in subsequent requests.
  86 + * @param Array User attributes requested by the RP.
  87 + */
  88 + abstract function setup($identity, $realm, $assoc_handle, $attributes);
  89 +
  90 + /**
  91 + * Stores an association.
  92 + * If you want to use php sessions in your provider code, you have to replace it.
  93 + * @param String $handle Association handle -- should be used as a key.
  94 + * @param Array $assoc Association data.
  95 + */
  96 + protected function setAssoc($handle, $assoc)
  97 + {
  98 + $oldSession = session_id();
  99 + session_commit();
  100 + session_id($assoc['handle']);
  101 + session_start();
  102 + $_SESSION['assoc'] = $assoc;
  103 + session_commit();
  104 + if($oldSession) {
  105 + session_id($oldSession);
  106 + session_start();
  107 + }
  108 + }
  109 +
  110 + /**
  111 + * Retreives association data.
  112 + * If you want to use php sessions in your provider code, you have to replace it.
  113 + * @param String $handle Association handle.
  114 + * @return Array Association data.
  115 + */
  116 + protected function getAssoc($handle)
  117 + {
  118 + $oldSession = session_id();
  119 + session_commit();
  120 + session_id($handle);
  121 + session_start();
  122 + $assoc = null;
  123 + if(!empty($_SESSION['assoc'])) {
  124 + $assoc = $_SESSION['assoc'];
  125 + }
  126 + session_commit();
  127 + if($oldSession) {
  128 + session_id($oldSession);
  129 + session_start();
  130 + }
  131 + return $assoc;
  132 + }
  133 +
  134 + /**
  135 + * Deletes an association.
  136 + * If you want to use php sessions in your provider code, you have to replace it.
  137 + * @param String $handle Association handle.
  138 + */
  139 + protected function delAssoc($handle)
  140 + {
  141 + $oldSession = session_id();
  142 + session_commit();
  143 + session_id($handle);
  144 + session_start();
  145 + session_destroy();
  146 + if($oldSession) {
  147 + session_id($oldSession);
  148 + session_start();
  149 + }
  150 + }
  151 +
  152 + # ------------------------------------------------------------------------ #
  153 + # Functions that you might want to implement.
  154 +
  155 + /**
  156 + * Redirects the user to an url.
  157 + * @param String $location The url that the user will be redirected to.
  158 + */
  159 + protected function redirect($location)
  160 + {
  161 + header('Location: ' . $location);
  162 + die();
  163 + }
  164 +
  165 + /**
  166 + * Generates a new association handle.
  167 + * @return string
  168 + */
  169 + protected function assoc_handle()
  170 + {
  171 + return sha1(microtime());
  172 + }
  173 +
  174 + /**
  175 + * Generates a random shared secret.
  176 + * @return string
  177 + */
  178 + protected function shared_secret($hash)
  179 + {
  180 + $length = 20;
  181 + if($hash == 'sha256') {
  182 + $length = 256;
  183 + }
  184 +
  185 + $secret = '';
  186 + for($i = 0; $i < $length; $i++) {
  187 + $secret .= mt_rand(0,255);
  188 + }
  189 +
  190 + return $secret;
  191 + }
  192 +
  193 + /**
  194 + * Generates a private key.
  195 + * @param int $length Length of the key.
  196 + */
  197 + protected function keygen($length)
  198 + {
  199 + $key = '';
  200 + for($i = 1; $i < $length; $i++) {
  201 + $key .= mt_rand(0,9);
  202 + }
  203 + $key .= mt_rand(1,9);
  204 +
  205 + return $key;
  206 + }
  207 +
  208 + # ------------------------------------------------------------------------ #
  209 + # Functions that you probably shouldn't touch.
  210 +
  211 + function __construct()
  212 + {
  213 + $this->default_modulus =
  214 + 'ANz5OguIOXLsDhmYmsWizjEOHTdxfo2Vcbt2I3MYZuYe91ouJ4mLBX+YkcLiemOcPy'
  215 + . 'm2CBRYHNOyyjmG0mg3BVd9RcLn5S3IHHoXGHblzqdLFEi/368Ygo79JRnxTkXjgmY0'
  216 + . 'rxlJ5bU1zIKaSDuKdiI+XUkKJX8Fvf8W8vsixYOr';
  217 +
  218 + $location = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://'
  219 + . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  220 + $location = preg_replace('/\?.*/','',$location);
  221 + $this->serverLocation = $location;
  222 + $location .= (strpos($location, '?') ? '&' : '?') . 'xrds';
  223 + $this->xrdsLocation = $location;
  224 +
  225 + $this->data = $_GET + $_POST;
  226 +
  227 + # We choose GMP if avaiable, and bcmath otherwise
  228 + if(function_exists('gmp_add')) {
  229 + $this->add = 'gmp_add';
  230 + $this->mul = 'gmp_mul';
  231 + $this->pow = 'gmp_pow';
  232 + $this->mod = 'gmp_mod';
  233 + $this->div = 'gmp_div';
  234 + $this->powmod = 'gmp_powm';
  235 + } elseif(function_exists('bcadd')) {
  236 + $this->add = 'bcadd';
  237 + $this->mul = 'bcmul';
  238 + $this->pow = 'bcpow';
  239 + $this->mod = 'bcmod';
  240 + $this->div = 'bcdiv';
  241 + $this->powmod = 'bcpowmod';
  242 + } else {
  243 + # If neither are avaiable, we can't use DH
  244 + $this->dh = false;
  245 + }
  246 +
  247 + # However, we do require the hash functions.
  248 + # They should be built-in anyway.
  249 + if(!function_exists('hash_algos')) {
  250 + $this->dh = false;
  251 + }
  252 + }
  253 +
  254 + /**
  255 + * Displays an XRDS document, or redirects to it.
  256 + * By default, it detects whether it should display or redirect automatically.
  257 + * @param bool|null $force When true, always display the document, when false always redirect.
  258 + */
  259 + function xrds($force=null)
  260 + {
  261 + if($force) {
  262 + echo $this->xrdsContent();
  263 + die();
  264 + } elseif($force === false) {
  265 + header('X-XRDS-Location: '. $this->xrdsLocation);
  266 + return;
  267 + }
  268 +
  269 + if (isset($_GET['xrds'])
  270 + || (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/xrds+xml') !== false)
  271 + ) {
  272 + header('Content-Type: application/xrds+xml');
  273 + echo $this->xrdsContent();
  274 + die();
  275 + }
  276 +
  277 + header('X-XRDS-Location: ' . $this->xrdsLocation);
  278 + }
  279 +
  280 + /**
  281 + * Returns the content of the XRDS document
  282 + * @return String The XRDS document.
  283 + */
  284 + protected function xrdsContent()
  285 + {
  286 + $lines = array(
  287 + '<?xml version="1.0" encoding="UTF-8"?>',
  288 + '<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">',
  289 + '<XRD>',
  290 + ' <Service>',
  291 + ' <Type>' . $this->ns . '/' . ($this->select_id ? 'server' : 'signon') .'</Type>',
  292 + ' <URI>' . $this->serverLocation . '</URI>',
  293 + ' </Service>',
  294 + '</XRD>',
  295 + '</xrds:XRDS>'
  296 + );
  297 + return implode("\n", $lines);
  298 + }
  299 +
  300 + /**
  301 + * Does everything that a provider has to -- in one function.
  302 + */
  303 + function server()
  304 + {
  305 + if(isset($this->data['openid_assoc_handle'])) {
  306 + $this->assoc = $this->getAssoc($this->data['openid_assoc_handle']);
  307 + if(isset($this->assoc['data'])) {
  308 + # We have additional data stored for setup.
  309 + $this->data += $this->assoc['data'];
  310 + unset($this->assoc['data']);
  311 + }
  312 + }
  313 +
  314 + if (isset($this->data['openid_ns'])
  315 + && $this->data['openid_ns'] == $this->ns
  316 + ) {
  317 + if(!isset($this->data['openid_mode'])) $this->errorResponse();
  318 +
  319 + switch($this->data['openid_mode'])
  320 + {
  321 + case 'checkid_immediate':
  322 + case 'checkid_setup':
  323 + $this->checkRealm();
  324 + # We support AX xor SREG.
  325 + $attributes = $this->ax();
  326 + if(!$attributes) {
  327 + $attributes = $this->sreg();
  328 + }
  329 +
  330 + # Even if some user is authenticated, we need to know if it's
  331 + # the same one that want's to authenticate.
  332 + # Of course, if we use select_id, we accept any user.
  333 + if (($identity = $this->checkid($this->data['openid_realm'], $attrValues))
  334 + && ($this->select_id || $identity == $this->data['openid_identity'])
  335 + ) {
  336 + $this->positiveResponse($identity, $attrValues);
  337 + } elseif($this->data['openid_mode'] == 'checkid_immediate') {
  338 + $this->redirect($this->response(array('openid.mode' => 'setup_needed')));
  339 + } else {
  340 + if(!$this->assoc) {
  341 + $this->generateAssociation();
  342 + $this->assoc['private'] = true;
  343 + }
  344 + $this->assoc['data'] = $this->data;
  345 + $this->setAssoc($this->assoc['handle'], $this->assoc);
  346 + $this->setup($this->data['openid_identity'],
  347 + $this->data['openid_realm'],
  348 + $this->assoc['handle'],
  349 + $attributes);
  350 + }
  351 + break;
  352 + case 'associate':
  353 + $this->associate();
  354 + break;
  355 + case 'check_authentication':
  356 + $this->checkRealm();
  357 + if($this->verify()) {
  358 + echo "ns:$this->ns\nis_valid:true";
  359 + if(strpos($this->data['openid_signed'],'invalidate_handle') !== false) {
  360 + echo "\ninvalidate_handle:" . $this->data['openid_invalidate_handle'];
  361 + }
  362 + } else {
  363 + echo "ns:$this->ns\nis_valid:false";
  364 + }
  365 + die();
  366 + break;
  367 + default:
  368 + $this->errorResponse();
  369 + }
  370 + } else {
  371 + $this->xrds();
  372 + }
  373 + }
  374 +
  375 + protected function checkRealm()
  376 + {
  377 + if (!isset($this->data['openid_return_to'], $this->data['openid_realm'])) {
  378 + $this->errorResponse();
  379 + }
  380 +
  381 + $realm = str_replace('\*', '[^/]', preg_quote($this->data['openid_realm']));
  382 + if(!preg_match("#^$realm#", $this->data['openid_return_to'])) {
  383 + $this->errorResponse();
  384 + }
  385 + }
  386 +
  387 + protected function ax()
  388 + {
  389 + # Namespace prefix that the fields must have.
  390 + $ns = 'http://axschema.org/';
  391 +
  392 + # First, we must find out what alias is used for AX.
  393 + # Let's check the most likely one
  394 + $alias = null;
  395 + if (isset($this->data['openid_ns_ax'])
  396 + && $this->data['openid_ns_ax'] == 'http://openid.net/srv/ax/1.0'
  397 + ) {
  398 + $alias = 'ax';
  399 + } else {
  400 + foreach($this->data as $name => $value) {
  401 + if ($value == 'http://openid.net/srv/ax/1.0'
  402 + && preg_match('/openid_ns_(.+)/', $name, $m)
  403 + ) {
  404 + $alias = $m[1];
  405 + break;
  406 + }
  407 + }
  408 + }
  409 +
  410 + if(!$alias) {
  411 + return null;
  412 + }
  413 +
  414 + $fields = array();
  415 + # Now, we must search again, this time for field aliases
  416 + foreach($this->data as $name => $value) {
  417 + if (strpos($name, 'openid_' . $alias . '_type') === false
  418 + || strpos($value, $ns) === false) {
  419 + continue;
  420 + }
  421 +
  422 + $name = substr($name, strlen('openid_' . $alias . '_type_'));
  423 + $value = substr($value, strlen($ns));
  424 +
  425 + $fields[$name] = $value;
  426 + }
  427 +
  428 + # Then, we find out what fields are required and optional
  429 + $required = array();
  430 + $if_available = array();
  431 + foreach(array('required','if_available') as $type) {
  432 + if(empty($this->data["openid_{$alias}_{$type}"])) {
  433 + continue;
  434 + }
  435 + $attributes = explode(',', $this->data["openid_{$alias}_{$type}"]);
  436 + foreach($attributes as $attr) {
  437 + if(empty($fields[$attr])) {
  438 + # There is an undefined field here, so we ignore it.
  439 + continue;
  440 + }
  441 +
  442 + ${$type}[] = $fields[$attr];
  443 + }
  444 + }
  445 +
  446 + $this->data['ax'] = true;
  447 + return array('required' => $required, 'optional' => $if_available);
  448 + }
  449 +
  450 + protected function sreg()
  451 + {
  452 + $sreg_to_ax = array_flip($this->ax_to_sreg);
  453 +
  454 + $attributes = array('required' => array(), 'optional' => array());
  455 +
  456 + if (empty($this->data['openid_sreg_required'])
  457 + && empty($this->data['openid_sreg_optional'])
  458 + ) {
  459 + return $attributes;
  460 + }
  461 +
  462 + foreach(array('required', 'optional') as $type) {
  463 + foreach(explode(',',$this->data['openid_sreg_' . $type]) as $attr) {
  464 + if(empty($sreg_to_ax[$attr])) {
  465 + # Undefined attribute in SREG request.
  466 + # Shouldn't happen, but we check anyway.
  467 + continue;
  468 + }
  469 +
  470 + $attributes[$type][] = $sreg_to_ax[$attr];
  471 + }
  472 + }
  473 +
  474 + return $attributes;
  475 + }
  476 +
  477 + /**
  478 + * Aids an RP in assertion verification.
  479 + * @return bool Information whether the verification suceeded.
  480 + */
  481 + protected function verify()
  482 + {
  483 + # Firstly, we need to make sure that there's an association.
  484 + # Otherwise the verification will fail,
  485 + # because we've signed assoc_handle in the assertion
  486 + if(empty($this->assoc)) {
  487 + return false;
  488 + }
  489 +
  490 + # Next, we check that it's a private association,
  491 + # i.e. one made without RP input.
  492 + # Otherwise, the RP shouldn't ask us to verify.
  493 + if(empty($this->assoc['private'])) {
  494 + return false;
  495 + }
  496 +
  497 + # Now we have to check if the nonce is correct, to prevent replay attacks.
  498 + if($this->data['openid_response_nonce'] != $this->assoc['nonce']) {
  499 + return false;
  500 + }
  501 +
  502 + # Getting the signed fields for signature.
  503 + $sig = array();
  504 + $signed = explode(',', $this->data['openid_signed']);
  505 + foreach($signed as $field) {
  506 + $name = strtr($field, '.', '_');
  507 + if(!isset($this->data['openid_' . $name])) {
  508 + return false;
  509 + }
  510 +
  511 + $sig[$field] = $this->data['openid_' . $name];
  512 + }
  513 +
  514 + # Computing the signature and checking if it matches.
  515 + $sig = $this->keyValueForm($sig);
  516 + if ($this->data['openid_sig'] !=
  517 + base64_encode(hash_hmac($this->assoc['hash'], $sig, $this->assoc['mac'], true))
  518 + ) {
  519 + return false;
  520 + }
  521 +
  522 + # Clearing the nonce, so that it won't be used again.
  523 + $this->assoc['nonce'] = null;
  524 +
  525 + if(empty($this->assoc['private'])) {
  526 + # Commiting changes to the association.
  527 + $this->setAssoc($this->assoc['handle'], $this->assoc);
  528 + } else {
  529 + # Private associations shouldn't be used again, se we can as well delete them.
  530 + $this->delAssoc($this->assoc['handle']);
  531 + }
  532 +
  533 + # Nothing has failed, so the verification was a success.
  534 + return true;
  535 + }
  536 +
  537 + /**
  538 + * Performs association with an RP.
  539 + */
  540 + protected function associate()
  541 + {
  542 + # Rejecting no-encryption without TLS.
  543 + if(empty($_SERVER['HTTPS']) && $this->data['openid_session_type'] == 'no-encryption') {
  544 + $this->directErrorResponse();
  545 + }
  546 +
  547 + # Checking whether we support DH at all.
  548 + if (!$this->dh && substr($this->data['openid_session_type'], 0, 2) == 'DH') {
  549 + $this->redirect($this->response(array(
  550 + 'openid.error' => 'DH not supported',
  551 + 'openid.error_code' => 'unsupported-type',
  552 + 'openid.session_type' => 'no-encryption'
  553 + )));
  554 + }
  555 +
  556 + # Creating the association
  557 + $this->assoc = array();
  558 + $this->assoc['hash'] = $this->data['openid_assoc_type'] == 'HMAC-SHA256' ? 'sha256' : 'sha1';
  559 + $this->assoc['handle'] = $this->assoc_handle();
  560 +
  561 + # Getting the shared secret
  562 + if($this->data['openid_session_type'] == 'no-encryption') {
  563 + $this->assoc['mac'] = base64_encode($this->shared_secret($this->assoc['hash']));
  564 + } else {
  565 + $this->dh();
  566 + }
  567 +
  568 + # Preparing the direct response...
  569 + $response = array(
  570 + 'ns' => $this->ns,
  571 + 'assoc_handle' => $this->assoc['handle'],
  572 + 'assoc_type' => $this->data['openid_assoc_type'],
  573 + 'session_type' => $this->data['openid_session_type'],
  574 + 'expires_in' => $this->assoc_lifetime
  575 + );
  576 +
  577 + if(isset($this->assoc['dh_server_public'])) {
  578 + $response['dh_server_public'] = $this->assoc['dh_server_public'];
  579 + $response['enc_mac_key'] = $this->assoc['mac'];
  580 + } else {
  581 + $response['mac_key'] = $this->assoc['mac'];
  582 + }
  583 +
  584 + # ...and sending it.
  585 + echo $this->keyValueForm($response);
  586 + die();
  587 + }
  588 +
  589 + /**
  590 + * Creates a private association.
  591 + */
  592 + protected function generateAssociation()
  593 + {
  594 + $this->assoc = array();
  595 + # We use sha1 by default.
  596 + $this->assoc['hash'] = 'sha1';
  597 + $this->assoc['mac'] = $this->shared_secret('sha1');
  598 + $this->assoc['handle'] = $this->assoc_handle();
  599 + }
  600 +
  601 + /**
  602 + * Encrypts the MAC key using DH key exchange.
  603 + */
  604 + protected function dh()
  605 + {
  606 + if(empty($this->data['openid_dh_modulus'])) {
  607 + $this->data['openid_dh_modulus'] = $this->default_modulus;
  608 + }
  609 +
  610 + if(empty($this->data['openid_dh_gen'])) {
  611 + $this->data['openid_dh_gen'] = $this->default_gen;
  612 + }
  613 +
  614 + if(empty($this->data['openid_dh_consumer_public'])) {
  615 + $this->directErrorResponse();
  616 + }
  617 +
  618 + $modulus = $this->b64dec($this->data['openid_dh_modulus']);
  619 + $gen = $this->b64dec($this->data['openid_dh_gen']);
  620 + $consumerKey = $this->b64dec($this->data['openid_dh_consumer_public']);
  621 +
  622 + $privateKey = $this->keygen(strlen($modulus));
  623 + $publicKey = $this->powmod($gen, $privateKey, $modulus);
  624 + $ss = $this->powmod($consumerKey, $privateKey, $modulus);
  625 +
  626 + $mac = $this->x_or(hash($this->assoc['hash'], $ss, true), $this->shared_secret($this->assoc['hash']));
  627 + $this->assoc['dh_server_public'] = $this->decb64($publicKey);
  628 + $this->assoc['mac'] = base64_encode($mac);
  629 + }
  630 +
  631 + /**
  632 + * XORs two strings.
  633 + * @param String $a
  634 + * @param String $b
  635 + * @return String $a ^ $b
  636 + */
  637 + protected function x_or($a, $b)
  638 + {
  639 + $length = strlen($a);
  640 + for($i = 0; $i < $length; $i++) {
  641 + $a[$i] = $a[$i] ^ $b[$i];
  642 + }
  643 +
  644 + return $a;
  645 + }
  646 +
  647 + /**
  648 + * Prepares an indirect response url.
  649 + * @param array $params Parameters to be sent.
  650 + */
  651 + protected function response($params)
  652 + {
  653 + $params += array('openid.ns' => $this->ns);
  654 + return $this->data['openid_return_to']
  655 + . (strpos($this->data['openid_return_to'],'?') ? '&' : '?')
  656 + . http_build_query($params, '', '&');
  657 + }
  658 +
  659 + /**
  660 + * Outputs a direct error.
  661 + */
  662 + protected function errorResponse()
  663 + {
  664 + if(!empty($this->data['openid_return_to'])) {
  665 + $response = array(
  666 + 'openid.mode' => 'error',
  667 + 'openid.error' => 'Invalid request'
  668 + );
  669 + $this->redirect($this->response($response));
  670 + } else {
  671 + header('HTTP/1.1 400 Bad Request');
  672 + $response = array(
  673 + 'ns' => $this->ns,
  674 + 'error' => 'Invalid request'
  675 + );
  676 + echo $this->keyValueForm($response);
  677 + }
  678 + die();
  679 + }
  680 +
  681 + /**
  682 + * Sends an positive assertion.
  683 + * @param String $identity the OP-Local Identifier that is being authenticated.
  684 + * @param Array $attributes User attributes to be sent.
  685 + */
  686 + protected function positiveResponse($identity, $attributes)
  687 + {
  688 + # We generate a private association if there is none established.
  689 + if(!$this->assoc) {
  690 + $this->generateAssociation();
  691 + $this->assoc['private'] = true;
  692 + }
  693 +
  694 + # We set openid.identity (and openid.claimed_id if necessary) to our $identity
  695 + if($this->data['openid_identity'] == $this->data['openid_claimed_id'] || $this->select_id) {
  696 + $this->data['openid_claimed_id'] = $identity;
  697 + }
  698 + $this->data['openid_identity'] = $identity;
  699 +
  700 + # Preparing fields to be signed
  701 + $params = array(
  702 + 'op_endpoint' => $this->serverLocation,
  703 + 'claimed_id' => $this->data['openid_claimed_id'],
  704 + 'identity' => $this->data['openid_identity'],
  705 + 'return_to' => $this->data['openid_return_to'],
  706 + 'realm' => $this->data['openid_realm'],
  707 + 'response_nonce' => gmdate("Y-m-d\TH:i:s\Z"),
  708 + 'assoc_handle' => $this->assoc['handle'],
  709 + );
  710 +
  711 + $params += $this->responseAttributes($attributes);
  712 +
  713 + # Has the RP used an invalid association handle?
  714 + if (isset($this->data['openid_assoc_handle'])
  715 + && $this->data['openid_assoc_handle'] != $this->assoc['handle']
  716 + ) {
  717 + $params['invalidate_handle'] = $this->data['openid_assoc_handle'];
  718 + }
  719 +
  720 + # Signing the $params
  721 + $sig = hash_hmac($this->assoc['hash'], $this->keyValueForm($params), $this->assoc['mac'], true);
  722 + $req = array(
  723 + 'openid.mode' => 'id_res',
  724 + 'openid.signed' => implode(',', array_keys($params)),
  725 + 'openid.sig' => base64_encode($sig),
  726 + );
  727 +
  728 + # Saving the nonce and commiting the association.
  729 + $this->assoc['nonce'] = $params['response_nonce'];
  730 + $this->setAssoc($this->assoc['handle'], $this->assoc);
  731 +
  732 + # Preparing and sending the response itself
  733 + foreach($params as $name => $value) {
  734 + $req['openid.' . $name] = $value;
  735 + }
  736 +
  737 + $this->redirect($this->response($req));
  738 + }
  739 +
  740 + /**
  741 + * Prepares an array of attributes to send
  742 + */
  743 + protected function responseAttributes($attributes)
  744 + {
  745 + if(!$attributes) return array();
  746 +
  747 + $ns = 'http://axschema.org/';
  748 +
  749 + $response = array();
  750 + if(isset($this->data['ax'])) {
  751 + $response['ns.ax'] = 'http://openid.net/srv/ax/1.0';
  752 + foreach($attributes as $name => $value) {
  753 + $alias = strtr($name, '/', '_');
  754 + $response['ax.type.' . $alias] = $ns . $name;
  755 + $response['ax.value.' . $alias] = $value;
  756 + }
  757 + return $response;
  758 + }
  759 +
  760 + foreach($attributes as $name => $value) {
  761 + if(!isset($this->ax_to_sreg[$name])) {
  762 + continue;
  763 + }
  764 +
  765 + $response['sreg.' . $this->ax_to_sreg[$name]] = $value;
  766 + }
  767 + return $response;
  768 + }
  769 +
  770 + /**
  771 + * Encodes fields in key-value form.
  772 + * @param Array $params Fields to be encoded.
  773 + * @return String $params in key-value form.
  774 + */
  775 + protected function keyValueForm($params)
  776 + {
  777 + $str = '';
  778 + foreach($params as $name => $value) {
  779 + $str .= "$name:$value\n";
  780 + }
  781 +
  782 + return $str;
  783 + }
  784 +
  785 + /**
  786 + * Responds with an information that the user has canceled authentication.
  787 + */
  788 + protected function cancel()
  789 + {
  790 + $this->redirect($this->response(array('openid.mode' => 'cancel')));
  791 + }
  792 +
  793 + /**
  794 + * Converts base64 encoded number to it's decimal representation.
  795 + * @param String $str base64 encoded number.
  796 + * @return String Decimal representation of that number.
  797 + */
  798 + protected function b64dec($str)
  799 + {
  800 + $bytes = unpack('C*', base64_decode($str));
  801 + $n = 0;
  802 + foreach($bytes as $byte) {
  803 + $n = $this->add($this->mul($n, 256), $byte);
  804 + }
  805 +
  806 + return $n;
  807 + }
  808 +
  809 + /**
  810 + * Complements b64dec.
  811 + */
  812 + protected function decb64($num)
  813 + {
  814 + $bytes = array();
  815 + while($num) {
  816 + array_unshift($bytes, $this->mod($num, 256));
  817 + $num = $this->div($num, 256);
  818 + }
  819 +
  820 + if($bytes && $bytes[0] > 127) {
  821 + array_unshift($bytes,0);
  822 + }
  823 +
  824 + array_unshift($bytes, 'C*');
  825 +
  826 + return base64_encode(call_user_func_array('pack', $bytes));
  827 + }
  828 +
  829 + function __call($name, $args)
  830 + {
  831 + switch($name) {
  832 + case 'add':
  833 + case 'mul':
  834 + case 'pow':
  835 + case 'mod':
  836 + case 'div':
  837 + case 'powmod':
  838 + if(function_exists('gmp_strval')) {
  839 + return gmp_strval(call_user_func_array($this->$name, $args));
  840 + }
  841 + return call_user_func_array($this->$name, $args);
  842 + default:
  843 + throw new BadMethodCallException();
  844 + }
  845 + }
  846 +}
... ...
common/config/main-local.php
... ... @@ -3,7 +3,7 @@ return [
3 3 'components' => [
4 4 'db' => [
5 5 'class' => 'yii\db\Connection',
6   - 'dsn' => 'pgsql:host=localhost;port=5432;dbname=artbox_db',
  6 + 'dsn' => 'pgsql:host=localhost;port=5432;dbname=artbox_test',
7 7 'username' => 'postgres',
8 8 'password' => '',
9 9 'schemaMap' => [
... ...
common/config/main.php
... ... @@ -55,7 +55,7 @@ return [
55 55 //подключаем конфигурации API соц сетей для авторизации
56 56  
57 57 'eauth' => [
58   - 'class' => 'nodge\eauth\EAuth',
  58 + 'class' => 'common\components\nodge\eauth\src\EAuth',
59 59 'popup' => true, // Use the popup window instead of redirecting.
60 60 'cache' => false, // Cache component name or false to disable cache. Defaults to 'cache' on production environments.
61 61 'cacheExpire' => 0, // Cache lifetime. Defaults to 0 - means unlimited.
... ... @@ -66,86 +66,86 @@ return [
66 66 'services' => [ // You can change the providers and their classes.
67 67 'google' => [
68 68 // register your app here: https://code.google.com/apis/console/
69   - 'class' => 'nodge\eauth\services\GoogleOAuth2Service',
  69 + 'class' => 'common\components\nodge\eauth\src\services\GoogleOAuth2Service',
70 70 'clientId' => 'artbox-1138',
71 71 'clientSecret' => '',
72 72 'title' => 'Google',
73 73 ],
74 74 'twitter' => [
75 75 // register your app here: https://dev.twitter.com/apps/new
76   - 'class' => 'nodge\eauth\services\TwitterOAuth1Service',
  76 + 'class' => 'common\components\nodge\eauth\src\services\TwitterOAuth1Service',
77 77 'key' => '8vReLxI63vTs98MBMqhvrszwy',
78 78 'secret' => 'jOqNbHIkQw4cVKKJkgrMtaEeCcfbeT1GTik4pF6O9D7AmqcwOG',
79 79 ],
80 80 'yandex' => [
81 81 // register your app here: https://oauth.yandex.ru/client/my
82   - 'class' => 'nodge\eauth\services\YandexOAuth2Service',
  82 + 'class' => 'common\components\nodge\eauth\src\services\YandexOAuth2Service',
83 83 'clientId' => 'ea13195ac0424ff8a190838bec41bb71',
84 84 'clientSecret' => '911f2c9afcbf4f5f9319b3134c096c86',
85 85 'title' => 'Yandex',
86 86 ],
87 87 'facebook' => [
88 88 // register your app here: https://developers.facebook.com/apps/
89   - 'class' => 'nodge\eauth\services\FacebookOAuth2Service',
  89 + 'class' => 'common\components\nodge\eauth\src\services\FacebookOAuth2Service',
90 90 'clientId' => '1642047622727997',
91 91 'clientSecret' => 'f5b7ba4f062a568678b764fc74cc416e',
92 92 ],
93 93 'yahoo' => [
94   - 'class' => 'nodge\eauth\services\YahooOpenIDService',
  94 + 'class' => 'common\components\nodge\eauth\src\services\YahooOpenIDService',
95 95 //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
96 96 ],
97 97 'linkedin' => [
98 98 // register your app here: https://www.linkedin.com/secure/developer
99   - 'class' => 'nodge\eauth\services\LinkedinOAuth1Service',
  99 + 'class' => 'common\components\nodge\eauth\src\services\LinkedinOAuth1Service',
100 100 'key' => '77s41eixn3dyvo',
101 101 'secret' => '1xLZQ7RRK6RNjo4U',
102 102 'title' => 'LinkedIn (OAuth1)',
103 103 ],
104 104 'linkedin_oauth2' => [
105 105 // register your app here: https://www.linkedin.com/secure/developer
106   - 'class' => 'nodge\eauth\services\LinkedinOAuth2Service',
  106 + 'class' => 'common\components\nodge\eauth\src\services\LinkedinOAuth2Service',
107 107 'clientId' => '77s41eixn3dyvo',
108 108 'clientSecret' => '1xLZQ7RRK6RNjo4U',
109 109 'title' => 'LinkedIn (OAuth2)',
110 110 ],
111 111 'github' => [
112 112 // register your app here: https://github.com/settings/applications
113   - 'class' => 'nodge\eauth\services\GitHubOAuth2Service',
  113 + 'class' => 'common\components\nodge\eauth\src\services\GitHubOAuth2Service',
114 114 'clientId' => 'd00283b5cfb225cd1600',
115 115 'clientSecret' => 'f482361fad7184819d452f421c8b09db60830b42',
116 116 ],
117 117 'live' => [
118 118 // register your app here: https://account.live.com/developers/applications/index
119   - 'class' => 'nodge\eauth\services\LiveOAuth2Service',
  119 + 'class' => 'common\components\nodge\eauth\src\services\LiveOAuth2Service',
120 120 'clientId' => '00000000481796AE',
121 121 'clientSecret' => 'rt9GiJrlKz3sE6CvdOeuwWyYbl1tQT03',
122 122 ],
123 123 'steam' => [
124   - 'class' => 'nodge\eauth\services\SteamOpenIDService',
  124 + 'class' => 'common\components\nodge\eauth\src\services\SteamOpenIDService',
125 125 //'realm' => '*.example.org', // your domain, can be with wildcard to authenticate on subdomains.
126 126 ],
127 127 'instagram' => [
128 128 // register your app here: https://instagram.com/developer/register/
129   - 'class' => 'nodge\eauth\services\InstagramOAuth2Service',
  129 + 'class' => 'common\components\nodge\eauth\src\services\InstagramOAuth2Service',
130 130 'clientId' => '...',
131 131 'clientSecret' => '...',
132 132 ],
133 133 'vkontakte' => [
134 134 // register your app here: https://vk.com/editapp?act=create&site=1
135   - 'class' => 'nodge\eauth\services\VKontakteOAuth2Service',
  135 + 'class' => 'common\components\nodge\eauth\src\services\VKontakteOAuth2Service',
136 136 'clientId' => '5155388',
137 137 'clientSecret' => 'jxgmdGVQw7huGKRpnX3a',
138 138 ],
139 139 'mailru' => [
140 140 // register your app here: http://api.mail.ru/sites/my/add
141   - 'class' => 'nodge\eauth\services\MailruOAuth2Service',
  141 + 'class' => 'common\components\nodge\eauth\src\services\MailruOAuth2Service',
142 142 'clientId' => '739322',
143 143 'clientSecret' => 'd6ce7be6ff791375adff58fe0e4460b2',
144 144 ],
145 145 'odnoklassniki' => [
146 146 // register your app here: http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=13992188
147 147 // ... or here: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
148   - 'class' => 'nodge\eauth\services\OdnoklassnikiOAuth2Service',
  148 + 'class' => 'common\components\nodge\eauth\src\services\OdnoklassnikiOAuth2Service',
149 149 'clientId' => '...',
150 150 'clientSecret' => '...',
151 151 'clientPublic' => '...',
... ... @@ -160,7 +160,7 @@ return [
160 160 [
161 161 'class' => 'yii\log\FileTarget',
162 162 'logFile' => '@app/runtime/logs/eauth.log',
163   - 'categories' => ['nodge\eauth\*'],
  163 + 'categories' => ['common\components\nodge\eauth\nodge\eauth\*'],
164 164 'logVars' => [],
165 165 ],
166 166 ],
... ...
db-migration/artbox_db3.backup 0 → 100644
No preview for this file type
db-migration/dmitryi/all.backup 0 → 100644
No preview for this file type
db-migration/dmitryi/auth_assignup.backup 0 → 100644
No preview for this file type
db-migration/dmitryi/auth_item.backup 0 → 100644
No preview for this file type
db-migration/dmitryi/auth_item_child.backup 0 → 100644
No preview for this file type
db-migration/dmitryi/auth_rule.backup 0 → 100644
No preview for this file type
db-migration/social.backup renamed to db-migration/dmitryi/social.backup
No preview for this file type
db-migration/user.backup renamed to db-migration/dmitryi/user.backup
No preview for this file type
frontend/controllers/SiteController.php
... ... @@ -190,7 +190,7 @@ class SiteController extends Controller
190 190 */
191 191 public function actionContact()
192 192 {
193   - //Yii::$app->user->logout();
  193 + Yii::$app->user->logout();
194 194 $identity = Yii::$app->getUser()->getIdentity();
195 195 var_dump($identity[profile]);
196 196 die();
... ...