Permalink
Browse files

* Added access_token lifetime handling, #1 closed. Please, check your…

… custom OAuth 2.0 classes!

* Added links to provider files to register your applications.
* Removed $_GET['js'] from the redirect_uri for the OAuth 2.0 providers, which could cause problems with a callback URL for some providers.
  • Loading branch information...
1 parent f6ab25f commit 6b5fbbf9170356f1959a17a8bff79429e00105f4 @Nodge committed Jan 3, 2012
View
5 CHANGELOG.md
@@ -5,9 +5,12 @@ Yii EAuth Change Log
* Added MoiKrug OAuth provider.
* Added Odnoklassniki OAuth provider.
* Added ability to write in the log of unsuccessful requests in the EAuthServiceBase::makeRequest().
+* Added access_token lifetime handling, #1 closed. Please, check your custom OAuth 2.0 classes!
+* Added links to provider files to register your applications.
+* Changed url for the Yandex OpenID.
* Fixed infinite loop when calling getAttrbiutes from fetchAttributes inside a provider class.
+* Removed $_GET['js'] from the redirect_uri for the OAuth 2.0 providers, which could cause problems with a callback URL for some providers.
* Small fixes in the css of the widget.
-* Changed url for the Yandex OpenID.
### Version 1.1.4 (13.11.2011)
* Added handling for denied callback in the TwitterOAuthService.
View
51 EOAuth2Service.php
@@ -55,28 +55,29 @@ public function authenticate() {
return false;
}
- //Получаем "access_token" и сохр. в сессионной переменной
+ // Get the access_token and save them to the session.
if (isset($_GET['code'])) {
$code = $_GET['code'];
$token = $this->getAccessToken($code);
if (isset($token)) {
- $this->setState('auth_token', $token);
- $this->access_token = $token;
+ $this->saveAccessToken($token);
$this->authenticated = true;
}
}
- //Получаем "code"
- else if (!$this->hasState('auth_token')) {
+ // Redirect to the authorization page
+ else if (!$this->restoreAccessToken()) {
// Use the URL of the current page as the callback URL.
- $server = Yii::app()->request->getHostInfo();
- $path = Yii::app()->request->getUrl();
- $url = $this->getCodeUrl($server.$path);
+ if (isset($_GET['redirect_uri'])) {
+ $redirect_uri = $_GET['redirect_uri'];
+ }
+ else {
+ $server = Yii::app()->request->getHostInfo();
+ $path = Yii::app()->request->getUrl();
+ $redirect_uri = $server.$path;
+ }
+ $url = $this->getCodeUrl($redirect_uri);
Yii::app()->request->redirect($url);
}
- else {
- $this->access_token = $this->getState('auth_token');
- $this->authenticated = true;
- }
return $this->getIsAuthenticated();
}
@@ -108,6 +109,32 @@ protected function getAccessToken($code) {
}
/**
+ * Save access token to the session.
+ * @param string $token access token.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token);
+ $this->access_token = $token;
+ }
+
+ /**
+ * Restore access token from the session.
+ * @return boolean whether the access token was successfuly restored.
+ */
+ protected function restoreAccessToken() {
+ if ($this->hasState('auth_token') && $this->getState('expires', 0) > time()) {
+ $this->access_token = $this->getState('auth_token');
+ $this->authenticated = true;
+ return true;
+ }
+ else {
+ $this->access_token = null;
+ $this->authenticated = false;
+ return false;
+ }
+ }
+
+ /**
* Returns the protected resource.
* @param string $url url to request.
* @param array $options HTTP request options. Keys: query, data, referer.
View
7 assets/js/auth.js
@@ -22,10 +22,13 @@ jQuery(function($) {
if (popup !== undefined)
popup.close();
- var url = this.href + (this.href.indexOf('?') >= 0 ? '&' : '?') + 'js';
+ var redirect_uri, url = redirect_uri = this.href;
+ url += (url.indexOf('?') >= 0 ? '&' : '?') + 'redirect_uri=' + encodeURIComponent(redirect_uri);
+ url += '&js';
+
/*var remember = $(this).parents('.auth-services').parent().find('.auth-services-rememberme');
if (remember.size() > 0 && remember.find('input').is(':checked'))
- url += '&remember';*/
+ url += (url.indexOf('?') >= 0 ? '&' : '?') + 'remember';*/
var centerWidth = ($(window).width() - options.popup.width) / 2;
var centerHeight = ($(window).height() - options.popup.height) / 2;
View
2 custom_services/CustomMailruService.php
@@ -14,7 +14,7 @@ class CustomMailruService extends MailruOAuthService {
protected function fetchAttributes() {
$info = (array)$this->makeSignedRequest('http://www.appsmail.ru/platform/api', array(
'query' => array(
- 'uids' => $this->getUid(),
+ 'uids' => $this->uid,
'method' => 'users.getInfo',
'app_id' => $this->client_id,
),
View
2 custom_services/CustomVKontakteService.php
@@ -16,7 +16,7 @@ class CustomVKontakteService extends VKontakteOAuthService {
protected function fetchAttributes() {
$info = (array)$this->makeSignedRequest('https://api.vkontakte.ru/method/getProfiles', array(
'query' => array(
- 'uids' => $this->getUid(),
+ 'uids' => $this->uid,
//'fields' => '', // uid, first_name and last_name is always available
'fields' => 'nickname, sex, bdate, city, country, timezone, photo, photo_medium, photo_big, photo_rec',
),
View
35 services/FacebookOAuthService.php
@@ -2,6 +2,8 @@
/**
* FacebookOAuthService class file.
*
+ * Register application: https://developers.facebook.com/apps/
+ *
* @author Maxim Zemskov <nodge@yandex.ru>
* @link http://code.google.com/p/yii-eauth/
* @license http://www.opensource.org/licenses/bsd-license.php
@@ -35,34 +37,43 @@ protected function fetchAttributes() {
$this->attributes['name'] = $info->name;
$this->attributes['url'] = $info->link;
}
-
- protected function getTokenUrl($code) {
- return parent::getTokenUrl($code).'&redirect_uri='.urlencode($this->getState('redirect_uri'));
- }
-
- protected function getAccessToken($code) {
- $response = $this->makeRequest($this->getTokenUrl($code), array(), false);
- parse_str($response, $result);
- return $result['access_token'];
- }
protected function getCodeUrl($redirect_uri) {
- /*if (strpos($redirect_uri, '?') !== false || strpos($redirect_uri, '&') !== false)
- throw new EAuthException('Facebook does not support url with special characters. You should use SEF urls for authentication through Facebook.', 500);*/
if (strpos($redirect_uri, '?') !== false) {
$url = explode('?', $redirect_uri);
$url[1] = preg_replace('#[/]#', '%2F', $url[1]);
$redirect_uri = implode('?', $url);
}
$this->setState('redirect_uri', $redirect_uri);
+
$url = parent::getCodeUrl($redirect_uri);
if (isset($_GET['js']))
$url .= '&display=popup';
return $url;
}
+ protected function getTokenUrl($code) {
+ return parent::getTokenUrl($code).'&redirect_uri='.urlencode($this->getState('redirect_uri'));
+ }
+
+ protected function getAccessToken($code) {
+ $response = $this->makeRequest($this->getTokenUrl($code), array(), false);
+ parse_str($response, $result);
+ return $result;
+ }
+
+ /**
+ * Save access token to the session.
+ * @param array $token access token array.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token['access_token']);
+ $this->setState('expires', time() + (int)$token['expires'] - 60);
+ $this->access_token = $token['access_token'];
+ }
+
/**
* Returns the error info from json.
* @param stdClass $json the json response.
View
33 services/GoogleOAuthService.php
@@ -1,7 +1,9 @@
<?php
/**
* GoogleOAuthService class file.
- *
+ *
+ * Register application: https://code.google.com/apis/console/
+ *
* @author Maxim Zemskov <nodge@yandex.ru>
* @link http://code.google.com/p/yii-eauth/
* @license http://www.opensource.org/licenses/bsd-license.php
@@ -49,30 +51,39 @@ protected function fetchAttributes() {
$info['locale']; // format: en*/
}
+ protected function getCodeUrl($redirect_uri) {
+ $this->setState('redirect_uri', $redirect_uri);
+ $url = parent::getCodeUrl($redirect_uri);
+ if (isset($_GET['js']))
+ $url .= '&display=popup';
+ return $url;
+ }
+
protected function getTokenUrl($code) {
return $this->providerOptions['access_token'];
}
- protected function getAccessToken($code) {
+ protected function getAccessToken($code) {
$params = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $this->getState('redirect_uri'),
);
- $result = $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
- return $result->access_token;
+ return $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
}
- protected function getCodeUrl($redirect_uri) {
- $this->setState('redirect_uri', $redirect_uri);
- $url = parent::getCodeUrl($redirect_uri);
- //if (isset($_GET['js']))
- //$url .= '&display=popup';
- return $url;
+ /**
+ * Save access token to the session.
+ * @param stdClass $token access token array.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token->access_token);
+ $this->setState('expires', time() + $token->expires_in - 60);
+ $this->access_token = $token->access_token;
}
-
+
/**
* Makes the curl request to the url.
* @param string $url url to request.
View
64 services/MailruOAuthService.php
@@ -2,6 +2,8 @@
/**
* MailRuOAuthService class file.
*
+ * Register application: http://api.mail.ru/sites/my/add
+ *
* @author ChooJoy <choojoy.work@gmail.com>
* @link http://code.google.com/p/yii-eauth/
* @license http://www.opensource.org/licenses/bsd-license.php
@@ -27,11 +29,13 @@ class MailruOAuthService extends EOAuth2Service {
'authorize' => 'https://connect.mail.ru/oauth/authorize',
'access_token' => 'https://connect.mail.ru/oauth/token',
);
+
+ protected $uid = null;
protected function fetchAttributes() {
$info = (array)$this->makeSignedRequest('http://www.appsmail.ru/platform/api', array(
'query' => array(
- 'uids' => $this->getUid(),
+ 'uids' => $this->uid,
'method' => 'users.getInfo',
'app_id' => $this->client_id,
),
@@ -44,32 +48,58 @@ protected function fetchAttributes() {
$this->attributes['url'] = $info->link;
}
+ protected function getCodeUrl($redirect_uri) {
+ $this->setState('redirect_uri', $redirect_uri);
+
+ $url = parent::getCodeUrl($redirect_uri);
+ if (isset($_GET['js']))
+ $url .= '&display=popup';
+
+ return $url;
+ }
+
protected function getTokenUrl($code) {
return $this->providerOptions['access_token'];
}
- protected function getAccessToken($code) {
+ protected function getAccessToken($code) {
$params = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $this->getState('redirect_uri'),
);
- $result = $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
- $this->setState('uid', $result->x_mailru_vid);
- return $result->access_token;
+ return $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
}
- protected function getCodeUrl($redirect_uri) {
- $this->setState('redirect_uri', $redirect_uri);
- $url = parent::getCodeUrl($redirect_uri);
- if (isset($_GET['js']))
- $url .= '&display=popup';
-
- return $url;
+ /**
+ * Save access token to the session.
+ * @param stdClass $token access token object.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token->access_token);
+ $this->setState('uid', $token->x_mailru_vid);
+ $this->setState('expires', time() + $token->expires_in - 60);
+ $this->uid = $token->x_mailru_vid;
+ $this->access_token = $token->access_token;
}
-
+
+ /**
+ * Restore access token from the session.
+ * @return boolean whether the access token was successfuly restored.
+ */
+ protected function restoreAccessToken() {
+ if ($this->hasState('uid') && parent::restoreAccessToken()) {
+ $this->uid = $this->getState('uid');
+ return true;
+ }
+ else {
+ $this->uid = null;
+ return false;
+ }
+ }
+
public function makeSignedRequest($url, $options = array(), $parseJson = true) {
if (!$this->getIsAuthenticated())
throw new CHttpException(401, Yii::t('eauth', 'Unable to complete the authentication because the required data was not received.', array('{provider}' => ucfirst($this->serviceName))));
@@ -85,13 +115,7 @@ public function makeSignedRequest($url, $options = array(), $parseJson = true) {
$result = $this->makeRequest($url, $options);
return $result;
}
-
- protected function getUid() {
- if (!$this->hasState('uid'))
- throw new EAuthException('Unable to get mailru user id.', 500);
- return $this->getState('uid');
- }
-
+
/**
* Returns the error info from json.
* @param stdClass $json the json response.
View
26 services/MoikrugOAuthService.php
@@ -3,7 +3,6 @@
* MoikrugOAuthService class file.
*
* Register application: https://oauth.yandex.ru/client/my
- * Example callback for the registration: http://example.com/index.php?r=site/login&service=moikrug&js
*
* @author Maxim Zemskov <nodge@yandex.ru>
* @link http://code.google.com/p/yii-eauth/
@@ -21,7 +20,7 @@ class MoikrugOAuthService extends EOAuth2Service {
protected $name = 'moikrug';
protected $title = 'Мой круг';
protected $type = 'OAuth';
- protected $jsArguments = array('popup' => array('width' => 400, 'height' => 350));
+ protected $jsArguments = array('popup' => array('width' => 500, 'height' => 450));
protected $client_id = '';
protected $client_secret = '';
@@ -42,6 +41,13 @@ protected function fetchAttributes() {
$this->attributes['gender'] = ($info['gender'] == 'male') ? 'M' : 'F';
}
+ protected function getCodeUrl($redirect_uri) {
+ $url = parent::getCodeUrl($redirect_uri);
+ if (isset($_GET['js']))
+ $url .= '&display=popup';
+ return $url;
+ }
+
protected function getTokenUrl($code) {
return $this->providerOptions['access_token'];
}
@@ -53,15 +59,17 @@ protected function getAccessToken($code) {
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
);
- $result = $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
- return $result->access_token;
+ return $this->makeRequest($this->getTokenUrl($code), array('data' => $params));
}
- protected function getCodeUrl($redirect_uri) {
- $url = parent::getCodeUrl($redirect_uri);
- if (isset($_GET['js']))
- $url .= '&display=popup';
- return $url;
+ /**
+ * Save access token to the session.
+ * @param stdClass $token access token array.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token->access_token);
+ $this->setState('expires', time() + (isset($token->expires_in) ? $token->expires_in : 365*86400) - 60);
+ $this->access_token = $token->access_token;
}
/**
View
7 services/OdnoklassnikiOAuthService.php
@@ -2,6 +2,7 @@
/**
* OdnoklassnikiOAuthService class file.
*
+ * Register application: http://www.odnoklassniki.ru/dk?st.cmd=appsInfoMyDevList&st._aid=Apps_Info_MyDev
* Note: Enabling this service a little more difficult because of the authorization policy of the service.
*
* @author Sergey Vardanyan <rakot.ss@gmail.com>
@@ -73,12 +74,6 @@ protected function getCodeUrl($redirect_uri) {
return $url;
}
- protected function getUid() {
- if (!$this->hasState('uid'))
- throw new EAuthException('Unable to get odnoklassniki user id.', 500);
- return $this->getState('uid');
- }
-
/**
* Returns the error info from json.
* @param stdClass $json the json response.
View
2 services/TwitterOAuthService.php
@@ -2,6 +2,8 @@
/**
* TwitterOAuthService class file.
*
+ * Register application: https://dev.twitter.com/apps/new
+ *
* @author Maxim Zemskov <nodge@yandex.ru>
* @link http://code.google.com/p/yii-eauth/
* @license http://www.opensource.org/licenses/bsd-license.php
View
56 services/VKontakteOAuthService.php
@@ -2,6 +2,8 @@
/**
* VKontakteOAuthService class file.
*
+ * Register application: http://vkontakte.ru/editapp?act=create&site=1
+ *
* @author Maxim Zemskov <nodge@yandex.ru>
* @link http://code.google.com/p/yii-eauth/
* @license http://www.opensource.org/licenses/bsd-license.php
@@ -18,7 +20,7 @@ class VKontakteOAuthService extends EOAuth2Service {
protected $name = 'vkontakte';
protected $title = 'ВКонтакте';
protected $type = 'OAuth';
- protected $jsArguments = array('popup' => array('width' => 824, 'height' => 500));
+ protected $jsArguments = array('popup' => array('width' => 585, 'height' => 350));
protected $client_id = '';
protected $client_secret = '';
@@ -28,10 +30,12 @@ class VKontakteOAuthService extends EOAuth2Service {
'access_token' => 'https://api.vkontakte.ru/oauth/access_token',
);
+ protected $uid = null;
+
protected function fetchAttributes() {
$info = (array)$this->makeSignedRequest('https://api.vkontakte.ru/method/getProfiles', array(
'query' => array(
- 'uids' => $this->getUid(),
+ 'uids' => $this->uid,
'fields' => '', // uid, first_name and last_name is always available
//'fields' => 'nickname, sex, bdate, city, country, timezone, photo, photo_medium, photo_big, photo_rec',
),
@@ -61,26 +65,46 @@ protected function fetchAttributes() {
$this->attributes['photo_rec'] = $info->photo_rec;*/
}
- protected function getUid() {
- if (!$this->hasState('uid'))
- throw new EAuthException('Unable to get vkontakte user id.', 500);
- return $this->getState('uid');
- }
-
- protected function getAccessToken($code) {
- $result = parent::getAccessToken($code);
- $this->setState('uid', $result->user_id);
- return $result->access_token;
- }
-
- /*protected function getCodeUrl($redirect_uri) {
+ /**
+ * Returns the url to request to get OAuth2 code.
+ * @param string $redirect_uri url to redirect after user confirmation.
+ * @return string url to request.
+ */
+ protected function getCodeUrl($redirect_uri) {
$url = parent::getCodeUrl($redirect_uri);
if (isset($_GET['js']))
$url .= '&display=popup';
return $url;
- }*/
+ }
+
+ /**
+ * Save access token to the session.
+ * @param stdClass $token access token object.
+ */
+ protected function saveAccessToken($token) {
+ $this->setState('auth_token', $token->access_token);
+ $this->setState('uid', $token->user_id);
+ $this->setState('expires', time() + $token->expires_in - 60);
+ $this->uid = $token->user_id;
+ $this->access_token = $token->access_token;
+ }
/**
+ * Restore access token from the session.
+ * @return boolean whether the access token was successfuly restored.
+ */
+ protected function restoreAccessToken() {
+ if ($this->hasState('uid') && parent::restoreAccessToken()) {
+ $this->uid = $this->getState('uid');
+ return true;
+ }
+ else {
+ $this->uid = null;
+ return false;
+ }
+ }
+
+ /**
* Returns the error info from json.
* @param stdClass $json the json response.
* @return array the error array with 2 keys: code and message. Should be null if no errors.

0 comments on commit 6b5fbbf

Please sign in to comment.