1
0
mirror of https://github.com/e107inc/e107.git synced 2025-07-31 20:00:37 +02:00

HybridAuth upgraded to 2.3.0

This commit is contained in:
Cameron
2015-01-23 14:44:00 -08:00
parent 833567be4c
commit a2af913640
31 changed files with 1391 additions and 449 deletions

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -14,7 +14,7 @@
*/
class Hybrid_Auth
{
public static $version = "2.1.2";
public static $version = "2.3.0";
public static $config = array();
@@ -68,10 +68,9 @@ class Hybrid_Auth
# load hybridauth required files, a autoload is on the way...
require_once $config["path_base"] . "Error.php";
require_once $config["path_base"] . "Exception.php";
require_once $config["path_base"] . "Logger.php";
require_once $config["path_base"] . "Storage.php";
require_once $config["path_base"] . "Provider_Adapter.php";
require_once $config["path_base"] . "Provider_Model.php";
@@ -84,13 +83,17 @@ class Hybrid_Auth
require_once $config["path_base"] . "User_Contact.php";
require_once $config["path_base"] . "User_Activity.php";
if ( ! class_exists("Hybrid_Storage", false) ){
require_once $config["path_base"] . "Storage.php";
}
// hash given config
Hybrid_Auth::$config = $config;
// instace of log mng
// instance of log mng
Hybrid_Auth::$logger = new Hybrid_Logger();
// instace of errors mng
// instance of errors mng
Hybrid_Auth::$error = new Hybrid_Error();
// start session storage mng
@@ -161,7 +164,7 @@ class Hybrid_Auth
/**
* Hybrid storage system accessor
*
* Users sessions are stored using HybridAuth storage system ( HybridAuth 2.0 handle PHP Session only) and can be acessed directly by
* Users sessions are stored using HybridAuth storage system ( HybridAuth 2.0 handle PHP Session only) and can be accessed directly by
* Hybrid_Auth::storage()->get($key) to retrieves the data for the given key, or calling
* Hybrid_Auth::storage()->set($key, $value) to store the key => $value set.
*/
@@ -249,7 +252,7 @@ class Hybrid_Auth
if( ! $params ){
$params = Hybrid_Auth::storage()->get( "hauth_session.$providerId.id_provider_params" );
Hybrid_Logger::debug( "Hybrid_Auth::setup( $providerId ), no params given. Trying to get the sotred for this provider.", $params );
Hybrid_Logger::debug( "Hybrid_Auth::setup( $providerId ), no params given. Trying to get the stored for this provider.", $params );
}
if( ! $params ){
@@ -258,11 +261,11 @@ class Hybrid_Auth
Hybrid_Logger::info( "Hybrid_Auth::setup( $providerId ), no stored params found for this provider. Initialize a new one for new session" );
}
if( ! isset( $params["hauth_return_to"] ) ){
if( is_array($params) && ! isset( $params["hauth_return_to"] ) ){
$params["hauth_return_to"] = Hybrid_Auth::getCurrentUrl();
}
Hybrid_Logger::debug( "Hybrid_Auth::setup( $providerId ). HybridAuth Callback URL set to: ", $params["hauth_return_to"] );
Hybrid_Logger::debug( "Hybrid_Auth::setup( $providerId ). HybridAuth Callback URL set to: ", $params["hauth_return_to"] );
}
# instantiate a new IDProvider Adapter
$provider = new Hybrid_Provider_Adapter();
@@ -385,14 +388,6 @@ class Hybrid_Auth
$url = $protocol . $_SERVER['HTTP_HOST'];
// use port if non default
if( isset( $_SERVER['SERVER_PORT'] ) && strpos( $url, ':'.$_SERVER['SERVER_PORT'] ) === FALSE ) {
$url .= ($protocol === 'http://' && $_SERVER['SERVER_PORT'] != 80 && !isset( $_SERVER['HTTP_X_FORWARDED_PROTO']))
|| ($protocol === 'https://' && $_SERVER['SERVER_PORT'] != 443 && !isset( $_SERVER['HTTP_X_FORWARDED_PROTO']))
? ':' . $_SERVER['SERVER_PORT']
: '';
}
if( $request_uri ){
$url .= $_SERVER['REQUEST_URI'];
}

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -119,8 +119,7 @@ class Hybrid_Endpoint {
if( ! Hybrid_Auth::storage()->get( "hauth_session.$provider_id.hauth_endpoint" ) ) {
Hybrid_Logger::error( "Endpoint: hauth_endpoint parameter is not defined on hauth_start, halt login process!" );
header( "HTTP/1.0 404 Not Found" );
die( "You cannot access this page directly." );
throw new Hybrid_Exception( "You cannot access this page directly." );
}
# define:hybrid.endpoint.php step 2.
@@ -130,8 +129,7 @@ class Hybrid_Endpoint {
if( ! $hauth ) {
Hybrid_Logger::error( "Endpoint: Invalid parameter on hauth_start!" );
header( "HTTP/1.0 404 Not Found" );
die( "Invalid parameter! Please return to the login page and try again." );
throw new Hybrid_Exception( "Invalid parameter! Please return to the login page and try again." );
}
try {
@@ -141,7 +139,7 @@ class Hybrid_Endpoint {
}
catch ( Exception $e ) {
Hybrid_Logger::error( "Exception:" . $e->getMessage(), $e );
Hybrid_Error::setError( $e->getMessage(), $e->getCode(), $e->getTraceAsString(), $e );
Hybrid_Error::setError( $e->getMessage(), $e->getCode(), $e->getTraceAsString(), $e->getPrevious() );
$hauth->returnToCallbackUrl();
}
@@ -165,8 +163,7 @@ class Hybrid_Endpoint {
$hauth->adapter->setUserUnconnected();
header("HTTP/1.0 404 Not Found");
die( "Invalid parameter! Please return to the login page and try again." );
throw new Hybrid_Exception( "Invalid parameter! Please return to the login page and try again." );
}
try {
@@ -176,7 +173,7 @@ class Hybrid_Endpoint {
}
catch( Exception $e ){
Hybrid_Logger::error( "Exception:" . $e->getMessage(), $e );
Hybrid_Error::setError( $e->getMessage(), $e->getCode(), $e->getTraceAsString(), $e );
Hybrid_Error::setError( $e->getMessage(), $e->getCode(), $e->getTraceAsString(), $e->getPrevious());
$hauth->adapter->setUserUnconnected();
}
@@ -194,23 +191,25 @@ class Hybrid_Endpoint {
# Init Hybrid_Auth
try {
require_once realpath( dirname( __FILE__ ) ) . "/Storage.php";
if(!class_exists("Hybrid_Storage")){
require_once realpath( dirname( __FILE__ ) ) . "/Storage.php";
}
$storage = new Hybrid_Storage();
// Check if Hybrid_Auth session already exist
if ( ! $storage->config( "CONFIG" ) ) {
header( "HTTP/1.0 404 Not Found" );
die( "You cannot access this page directly." );
if ( ! $storage->config( "CONFIG" ) ) {
Hybrid_Logger::error( "Endpoint: Config storage not found when trying to init Hyrid_Auth. " );
throw new Hybrid_Exception( "You cannot access this page directly." );
}
Hybrid_Auth::initialize( $storage->config( "CONFIG" ) );
}
catch ( Exception $e ){
Hybrid_Logger::error( "Endpoint: Error while trying to init Hybrid_Auth" );
Hybrid_Logger::error( "Endpoint: Error while trying to init Hybrid_Auth: " . $e->getMessage());
header( "HTTP/1.0 404 Not Found" );
die( "Oophs. Error!" );
throw new Hybrid_Exception( "Oophs. Error!" );
}
}
}

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -13,7 +13,12 @@
class Hybrid_Error
{
/**
* store error in session
* Store error in session
*
* @param String $message
* @param Number $code
* @param String $trace
* @param String $previous
*/
public static function setError( $message, $code = NULL, $trace = NULL, $previous = NULL )
{
@@ -27,7 +32,7 @@ class Hybrid_Error
}
/**
* clear the last error
* Clear the last error
*/
public static function clearError()
{
@@ -67,7 +72,7 @@ class Hybrid_Error
}
/**
* return string detailled error backtrace as string.
* return string detailed error backtrace as string.
*/
public static function getErrorTrace()
{
@@ -75,7 +80,7 @@ class Hybrid_Error
}
/**
* @return string detailled error backtrace as string.
* @return string detailed error backtrace as string.
*/
public static function getErrorPrevious()
{

View File

@@ -0,0 +1,16 @@
<?php
/*!
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* Exception implementation
*
* The base Exception is extended to allow applications to handle exceptions from hybrid auth
* separately from general exceptions.
*/
class Hybrid_Exception extends Exception
{
}

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -10,20 +10,32 @@
*/
class Hybrid_Logger
{
/**
* Constructor
*/
function __construct()
{
// if debug mode is set to true, then check for the writable log file
if ( Hybrid_Auth::$config["debug_mode"] ){
if ( ! file_exists( Hybrid_Auth::$config["debug_file"] ) ){
throw new Exception( "'debug_mode' is set to 'true', but the file " . Hybrid_Auth::$config['debug_file'] . " in 'debug_file' does not exit.", 1 );
// if debug mode is set to true, then check for the writable log file
if ( Hybrid_Auth::$config["debug_mode"] ){
if ( ! isset(Hybrid_Auth::$config["debug_file"]) ) {
throw new Exception( "'debug_mode' is set to 'true' but no log file path 'debug_file' is set.", 1 );
}
elseif ( ! file_exists( Hybrid_Auth::$config["debug_file"] ) && ! is_writable( Hybrid_Auth::$config["debug_file"]) ){
if ( ! touch( Hybrid_Auth::$config["debug_file"] ) ){
throw new Exception( "'debug_mode' is set to 'true', but the file " . Hybrid_Auth::$config['debug_file'] . " in 'debug_file' can not be created.", 1 );
}
}
if ( ! is_writable( Hybrid_Auth::$config["debug_file"] ) ){
elseif ( ! is_writable( Hybrid_Auth::$config["debug_file"] ) ){
throw new Exception( "'debug_mode' is set to 'true', but the given log file path 'debug_file' is not a writable file.", 1 );
}
}
}
/**
* Debug
* @param String $message
* @param Object $object
*/
public static function debug( $message, $object = NULL )
{
if( Hybrid_Auth::$config["debug_mode"] ){
@@ -37,10 +49,14 @@ class Hybrid_Logger
);
}
}
/**
* Info
* @param String $message
*/
public static function info( $message )
{
if( Hybrid_Auth::$config["debug_mode"] ){
if( in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info'), true) ){
$datetime = new DateTime();
$datetime = $datetime->format(DATE_ATOM);
@@ -51,10 +67,15 @@ class Hybrid_Logger
);
}
}
/**
* Error
* @param String $message Error message
* @param Object $object
*/
public static function error($message, $object = NULL)
{
if( Hybrid_Auth::$config["debug_mode"] ){
if(isset(Hybrid_Auth::$config["debug_mode"]) && in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info', 'error'), true) ){
$datetime = new DateTime();
$datetime = $datetime->format(DATE_ATOM);

View File

@@ -1,15 +1,15 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* Hybrid_Provider_Adapter is the basic class which Hybrid_Auth will use
* to connect users to a given provider.
*
* Basically Hybrid_Provider_Adapterwill create a bridge from your php
* Basically Hybrid_Provider_Adapter will create a bridge from your php
* application to the provider api.
*
* Hybrid_Auth will automatically load Hybrid_Provider_Adapter and create
@@ -17,19 +17,34 @@
*/
class Hybrid_Provider_Adapter
{
/* Provider ID (or unique name) */
/**
* Provider ID (or unique name)
* @var Numeric/String
*/
public $id = NULL ;
/* Provider adapter specific config */
/**
* Provider adapter specific config
* @var Array
*/
public $config = NULL ;
/* Provider adapter extra parameters */
public $params = NULL ;
/**
* Provider adapter extra parameters
* @var array
*/
public $params = array() ;
/* Provider adapter wrapper path */
/**
* Provider adapter wrapper path
* @var String
*/
public $wrapper = NULL ;
/* Provider adapter instance */
/**
* Provider adapter instance
* @var object
*/
public $adapter = NULL ;
// --------------------------------------------------------------------
@@ -40,7 +55,7 @@ class Hybrid_Provider_Adapter
* @param string $id The id or name of the IDp
* @param array $params (optional) required parameters by the adapter
*/
function factory( $id, $params = NULL )
function factory( $id, $params = array() )
{
Hybrid_Logger::info( "Enter Hybrid_Provider_Adapter::factory( $id )" );
@@ -67,7 +82,9 @@ class Hybrid_Provider_Adapter
# include the adapter wrapper
if( isset( $this->config["wrapper"] ) && is_array( $this->config["wrapper"] ) ){
require_once $this->config["wrapper"]["path"];
if (isset( $this->config["wrapper"]["path"] )) {
require_once $this->config["wrapper"]["path"];
}
if( ! class_exists( $this->config["wrapper"]["class"] ) ){
throw new Exception( "Unable to load the adapter class.", 3 );
@@ -112,7 +129,21 @@ class Hybrid_Provider_Adapter
$this->logout();
# get hybridauth base url
$HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"];
if (empty(Hybrid_Auth::$config["base_url"])) {
// the base url wasn't provide, so we must use the current
// url (which makes sense actually)
$url = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' ? 'http' : 'https';
$url .= '://' . $_SERVER['HTTP_HOST'];
$url .= $_SERVER['REQUEST_URI'];
$HYBRID_AUTH_URL_BASE = $url;
} else {
$HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"];
}
// make sure params is array
if( !is_array( $this->params ) ){
$this->params = array();
}
# we make use of session_id() as storage hash to identify the current user
# using session_regenerate_id() will be a problem, but ..
@@ -130,9 +161,13 @@ class Hybrid_Provider_Adapter
# auth.done required the IDp ID
$this->params["login_done"] = $HYBRID_AUTH_URL_BASE . ( strpos( $HYBRID_AUTH_URL_BASE, '?' ) ? '&' : '?' ) . "hauth.done={$this->id}";
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to" , $this->params["hauth_return_to"] );
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint" , $this->params["login_done"] );
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );
if( isset( $this->params["hauth_return_to"] ) ){
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to", $this->params["hauth_return_to"] );
}
if( isset( $this->params["login_done"] ) ){
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint" , $this->params["login_done"] );
}
Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );
// store config to be used by the end point
Hybrid_Auth::storage()->config( "CONFIG", Hybrid_Auth::$config );
@@ -184,12 +219,16 @@ class Hybrid_Provider_Adapter
throw new Exception( "Call to undefined function Hybrid_Providers_{$this->id}::$name()." );
}
if( count( $arguments ) ){
return $this->adapter->$name( $arguments[0] );
}
else{
return $this->adapter->$name();
}
$counter = count( $arguments );
if( $counter == 1 ){
return $this->adapter->$name( $arguments[0] );
}
elseif( $counter == 2 ){
return $this->adapter->$name( $arguments[0], $arguments[1] );
}
else{
return $this->adapter->$name();
}
}
// --------------------------------------------------------------------
@@ -242,7 +281,7 @@ class Hybrid_Provider_Adapter
// get the stored callback url
$callback_url = Hybrid_Auth::storage()->get( "hauth_session.{$this->id}.hauth_return_to" );
// remove some unneed'd stored data
// remove some unneeded stored data
Hybrid_Auth::storage()->delete( "hauth_session.{$this->id}.hauth_return_to" );
Hybrid_Auth::storage()->delete( "hauth_session.{$this->id}.hauth_endpoint" );
Hybrid_Auth::storage()->delete( "hauth_session.{$this->id}.id_provider_params" );

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -21,27 +21,48 @@
*/
abstract class Hybrid_Provider_Model
{
/* IDp ID (or unique name) */
/**
* IDp ID (or unique name)
* @var Numeric/String
*/
public $providerId = NULL;
/* specific provider adapter config */
/**
* specific provider adapter config
* @var array
*/
public $config = NULL;
/* provider extra parameters */
/**
* provider extra parameters
* @var array
*/
public $params = NULL;
/* Endpoint URL for that provider */
/**
* Endpoint URL for that provider
* @var String
*/
public $endpoint = NULL;
/* Hybrid_User obj, represents the current loggedin user */
/**
* Hybrid_User obj, represents the current loggedin user
* @var object
*/
public $user = NULL;
/* the provider api client (optional) */
/**
* the provider api client (optional)
* @var String
*/
public $api = NULL;
/**
* common providers adapter constructor
*/
* Common providers adapter constructor
* @param Numeric/String $providerId
* @param Array $config
* @param Array $params
*/
function __construct( $providerId, $config, $params = NULL )
{
# init the IDp adapter parameters, get them from the cache if possible
@@ -77,7 +98,7 @@ abstract class Hybrid_Provider_Model
* IDp wrappers initializer
*
* The main job of wrappers initializer is to performs (depend on the IDp api client it self):
* - include some libs nedded by this provider,
* - include some libs needed by this provider,
* - check IDp key and secret,
* - set some needed parameters (stored in $this->params) by this IDp api client
* - create and setup an instance of the IDp api client on $this->api
@@ -119,7 +140,7 @@ abstract class Hybrid_Provider_Model
*/
function getUserProfile()
{
Hybrid_Logger::error( "HybridAuth do not provide users contats list for {$this->providerId} yet." );
Hybrid_Logger::error( "HybridAuth do not provide users contacts list for {$this->providerId} yet." );
throw new Exception( "Provider does not support this feature.", 8 );
}
@@ -131,7 +152,7 @@ abstract class Hybrid_Provider_Model
*/
function getUserContacts()
{
Hybrid_Logger::error( "HybridAuth do not provide users contats list for {$this->providerId} yet." );
Hybrid_Logger::error( "HybridAuth do not provide users contacts list for {$this->providerId} yet." );
throw new Exception( "Provider does not support this feature.", 8 );
}
@@ -151,7 +172,7 @@ abstract class Hybrid_Provider_Model
// --------------------------------------------------------------------
/**
* return the user activity stream
* set user status
*/
function setUserStatus( $status )
{
@@ -160,6 +181,17 @@ abstract class Hybrid_Provider_Model
throw new Exception( "Provider does not support this feature.", 8 );
}
/**
* return the user status
*/
function getUserStatus( $statusid )
{
Hybrid_Logger::error( "HybridAuth do not provide user's status for {$this->providerId} yet." );
throw new Exception( "Provider does not support this feature.", 8 );
}
// --------------------------------------------------------------------
/**
@@ -222,7 +254,7 @@ abstract class Hybrid_Provider_Model
// --------------------------------------------------------------------
/**
* clear all existen tokens for this provider
* clear all existent tokens for this provider
*/
public function clearTokens()
{

View File

@@ -1,15 +1,15 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* To implement an OAuth 1 based service provider, Hybrid_Provider_Model_OAuth1
* can be used to save the hassle of the authentication flow.
*
* Each class that inherit from Hybrid_Provider_Model_OAuth1 have to implemenent
* Each class that inherit from Hybrid_Provider_Model_OAuth1 have to implement
* at least 2 methods:
* Hybrid_Providers_{provider_name}::initialize() to setup the provider api end-points urls
* Hybrid_Providers_{provider_name}::getUserProfile() to grab the user profile
@@ -19,11 +19,21 @@
*/
class Hybrid_Provider_Model_OAuth1 extends Hybrid_Provider_Model
{
public $request_tokens_raw = null; // request_tokens as recived from provider
public $access_tokens_raw = null; // access_tokens as recived from provider
/**
* request_tokens as received from provider
* @var object
*/
public $request_tokens_raw = null;
/**
* try to get the error message from provider api
* access_tokens as received from provider
* @var object
*/
public $access_tokens_raw = null;
/**
* Try to get the error message from provider api
* @param Numeric $code
*/
function errorMessageByStatus( $code = null ) {
$http_status_codes = ARRAY(
@@ -98,7 +108,7 @@ class Hybrid_Provider_Model_OAuth1 extends Hybrid_Provider_Model
{
$tokens = $this->api->requestToken( $this->endpoint );
// request tokens as recived from provider
// request tokens as received from provider
$this->request_tokens_raw = $tokens;
// check the last HTTP status code returned
@@ -134,7 +144,7 @@ class Hybrid_Provider_Model_OAuth1 extends Hybrid_Provider_Model
// request an access token
$tokens = $this->api->accessToken( $oauth_verifier );
// access tokens as recived from provider
// access tokens as received from provider
$this->access_tokens_raw = $tokens;
// check the last HTTP status code returned
@@ -147,11 +157,11 @@ class Hybrid_Provider_Model_OAuth1 extends Hybrid_Provider_Model
throw new Exception( "Authentication failed! {$this->providerId} returned an invalid access token.", 5 );
}
// we no more need to store requet tokens
// we no more need to store request tokens
$this->deleteToken( "request_token" );
$this->deleteToken( "request_token_secret" );
// sotre access_token for later user
// store access_token for later user
$this->token( "access_token" , $tokens['oauth_token'] );
$this->token( "access_token_secret" , $tokens['oauth_token_secret'] );

View File

@@ -1,15 +1,15 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* To implement an OAuth 2 based service provider, Hybrid_Provider_Model_OAuth2
* can be used to save the hassle of the authentication flow.
*
* Each class that inherit from Hybrid_Provider_Model_OAuth2 have to implemenent
* Each class that inherit from Hybrid_Provider_Model_OAuth2 have to implement
* at least 2 methods:
* Hybrid_Providers_{provider_name}::initialize() to setup the provider api end-points urls
* Hybrid_Providers_{provider_name}::getUserProfile() to grab the user profile
@@ -18,12 +18,16 @@
* Hybrid/thirdparty/OAuth/OAuth2Client.php
*/
class Hybrid_Provider_Model_OAuth2 extends Hybrid_Provider_Model
{
// default permissions
{
/**
* default permissions
* @var string
*/
public $scope = "";
/**
* try to get the error message from provider api
* Try to get the error message from provider api
* @param Numeric $code
*/
function errorMessageByStatus( $code = null ) {
$http_status_codes = ARRAY(
@@ -107,7 +111,7 @@ class Hybrid_Provider_Model_OAuth2 extends Hybrid_Provider_Model
throw new Exception( "Authentication failed! {$this->providerId} returned an error: $error", 5 );
}
// try to authenicate user
// try to authenticate user
$code = (array_key_exists('code',$_REQUEST))?$_REQUEST['code']:"";
try{

View File

@@ -1,14 +1,14 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* To implement an OpenID based service provider, Hybrid_Provider_Model_OpenID
* can be used to save the hassle of the authentication flow.
*
* can be used to save the hassle of the authentication flow.
*
* Each class that inherit from Hybrid_Provider_Model_OAuth2 have only to define
* the provider identifier : <code>public $openidIdentifier = ""; </code>
*
@@ -17,13 +17,16 @@
*/
class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
{
/* Openid provider identifier */
public $openidIdentifier = "";
/**
* Openid provider identifier
* @var string
*/
public $openidIdentifier = "";
// --------------------------------------------------------------------
/**
* adapter initializer
* adapter initializer
*/
function initialize()
{
@@ -32,18 +35,26 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
}
// include LightOpenID lib
require_once Hybrid_Auth::$config["path_libraries"] . "OpenID/LightOpenID.php";
require_once Hybrid_Auth::$config["path_libraries"] . "OpenID/LightOpenID.php";
// An error was occurring when proxy wasn't set. Not sure where proxy was meant to be set/initialized.
Hybrid_Auth::$config['proxy'] = isset(Hybrid_Auth::$config['proxy'])?Hybrid_Auth::$config['proxy']:'';
$this->api = new LightOpenID( parse_url( Hybrid_Auth::$config["base_url"], PHP_URL_HOST), Hybrid_Auth::$config["proxy"] );
$hostPort = parse_url( Hybrid_Auth::$config["base_url"], PHP_URL_PORT);
$hostUrl = parse_url( Hybrid_Auth::$config["base_url"], PHP_URL_HOST);
// Check for port on url
if($hostPort) {
$hostUrl .= ':'.$hostPort;
}
$this->api = new LightOpenID( $hostUrl, Hybrid_Auth::$config["proxy"] );
}
// --------------------------------------------------------------------
/**
* begin login step
* begin login step
*/
function loginBegin()
{
@@ -53,7 +64,7 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
$this->api->identity = $this->openidIdentifier;
$this->api->returnUrl = $this->endpoint;
$this->api->required = ARRAY(
$this->api->required = ARRAY(
'namePerson/first' ,
'namePerson/last' ,
'namePerson/friendly' ,
@@ -67,11 +78,11 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
'birthDate/birthYear' ,
'person/gender' ,
'pref/language' ,
'pref/language' ,
'contact/postalCode/home',
'contact/city/home' ,
'contact/country/home' ,
'contact/country/home' ,
'media/image/default' ,
);
@@ -83,24 +94,24 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
// --------------------------------------------------------------------
/**
* finish login step
* finish login step
*/
function loginFinish()
{
# if user don't garant acess of their data to your site, halt with an Exception
# if user don't grant access of their data to your site, halt with an Exception
if( $this->api->mode == 'cancel'){
throw new Exception( "Authentication failed! User has canceled authentication!", 5 );
}
# if something goes wrong
if( ! $this->api->validate() ){
throw new Exception( "Authentication failed. Invalid request recived!", 5 );
throw new Exception( "Authentication failed. Invalid request received!", 5 );
}
# fetch recived user data
# fetch received user data
$response = $this->api->getAttributes();
# sotre the user profile
# store the user profile
$this->user->profile->identifier = $this->api->identity;
$this->user->profile->firstName = (array_key_exists("namePerson/first",$response))?$response["namePerson/first"]:"";
@@ -108,25 +119,21 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
$this->user->profile->displayName = (array_key_exists("namePerson",$response))?$response["namePerson"]:"";
$this->user->profile->email = (array_key_exists("contact/email",$response))?$response["contact/email"]:"";
$this->user->profile->language = (array_key_exists("pref/language",$response))?$response["pref/language"]:"";
$this->user->profile->country = (array_key_exists("contact/country/home",$response))?$response["contact/country/home"]:"";
$this->user->profile->zip = (array_key_exists("contact/postalCode/home",$response))?$response["contact/postalCode/home"]:"";
$this->user->profile->gender = (array_key_exists("person/gender",$response))?$response["person/gender"]:"";
$this->user->profile->photoURL = (array_key_exists("media/image/default",$response))?$response["media/image/default"]:"";
$this->user->profile->country = (array_key_exists("contact/country/home",$response))?$response["contact/country/home"]:"";
$this->user->profile->zip = (array_key_exists("contact/postalCode/home",$response))?$response["contact/postalCode/home"]:"";
$this->user->profile->gender = (array_key_exists("person/gender",$response))?$response["person/gender"]:"";
$this->user->profile->photoURL = (array_key_exists("media/image/default",$response))?$response["media/image/default"]:"";
$this->user->profile->birthDay = (array_key_exists("birthDate/birthDay",$response))?$response["birthDate/birthDay"]:"";
$this->user->profile->birthMonth = (array_key_exists("birthDate/birthMonth",$response))?$response["birthDate/birthMonth"]:"";
$this->user->profile->birthYear = (array_key_exists("birthDate/birthDate",$response))?$response["birthDate/birthDate"]:"";
$this->user->profile->birthDay = (array_key_exists("birthDate/birthDay",$response))?$response["birthDate/birthDay"]:"";
$this->user->profile->birthMonth = (array_key_exists("birthDate/birthMonth",$response))?$response["birthDate/birthMonth"]:"";
$this->user->profile->birthYear = (array_key_exists("birthDate/birthDate",$response))?$response["birthDate/birthDate"]:"";
if( ! $this->user->profile->displayName ) {
$this->user->profile->displayName = trim( $this->user->profile->lastName . " " . $this->user->profile->firstName );
}
if( isset( $response['namePerson/friendly'] ) && ! empty( $response['namePerson/friendly'] ) && ! $this->user->profile->displayName ) {
$this->user->profile->displayName = (array_key_exists("namePerson/friendly",$response))?$response["namePerson/friendly"]:"" ;
if( isset( $response['namePerson/friendly'] ) && ! empty( $response['namePerson/friendly'] ) && ! $this->user->profile->displayName ) {
$this->user->profile->displayName = $response["namePerson/friendly"];
}
if( isset( $response['birthDate'] ) && ! empty( $response['birthDate'] ) && ! $this->user->profile->birthDay ) {
list( $birthday_year, $birthday_month, $birthday_day ) = (array_key_exists('birthDate',$response))?$response['birthDate']:"";
list( $birthday_year, $birthday_month, $birthday_day ) = $response['birthDate'];
$this->user->profile->birthDay = (int) $birthday_day;
$this->user->profile->birthMonth = (int) $birthday_month;
@@ -143,12 +150,12 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
if( $this->user->profile->gender == "m" ){
$this->user->profile->gender = "male";
}
}
// set user as logged in
$this->setUserConnected();
// with openid providers we get the user profile only once, so store it
// with openid providers we get the user profile only once, so store it
Hybrid_Auth::storage()->set( "hauth_session.{$this->providerId}.user", $this->user );
}
@@ -165,7 +172,7 @@ class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
// if not found
if ( ! is_object( $this->user ) ){
throw new Exception( "User profile request failed! User is not connected to {$this->providerId} or his session has expired.", 6 );
}
}
return $this->user->profile;
}

View File

@@ -14,8 +14,8 @@
*/
class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
{
// default permissions, and alot of them. You can change them from the configuration by setting the scope to what you want/need
public $scope = "email, user_about_me, user_birthday, user_hometown, user_website, read_stream, offline_access, publish_stream, read_friendlists";
// default permissions, and a lot of them. You can change them from the configuration by setting the scope to what you want/need
public $scope = "email, user_about_me, user_birthday, user_hometown, user_website, read_stream, publish_actions, read_friendlists";
/**
* IDp wrappers initializer
@@ -35,7 +35,8 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
BaseFacebook::$CURL_OPTS[CURLOPT_PROXY] = Hybrid_Auth::$config["proxy"];
}
$this->api = new Facebook( ARRAY( 'appId' => $this->config["keys"]["id"], 'secret' => $this->config["keys"]["secret"] ) );
$trustForwarded = isset( $this->config['trustForwarded'] ) ? (bool) $this->config['trustForwarded'] : false;
$this->api = new Facebook( ARRAY( 'appId' => $this->config["keys"]["id"], 'secret' => $this->config["keys"]["secret"], 'trustForwarded' => $trustForwarded ) );
if ( $this->token("access_token") ) {
$this->api->setAccessToken( $this->token("access_token") );
@@ -61,14 +62,29 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
function loginBegin()
{
$parameters = array("scope" => $this->scope, "redirect_uri" => $this->endpoint, "display" => "page");
$optionals = array("scope", "redirect_uri", "display");
$optionals = array("scope", "redirect_uri", "display", "auth_type");
foreach ($optionals as $parameter){
if( isset( $this->config[$parameter] ) && ! empty( $this->config[$parameter] ) ){
$parameters[$parameter] = $this->config[$parameter];
//If the auth_type parameter is used, we need to generate a nonce and include it as a parameter
if($parameter == "auth_type"){
$nonce = md5(uniqid(mt_rand(), true));
$parameters['auth_nonce'] = $nonce;
Hybrid_Auth::storage()->set('fb_auth_nonce', $nonce);
}
}
}
if( isset( $this->config[ 'force' ] ) && $this->config[ 'force' ] === true ){
$parameters[ 'auth_type' ] = 'reauthenticate';
$parameters[ 'auth_nonce' ] = md5( uniqid( mt_rand(), true ) );
Hybrid_Auth::storage()->set( 'fb_auth_nonce', $parameters[ 'auth_nonce' ] );
}
// get the login url
$url = $this->api->getLoginUrl( $parameters );
@@ -86,6 +102,35 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
throw new Exception( "Authentication failed! The user denied your request.", 5 );
}
// in case we are using iOS/Facebook reverse authentication
if(isset($_REQUEST['access_token'])){
$this->token("access_token", $_REQUEST['access_token'] );
$this->api->setAccessToken( $this->token("access_token") );
$this->api->setExtendedAccessToken();
$access_token = $this->api->getAccessToken();
if( $access_token ){
$this->token("access_token", $access_token );
$this->api->setAccessToken( $access_token );
}
$this->api->setAccessToken( $this->token("access_token") );
}
// if auth_type is used, then an auth_nonce is passed back, and we need to check it.
if(isset($_REQUEST['auth_nonce'])){
$nonce = Hybrid_Auth::storage()->get('fb_auth_nonce');
//Delete the nonce
Hybrid_Auth::storage()->delete('fb_auth_nonce');
if($_REQUEST['auth_nonce'] != $nonce){
throw new Exception( "Authentication failed! Invalid nonce used for reauthentication.", 5 );
}
}
// try to get the UID of the connected user from fb, should be > 0
if ( ! $this->api->getUser() ){
throw new Exception( "Authentication failed! {$this->providerId} returned an invalid user id.", 5 );
@@ -121,25 +166,36 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
throw new Exception( "User profile request failed! {$this->providerId} returned an error: $e", 6 );
}
// if the provider identifier is not recived, we assume the auth has failed
// if the provider identifier is not received, we assume the auth has failed
if ( ! isset( $data["id"] ) ){
throw new Exception( "User profile request failed! {$this->providerId} api returned an invalid response.", 6 );
}
# store the user profile.
$this->user->profile->identifier = (array_key_exists('id',$data))?$data['id']:"";
$this->user->profile->username = (array_key_exists('username',$data))?$data['username']:"";
$this->user->profile->displayName = (array_key_exists('name',$data))?$data['name']:"";
$this->user->profile->firstName = (array_key_exists('first_name',$data))?$data['first_name']:"";
$this->user->profile->lastName = (array_key_exists('last_name',$data))?$data['last_name']:"";
$this->user->profile->photoURL = "https://graph.facebook.com/" . $this->user->profile->identifier . "/picture?width=150&height=150";
$this->user->profile->coverInfoURL = "https://graph.facebook.com/" . $this->user->profile->identifier . "?fields=cover";
$this->user->profile->profileURL = (array_key_exists('link',$data))?$data['link']:"";
$this->user->profile->webSiteURL = (array_key_exists('website',$data))?$data['website']:"";
$this->user->profile->gender = (array_key_exists('gender',$data))?$data['gender']:"";
$this->user->profile->description = (array_key_exists('bio',$data))?$data['bio']:"";
$this->user->profile->language = (array_key_exists('locale',$data))?$data['locale']:"";
$this->user->profile->description = (array_key_exists('about',$data))?$data['about']:"";
$this->user->profile->email = (array_key_exists('email',$data))?$data['email']:"";
$this->user->profile->emailVerified = (array_key_exists('email',$data))?$data['email']:"";
$this->user->profile->region = (array_key_exists("hometown",$data)&&array_key_exists("name",$data['hometown']))?$data['hometown']["name"]:"";
if(!empty($this->user->profile->region )){
$regionArr = explode(',',$this->user->profile->region );
if(count($regionArr) > 1){
$this->user->profile->city = trim($regionArr[0]);
$this->user->profile->country = trim($regionArr[1]);
}
}
if( array_key_exists('birthday',$data) ) {
list($birthday_month, $birthday_day, $birthday_year) = explode( "/", $data['birthday'] );
@@ -151,30 +207,67 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
return $this->user->profile;
}
/**
* Attempt to retrieve the url to the cover image given the coverInfoURL
*
* @param string $coverInfoURL coverInfoURL variable
* @retval string url to the cover image OR blank string
*/
function getCoverURL($coverInfoURL)
{
try {
$headers = get_headers($coverInfoURL);
if(substr($headers[0], 9, 3) != "404") {
$coverOBJ = json_decode(file_get_contents($coverInfoURL));
if(array_key_exists('cover', $coverOBJ)) {
return $coverOBJ->cover->source;
}
}
} catch (Exception $e) { }
return "";
}
/**
* load the user contacts
*/
function getUserContacts()
{
try{
$response = $this->api->api('/me/friends');
}
catch( FacebookApiException $e ){
throw new Exception( "User contacts request failed! {$this->providerId} returned an error: $e" );
}
if( ! $response || ! count( $response["data"] ) ){
return ARRAY();
$apiCall = '?fields=link,name';
$returnedContacts = array();
$pagedList = false;
do {
try{
$response = $this->api->api('/me/friends' . $apiCall);
}
catch( FacebookApiException $e ){
throw new Exception( 'User contacts request failed! {$this->providerId} returned an error: $e' );
}
// Prepare the next call if paging links have been returned
if (array_key_exists('paging', $response) && array_key_exists('next', $response['paging'])) {
$pagedList = true;
$next_page = explode('friends', $response['paging']['next']);
$apiCall = $next_page[1];
}
else{
$pagedList = false;
}
// Add the new page contacts
$returnedContacts = array_merge($returnedContacts, $response['data']);
}
while ($pagedList == true);
$contacts = ARRAY();
foreach( $response["data"] as $item ){
foreach( $returnedContacts as $item ){
$uc = new Hybrid_User_Contact();
$uc->identifier = (array_key_exists("id",$item))?$item["id"]:"";
$uc->displayName = (array_key_exists("name",$item))?$item["name"]:"";
$uc->profileURL = "https://www.facebook.com/profile.php?id=" . $uc->identifier;
$uc->profileURL = (array_key_exists("link",$item))?$item["link"]:"https://www.facebook.com/profile.php?id=" . $uc->identifier;
$uc->photoURL = "https://graph.facebook.com/" . $uc->identifier . "/picture?width=150&height=150";
$contacts[] = $uc;
@@ -183,27 +276,96 @@ class Hybrid_Providers_Facebook extends Hybrid_Provider_Model
return $contacts;
}
/**
* update user status
*
* @param string $pageid (optional) User page id
*/
function setUserStatus( $status, $pageid = null )
{
if( !is_array( $status ) ){
$status = array( 'message' => $status );
}
if( is_null( $pageid ) ){
$pageid = 'me';
// if post on page, get access_token page
}else{
$access_token = null;
foreach( $this->getUserPages( true ) as $p ){
if( isset( $p[ 'id' ] ) && intval( $p['id'] ) == intval( $pageid ) ){
$access_token = $p[ 'access_token' ];
break;
}
}
if( is_null( $access_token ) ){
throw new Exception( "Update user page failed, page not found or not writable!" );
}
$status[ 'access_token' ] = $access_token;
}
try{
$response = $this->api->api( '/' . $pageid . '/feed', 'post', $status );
}
catch( FacebookApiException $e ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error: $e" );
}
return $response;
}
/**
* update user status
* get user status
*/
function setUserStatus( $status )
{
$parameters = array();
if( is_array( $status ) ){
$parameters = $status;
}
else{
$parameters["message"] = $status;
}
try{
$response = $this->api->api( "/me/feed", "post", $parameters );
}
function getUserStatus( $postid )
{
try{
$postinfo = $this->api->api( "/" . $postid );
}
catch( FacebookApiException $e ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error: $e" );
throw new Exception( "Cannot retrieve user status! {$this->providerId} returned an error: $e" );
}
}
return $postinfo;
}
/**
* get user pages
*/
function getUserPages( $writableonly = false )
{
if( ( isset( $this->config[ 'scope' ] ) && strpos( $this->config[ 'scope' ], 'manage_pages' ) === false ) || ( !isset( $this->config[ 'scope' ] ) && strpos( $this->scope, 'manage_pages' ) === false ) )
throw new Exception( "User status requires manage_page permission!" );
try{
$pages = $this->api->api( "/me/accounts", 'get' );
}
catch( FacebookApiException $e ){
throw new Exception( "Cannot retrieve user pages! {$this->providerId} returned an error: $e" );
}
if( !isset( $pages[ 'data' ] ) ){
return array();
}
if( !$writableonly ){
return $pages[ 'data' ];
}
$wrpages = array();
foreach( $pages[ 'data' ] as $p ){
if( isset( $p[ 'perms' ] ) && in_array( 'CREATE_CONTENT', $p[ 'perms' ] ) ){
$wrpages[] = $p;
}
}
return $wrpages;
}
/**
* load the user latest activity

View File

@@ -10,6 +10,21 @@
*
* http://hybridauth.sourceforge.net/userguide/IDProvider_info_Foursquare.html
*/
/**
* Howto define profile photo size:
* - add params key into hybridauth config
* ...
* "Foursquare" => array (
* "enabled" => true,
* "keys" => ...,
* "params" => array( "photo_size" => "16x16" )
* ),
* ...
* - list of valid photo_size values is described here https://developer.foursquare.com/docs/responses/photo.html
* - default photo_size is 100x100
*/
class Hybrid_Providers_Foursquare extends Hybrid_Provider_Model_OAuth2
{
/**
@@ -32,7 +47,7 @@ class Hybrid_Providers_Foursquare extends Hybrid_Provider_Model_OAuth2
*/
function getUserProfile()
{
$data = $this->api->api( "users/self" );
$data = $this->api->api( "users/self", "GET", array( "v" => "20120610" ) );
if ( ! isset( $data->response->user->id ) ){
throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 );
@@ -40,11 +55,14 @@ class Hybrid_Providers_Foursquare extends Hybrid_Provider_Model_OAuth2
$data = $data->response->user;
// get profile photo size from config
$photoSize = ((isset($this->config["params"]["photo_size"]))?($this->config["params"]["photo_size"]):("100x100"));
$this->user->profile->identifier = $data->id;
$this->user->profile->firstName = $data->firstName;
$this->user->profile->lastName = $data->lastName;
$this->user->profile->displayName = trim( $this->user->profile->firstName . " " . $this->user->profile->lastName );
$this->user->profile->photoURL = $data->photo;
$this->user->profile->photoURL = $data->photo->prefix.$photoSize.$data->photo->suffix;
$this->user->profile->profileURL = "https://www.foursquare.com/user/" . $data->id;
$this->user->profile->gender = $data->gender;
$this->user->profile->city = $data->homeCity;

View File

@@ -2,7 +2,7 @@
/*!
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -12,8 +12,11 @@
*/
class Hybrid_Providers_Google extends Hybrid_Provider_Model_OAuth2
{
// > more infos on google APIs: http://developer.google.com (official site)
// or here: http://discovery-check.appspot.com/ (unofficial but up to date)
// default permissions
public $scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.google.com/m8/feeds/";
public $scope = "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read https://www.google.com/m8/feeds/";
/**
* IDp wrappers initializer
@@ -25,7 +28,13 @@ class Hybrid_Providers_Google extends Hybrid_Provider_Model_OAuth2
// Provider api end-points
$this->api->authorize_url = "https://accounts.google.com/o/oauth2/auth";
$this->api->token_url = "https://accounts.google.com/o/oauth2/token";
$this->api->token_info_url = "https://www.googleapis.com/oauth2/v1/tokeninfo";
$this->api->token_info_url = "https://www.googleapis.com/oauth2/v2/tokeninfo";
// Override the redirect uri when it's set in the config parameters. This way we prevent
// redirect uri mismatches when authenticating with Google.
if( isset( $this->config['redirect_uri'] ) && ! empty( $this->config['redirect_uri'] ) ){
$this->api->redirect_uri = $this->config['redirect_uri'];
}
}
/**
@@ -34,14 +43,21 @@ class Hybrid_Providers_Google extends Hybrid_Provider_Model_OAuth2
function loginBegin()
{
$parameters = array("scope" => $this->scope, "access_type" => "offline");
$optionals = array("scope", "access_type", "redirect_uri", "approval_prompt", "hd");
$optionals = array("scope", "access_type", "redirect_uri", "approval_prompt", "hd", "state");
foreach ($optionals as $parameter){
if( isset( $this->config[$parameter] ) && ! empty( $this->config[$parameter] ) ){
$parameters[$parameter] = $this->config[$parameter];
}
if( isset( $this->config["scope"] ) && ! empty( $this->config["scope"] ) ){
$this->scope = $this->config["scope"];
}
}
if( isset( $this->config[ 'force' ] ) && $this->config[ 'force' ] === true ){
$parameters[ 'approval_prompt' ] = 'force';
}
Hybrid_Auth::redirect( $this->api->authorizeUrl( $parameters ) );
}
@@ -54,36 +70,104 @@ class Hybrid_Providers_Google extends Hybrid_Provider_Model_OAuth2
$this->refreshToken();
// ask google api for user infos
$response = $this->api->api( "https://www.googleapis.com/oauth2/v1/userinfo" );
if (strpos($this->scope, '/auth/plus.profile.emails.read') !== false) {
$verified = $this->api->api( "https://www.googleapis.com/plus/v1/people/me" );
if ( ! isset( $verified->id ) || isset( $verified->error ) )
$verified = new stdClass();
} else {
$verified = $this->api->api( "https://www.googleapis.com/plus/v1/people/me/openIdConnect" );
if ( ! isset( $verified->sub ) || isset( $verified->error ) )
$verified = new stdClass();
}
$response = $this->api->api( "https://www.googleapis.com/plus/v1/people/me" );
if ( ! isset( $response->id ) || isset( $response->error ) ){
throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 );
}
$this->user->profile->identifier = (property_exists($response,'id'))?$response->id:"";
$this->user->profile->firstName = (property_exists($response,'given_name'))?$response->given_name:"";
$this->user->profile->lastName = (property_exists($response,'family_name'))?$response->family_name:"";
$this->user->profile->displayName = (property_exists($response,'name'))?$response->name:"";
$this->user->profile->photoURL = (property_exists($response,'picture'))?$response->picture:"";
$this->user->profile->profileURL = "https://profiles.google.com/" . $this->user->profile->identifier;
$this->user->profile->identifier = (property_exists($verified,'id'))?$verified->id:((property_exists($response,'id'))?$response->id:"");
$this->user->profile->firstName = (property_exists($response,'name'))?$response->name->givenName:"";
$this->user->profile->lastName = (property_exists($response,'name'))?$response->name->familyName:"";
$this->user->profile->displayName = (property_exists($response,'displayName'))?$response->displayName:"";
$this->user->profile->photoURL = (property_exists($response,'image'))?((property_exists($response->image,'url'))?substr($response->image->url, 0, -2)."200":''):'';
$this->user->profile->profileURL = (property_exists($response,'url'))?$response->url:"";
$this->user->profile->description = (property_exists($response,'aboutMe'))?$response->aboutMe:"";
$this->user->profile->gender = (property_exists($response,'gender'))?$response->gender:"";
$this->user->profile->email = (property_exists($response,'email'))?$response->email:"";
$this->user->profile->emailVerified = (property_exists($response,'email'))?$response->email:"";
$this->user->profile->language = (property_exists($response,'locale'))?$response->locale:"";
$this->user->profile->language = (property_exists($response,'locale'))?$response->locale:((property_exists($verified,'locale'))?$verified->locale:"");
$this->user->profile->email = (property_exists($response,'email'))?$response->email:((property_exists($verified,'email'))?$verified->email:"");
$this->user->profile->emailVerified = (property_exists($verified,'email'))?$verified->email:"";
if (property_exists($response, 'emails')) {
if (count($response->emails) == 1) {
$this->user->profile->email = $response->emails[0]->value;
} else {
foreach ($response->emails as $email) {
if ($email->type == 'account') {
$this->user->profile->email = $email->value;
break;
}
}
}
}
$this->user->profile->phone = (property_exists($response,'phone'))?$response->phone:"";
$this->user->profile->country = (property_exists($response,'country'))?$response->country:"";
$this->user->profile->region = (property_exists($response,'region'))?$response->region:"";
$this->user->profile->zip = (property_exists($response,'zip'))?$response->zip:"";
if( property_exists($response,'placesLived') ){
$this->user->profile->city = "";
$this->user->profile->address = "";
foreach($response->placesLived as $c){
if(property_exists($c,'primary')){
if($c->primary == true){
$this->user->profile->address = $c->value;
$this->user->profile->city = $c->value;
break;
}
}else{
if(property_exists($c,'value')){
$this->user->profile->address = $c->value;
$this->user->profile->city = $c->value;
}
}
}
}
// google API returns multiple urls, but a "website" only if it is verified
// see http://support.google.com/plus/answer/1713826?hl=en
if( property_exists($response,'urls') ){
foreach($response->urls as $u){
if(property_exists($u, 'primary') && $u->primary == true) $this->user->profile->webSiteURL = $u->value;
}
} else {
$this->user->profile->webSiteURL = '';
}
// google API returns age ranges or min. age only (with plus.login scope)
if( property_exists($response,'ageRange') ){
if( property_exists($response->ageRange,'min') && property_exists($response->ageRange,'max') ){
$this->user->profile->age = $response->ageRange->min.' - '.$response->ageRange->max;
} else {
$this->user->profile->age = '> '.$response->ageRange->min;
}
} else {
$this->user->profile->age = '';
}
// google API returns birthdays only if a user set 'show in my account'
if( property_exists($response,'birthday') ){
list($birthday_year, $birthday_month, $birthday_day) = explode( '-', $response->birthday );
$this->user->profile->birthDay = (int) $birthday_day;
$this->user->profile->birthMonth = (int) $birthday_month;
$this->user->profile->birthYear = (int) $birthday_year;
} else {
$this->user->profile->birthDay=0;$this->user->profile->birthMonth=0;$this->user->profile->birthYear=0;
}
return $this->user->profile;
}
/**
* load the user (Gmail) contacts
* load the user (Gmail and google plus) contacts
* ..toComplete
*/
function getUserContacts()
@@ -91,29 +175,106 @@ class Hybrid_Providers_Google extends Hybrid_Provider_Model_OAuth2
// refresh tokens if needed
$this->refreshToken();
$contacts = array();
if( ! isset( $this->config['contacts_param'] ) ){
$this->config['contacts_param'] = array( "max-results" => 500 );
}
// Google Gmail and Android contacts
if (strpos($this->scope, '/m8/feeds/') !== false) {
$response = $this->api->api( "https://www.google.com/m8/feeds/contacts/default/full?"
. http_build_query( array_merge( array('alt' => 'json', 'v' => '3.0'), $this->config['contacts_param'] ) ) );
if( ! $response ){
return ARRAY();
}
$response = $this->api->api( "https://www.google.com/m8/feeds/contacts/default/full?"
. http_build_query( array_merge( array('alt' => 'json'), $this->config['contacts_param'] ) ) );
if (isset($response->feed->entry)) {
foreach( $response->feed->entry as $idx => $entry ){
$uc = new Hybrid_User_Contact();
$uc->email = isset($entry->{'gd$email'}[0]->address) ? (string) $entry->{'gd$email'}[0]->address : '';
$uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : '';
$uc->identifier = ($uc->email!='')?$uc->email:'';
$uc->description = '';
if( property_exists($entry,'link') ){
/**
* sign links with access_token
*/
if(is_array($entry->link)){
foreach($entry->link as $l){
if( property_exists($l,'gd$etag') && $l->type=="image/*"){
$uc->photoURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token));
} else if($l->type=="self"){
$uc->profileURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token));
}
}
}
} else {
$uc->profileURL = '';
}
if( property_exists($response,'website') ){
if(is_array($response->website)){
foreach($response->website as $w){
if($w->primary == true) $uc->webSiteURL = $w->value;
}
} else {
$uc->webSiteURL = $response->website->value;
}
} else {
$uc->webSiteURL = '';
}
if( ! $response ){
return ARRAY();
$contacts[] = $uc;
}
}
}
$contacts = ARRAY();
foreach( $response->feed->entry as $idx => $entry ){
$uc = new Hybrid_User_Contact();
$uc->email = isset($entry->{'gd$email'}[0]->address) ? (string) $entry->{'gd$email'}[0]->address : '';
$uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : '';
$uc->identifier = $uc->email;
$contacts[] = $uc;
}
// Google social contacts
if (strpos($this->scope, '/auth/plus.login') !== false) {
$response = $this->api->api( "https://www.googleapis.com/plus/v1/people/me/people/visible?"
. http_build_query( $this->config['contacts_param'] ) );
if( ! $response ){
return ARRAY();
}
foreach( $response->items as $idx => $item ){
$uc = new Hybrid_User_Contact();
$uc->email = (property_exists($item,'email'))?$item->email:'';
$uc->displayName = (property_exists($item,'displayName'))?$item->displayName:'';
$uc->identifier = (property_exists($item,'id'))?$item->id:'';
$uc->description = (property_exists($item,'objectType'))?$item->objectType:'';
$uc->photoURL = (property_exists($item,'image'))?((property_exists($item->image,'url'))?$item->image->url:''):'';
$uc->profileURL = (property_exists($item,'url'))?$item->url:'';
$uc->webSiteURL = '';
$contacts[] = $uc;
}
}
return $contacts;
}
/**
* Add to the $url new parameters
* @param string $url
* @param array $params
* @return string
*/
function addUrlParam($url, array $params)
{
$query = parse_url($url, PHP_URL_QUERY);
// Returns the URL string with new parameters
if( $query ) {
$url .= '&' . http_build_query( $params );
} else {
$url .= '?' . http_build_query( $params );
}
return $url;
}
}

View File

@@ -22,8 +22,9 @@ class Hybrid_Providers_LinkedIn extends Hybrid_Provider_Model
if ( ! $this->config["keys"]["key"] || ! $this->config["keys"]["secret"] ){
throw new Exception( "Your application key and secret are required in order to connect to {$this->providerId}.", 4 );
}
require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth.php";
if ( ! class_exists('OAuthConsumer') ) {
require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth.php";
}
require_once Hybrid_Auth::$config["path_libraries"] . "LinkedIn/LinkedIn.php";
$this->api = new LinkedIn( array( 'appKey' => $this->config["keys"]["key"], 'appSecret' => $this->config["keys"]["secret"], 'callbackUrl' => $this->endpoint ) );
@@ -200,6 +201,8 @@ class Hybrid_Providers_LinkedIn extends Hybrid_Provider_Model
{
throw new Exception( "Update user status update failed! {$this->providerId} returned an error." );
}
return $response;
}
/**

View File

@@ -20,7 +20,7 @@
class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2
{
// default permissions
public $scope = "wl.basic wl.emails wl.signin wl.share wl.birthday";
public $scope = "wl.basic wl.contacts_emails wl.emails wl.signin wl.share wl.birthday";
/**
@@ -46,7 +46,7 @@ class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2
$data = $this->api->get( "me" );
if ( ! isset( $data->id ) ){
throw new Exception( "User profile request failed! {$this->providerId} returned an invalide response.", 6 );
throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 );
}
$this->user->profile->identifier = (property_exists($data,'id'))?$data->id:"";
@@ -85,7 +85,7 @@ class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2
throw new Exception( 'User contacts request failed! ' . $this->providerId . ' returned an error: ' . $this->errorMessageByStatus( $this->api->http_code ) );
}
if ( ! $response->data && ( $response->error != 0 ) )
if ( !isset($response->data) || ( isset($response->errcode) && $response->errcode != 0 ) )
{
return array();
}
@@ -97,7 +97,7 @@ class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2
$uc->identifier = (property_exists($item,'id'))?$item->id:"";
$uc->displayName = (property_exists($item,'name'))?$item->name:"";
$uc->email = (property_exists($item,'emails'))?$item->emails->preferred:"";
$contacts[] = $uc;
}

View File

@@ -39,25 +39,37 @@ class Hybrid_Providers_Twitter extends Hybrid_Provider_Model_OAuth1
*/
function loginBegin()
{
// Initiate the Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth
if (isset($_REQUEST['reverse_auth']) && ($_REQUEST['reverse_auth'] == 'yes')){
$stage1 = $this->api->signedRequest( $this->api->request_token_url, 'POST', array( 'x_auth_mode' => 'reverse_auth' ) );
if ( $this->api->http_code != 200 ){
throw new Exception( "Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ), 5 );
}
$responseObj = array( 'x_reverse_auth_parameters' => $stage1, 'x_reverse_auth_target' => $this->config["keys"]["key"] );
$response = json_encode($responseObj);
header( "Content-Type: application/json", true, 200 ) ;
echo $response;
die();
}
$tokens = $this->api->requestToken( $this->endpoint );
// request tokens as recived from provider
// request tokens as received from provider
$this->request_tokens_raw = $tokens;
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Authentification failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ), 5 );
throw new Exception( "Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ), 5 );
}
if ( ! isset( $tokens["oauth_token"] ) ){
throw new Exception( "Authentification failed! {$this->providerId} returned an invalid oauth token.", 5 );
throw new Exception( "Authentication failed! {$this->providerId} returned an invalid oauth token.", 5 );
}
$this->token( "request_token" , $tokens["oauth_token"] );
$this->token( "request_token_secret", $tokens["oauth_token_secret"] );
// redirect the user to the provider authentication url with force_login
if ( isset( $this->config['force_login'] ) && $this->config['force_login'] ){
if ( ( isset( $this->config['force_login'] ) && $this->config['force_login'] ) || ( isset( $this->config[ 'force' ] ) && $this->config[ 'force' ] === true ) ){
Hybrid_Auth::redirect( $this->api->authorizeUrl( $tokens, array( 'force_login' => true ) ) );
}
@@ -65,6 +77,37 @@ class Hybrid_Providers_Twitter extends Hybrid_Provider_Model_OAuth1
Hybrid_Auth::redirect( $this->api->authorizeUrl( $tokens ) );
}
/**
* finish login step
*/
function loginFinish()
{
// in case we are completing a Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth
if(isset($_REQUEST['oauth_token_secret'])){
$tokens = $_REQUEST;
$this->access_tokens_raw = $tokens;
// we should have an access_token unless something has gone wrong
if ( ! isset( $tokens["oauth_token"] ) ){
throw new Exception( "Authentication failed! {$this->providerId} returned an invalid access token.", 5 );
}
// Get rid of tokens we don't need
$this->deleteToken( "request_token" );
$this->deleteToken( "request_token_secret" );
// Store access_token and secret for later use
$this->token( "access_token" , $tokens['oauth_token'] );
$this->token( "access_token_secret" , $tokens['oauth_token_secret'] );
// set user as logged in to the current provider
$this->setUserConnected();
return;
}
parent::loginFinish();
}
/**
* load the user profile from the IDp api client
*/
@@ -86,7 +129,7 @@ class Hybrid_Providers_Twitter extends Hybrid_Provider_Model_OAuth1
$this->user->profile->displayName = (property_exists($response,'screen_name'))?$response->screen_name:"";
$this->user->profile->description = (property_exists($response,'description'))?$response->description:"";
$this->user->profile->firstName = (property_exists($response,'name'))?$response->name:"";
$this->user->profile->photoURL = (property_exists($response,'profile_image_url'))?$response->profile_image_url:"";
$this->user->profile->photoURL = (property_exists($response,'profile_image_url'))?(str_replace('_normal', '', $response->profile_image_url)):"";
$this->user->profile->profileURL = (property_exists($response,'screen_name'))?("http://twitter.com/".$response->screen_name):"";
$this->user->profile->webSiteURL = (property_exists($response,'url'))?$response->url:"";
$this->user->profile->region = (property_exists($response,'location'))?$response->location:"";
@@ -143,19 +186,42 @@ class Hybrid_Providers_Twitter extends Hybrid_Provider_Model_OAuth1
return $contacts;
}
/**
* update user status
*/
function setUserStatus( $status )
{
$parameters = array( 'status' => $status );
$response = $this->api->post( 'statuses/update.json', $parameters );
/**
* update user status
*/
function setUserStatus( $status )
{
if( is_array( $status ) && isset( $status[ 'message' ] ) && isset( $status[ 'picture' ] ) ){
$response = $this->api->post( 'statuses/update_with_media.json', array( 'status' => $status[ 'message' ], 'media[]' => file_get_contents( $status[ 'picture' ] ) ), null, null, true );
}else{
$response = $this->api->post( 'statuses/update.json', array( 'status' => $status ) );
}
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
return $response;
}
/**
* get user status
*/
function getUserStatus( $tweetid )
{
$info = $this->api->get( 'statuses/show.json?id=' . $tweetid . '&include_entities=true' );
// check the last HTTP status code returned
if ( $this->api->http_code != 200 || !isset( $info->id ) ){
throw new Exception( "Cannot retrieve user status! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
return $info;
}
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
}
/**
* load the user latest activity

View File

@@ -24,7 +24,7 @@ class Hybrid_Providers_Yahoo extends Hybrid_Provider_Model_OAuth1
parent::initialize();
// Provider api end-points
$this->api->api_base_url = 'http://social.yahooapis.com/v1/';
$this->api->api_base_url = 'https://social.yahooapis.com/v1/';
$this->api->authorize_url = 'https://api.login.yahoo.com/oauth/v2/request_auth';
$this->api->request_token_url = 'https://api.login.yahoo.com/oauth/v2/get_request_token';
$this->api->access_token_url = 'https://api.login.yahoo.com/oauth/v2/get_token';
@@ -101,7 +101,7 @@ class Hybrid_Providers_Yahoo extends Hybrid_Provider_Model_OAuth1
throw new Exception( 'User contacts request failed! ' . $this->providerId . ' returned an error: ' . $this->errorMessageByStatus( $this->api->http_code ) );
}
if ( !$response->contacts->contact && ( $response->errcode != 0 ) )
if ( !isset($response->contacts) || !isset($response->contacts->contact) || ( isset($response->errcode) && $response->errcode != 0 ) )
{
return array();
}
@@ -218,6 +218,11 @@ class Hybrid_Providers_Yahoo extends Hybrid_Provider_Model_OAuth1
function selectEmail( $v )
{
$s = $this->select($v, 'email');
if(empty($s)){
$s = $this->select($v, 'yahooid');
if(!empty($s) && isset($s->value) && strpos($s->value,"@")===FALSE)
$s->value .= "@yahoo.com";
}
return ($s)?$s->value:"";
}

View File

@@ -1,15 +1,20 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
require_once realpath( dirname( __FILE__ ) ) . "/StorageInterface.php";
/**
* HybridAuth storage manager
*/
class Hybrid_Storage
class Hybrid_Storage implements Hybrid_Storage_Interface
{
/**
* Constructor
*/
function __construct()
{
if ( ! session_id() ){
@@ -21,8 +26,13 @@ class Hybrid_Storage
$this->config( "php_session_id", session_id() );
$this->config( "version", Hybrid_Auth::$version );
}
public function config($key, $value=null)
/**
* Config
* @param String $key
* @param String $value
*/
public function config($key, $value = null)
{
$key = strtolower( $key );
@@ -35,7 +45,11 @@ class Hybrid_Storage
return NULL;
}
/**
* Get a key
* @param String $key
*/
public function get($key)
{
$key = strtolower( $key );
@@ -46,19 +60,31 @@ class Hybrid_Storage
return NULL;
}
/**
* GEt a set of key and value
* @param String $key
* @param String $value
*/
public function set( $key, $value )
{
$key = strtolower( $key );
$key = strtolower( $key );
$_SESSION["HA::STORE"][$key] = serialize( $value );
$_SESSION["HA::STORE"][$key] = serialize( $value );
}
/**
* Clear session storage
*/
function clear()
{
$_SESSION["HA::STORE"] = ARRAY();
}
}
/**
* Delete a specific key
* @param String $key
*/
function delete($key)
{
$key = strtolower( $key );
@@ -69,7 +95,11 @@ class Hybrid_Storage
$_SESSION["HA::STORE"] = $f;
}
}
/**
* Delete a set
* @param String $key
*/
function deleteMatch($key)
{
$key = strtolower( $key );
@@ -85,7 +115,11 @@ class Hybrid_Storage
}
}
/**
* Get the storage session data into an array
* @return Array
*/
function getSessionData()
{
if( isset( $_SESSION["HA::STORE"] ) ){
@@ -94,7 +128,11 @@ class Hybrid_Storage
return NULL;
}
/**
* Restore the storage back into session from an array
* @param Array $sessiondata
*/
function restoreSessionData( $sessiondata = NULL )
{
$_SESSION["HA::STORE"] = unserialize( $sessiondata );

View File

@@ -0,0 +1,28 @@
<?php
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* HybridAuth storage manager interface
*/
interface Hybrid_Storage_Interface
{
public function config($key, $value);
public function get($key);
public function set( $key, $value );
function clear();
function delete($key);
function deleteMatch($key);
function getSessionData();
function restoreSessionData( $sessiondata);
}

View File

@@ -1,26 +1,35 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
* The Hybrid_User class represents the current loggedin user
* The Hybrid_User class represents the current logged in user
*/
class Hybrid_User
{
/* The ID (name) of the connected provider */
/**
* The ID (name) of the connected provider
* @var Numeric/String
*/
public $providerId = NULL;
/* timestamp connection to the provider */
/**
* timestamp connection to the provider
* @var timestamp
*/
public $timestamp = NULL;
/* user profile, containts the list of fields available in the normalized user profile structure used by HybridAuth. */
/**
* User profile, contains the list of fields available in the normalized user profile structure used by HybridAuth.
* @var object
*/
public $profile = NULL;
/**
* inisialize the user object,
* Initialize the user object.
*/
function __construct()
{

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -14,18 +14,33 @@
*/
class Hybrid_User_Activity
{
/* activity id on the provider side, usually given as integer */
/**
* activity id on the provider side, usually given as integer
* @var Numeric/String
*/
public $id = NULL;
/* activity date of creation */
/**
* activity date of creation
* @var timestamp
*/
public $date = NULL;
/* activity content as a string */
/**
* activity content as a string
* @var String
*/
public $text = NULL;
/* user who created the activity */
/**
* user who created the activity
* @var object
*/
public $user = NULL;
/**
* Constructor
*/
public function __construct()
{
$this->user = new stdClass();

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -14,24 +14,45 @@
*/
class Hybrid_User_Contact
{
/* The Unique contact user ID */
/**
* The Unique contact user ID
* @var Numeric
*/
public $identifier = NULL;
/* User website, blog, web page */
/**
* User website, blog, web page
* @var String
*/
public $webSiteURL = NULL;
/* URL link to profile page on the IDp web site */
/**
* URL link to profile page on the IDp web site
* @var String
*/
public $profileURL = NULL;
/* URL link to user photo or avatar */
/**
* URL link to user photo or avatar
* @var String
*/
public $photoURL = NULL;
/* User dispalyName provided by the IDp or a concatenation of first and last name */
public $displayName = NULL;
/**
* User displayName provided by the IDp or a concatenation of first and last name
* @var String
*/
public $displayName = NULL;
/* A short about_me */
/**
* A short about_me
* @var String
*/
public $description = NULL;
/* User email. Not all of IDp garant access to the user email */
public $email = NULL;
/**
* User email. Not all of IDp grant access to the user email
* @var String
*/
public $email = NULL;
}

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
/**
@@ -16,69 +16,135 @@
*/
class Hybrid_User_Profile
{
/* The Unique user's ID on the connected provider */
public $identifier = NULL;
/**
* The Unique user's ID on the connected provider
* @var Numeric
*/
public $identifier = NULL;
/* User website, blog, web page */
public $webSiteURL = NULL;
/**
* User website, blog, web page
* @var String
*/
public $webSiteURL = NULL;
/* URL link to profile page on the IDp web site */
public $profileURL = NULL;
/**
* URL link to profile page on the IDp web site
* @var String
*/
public $profileURL = NULL;
/* URL link to user photo or avatar */
public $photoURL = NULL;
/**
* URL link to user photo or avatar
* @var String
*/
public $photoURL = NULL;
/* User dispalyName provided by the IDp or a concatenation of first and last name. */
public $displayName = NULL;
/**
* User displayName provided by the IDp or a concatenation of first and last name.
* @var String
*/
public $displayName = NULL;
/* A short about_me */
public $description = NULL;
/**
* A short about_me
* @var String
*/
public $description = NULL;
/* User's first name */
public $firstName = NULL;
/**
* User's first name
* @var String
*/
public $firstName = NULL;
/* User's last name */
public $lastName = NULL;
/**
* User's last name
* @var String
*/
public $lastName = NULL;
/* male or female */
public $gender = NULL;
/**
* male or female
* @var String
*/
public $gender = NULL;
/* language */
public $language = NULL;
/**
* Language
* @var String
*/
public $language = NULL;
/* User age, we dont calculate it. we return it as is if the IDp provide it. */
public $age = NULL;
/**
* User age, we don't calculate it. we return it as is if the IDp provide it.
* @var Numeric
*/
public $age = NULL;
/* User birth Day */
/**
* User birth Day
* @var Numeric
*/
public $birthDay = NULL;
/* User birth Month */
/**
* User birth Month
* @var Numeric/String
*/
public $birthMonth = NULL;
/* User birth Year */
/**
* User birth Year
* @var Numeric
*/
public $birthYear = NULL;
/* User email. Note: not all of IDp garant access to the user email */
/**
* User email. Note: not all of IDp grant access to the user email
* @var String
*/
public $email = NULL;
/* Verified user email. Note: not all of IDp garant access to verified user email */
public $emailVerified = NULL;
/**
* Verified user email. Note: not all of IDp grant access to verified user email
* @var String
*/
public $emailVerified = NULL;
/* phone number */
public $phone = NULL;
/**
* Phone number
* @var String
*/
public $phone = NULL;
/* complete user address */
public $address = NULL;
/**
* Complete user address
* @var String
*/
public $address = NULL;
/* user country */
public $country = NULL;
/**
* User country
* @var String
*/
public $country = NULL;
/* region */
public $region = NULL;
/**
* Region
* @var String
*/
public $region = NULL;
/** city */
public $city = NULL;
/**
* City
* @var String
*/
public $city = NULL;
/* Postal code */
public $zip = NULL;
/**
* Postal code
* @var String
*/
public $zip = NULL;
}

View File

@@ -31,6 +31,8 @@ class FacebookApiException extends Exception
{
/**
* The result from the API server that represents the exception information.
*
* @var mixed
*/
protected $result;
@@ -42,7 +44,10 @@ class FacebookApiException extends Exception
public function __construct($result) {
$this->result = $result;
$code = isset($result['error_code']) ? $result['error_code'] : 0;
$code = 0;
if (isset($result['error_code']) && is_int($result['error_code'])) {
$code = $result['error_code'];
}
if (isset($result['error_description'])) {
// OAuth 2.0 Draft 10 style
@@ -120,7 +125,7 @@ abstract class BaseFacebook
/**
* Version.
*/
const VERSION = '3.2.2';
const VERSION = '3.2.3';
/**
* Signed Request Algorithm.
@@ -129,6 +134,8 @@ abstract class BaseFacebook
/**
* Default options for curl.
*
* @var array
*/
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
@@ -140,6 +147,8 @@ abstract class BaseFacebook
/**
* List of query parameters that get automatically dropped when rebuilding
* the current URL.
*
* @var array
*/
protected static $DROP_QUERY_PARAMS = array(
'code',
@@ -149,6 +158,8 @@ abstract class BaseFacebook
/**
* Maps aliases to Facebook domains.
*
* @var array
*/
public static $DOMAIN_MAP = array(
'api' => 'https://api.facebook.com/',
@@ -182,11 +193,15 @@ abstract class BaseFacebook
/**
* The data from the signed_request token.
*
* @var string
*/
protected $signedRequest;
/**
* A CSRF state variable to assist in the defense against CSRF attacks.
*
* @var string
*/
protected $state;
@@ -212,6 +227,13 @@ abstract class BaseFacebook
*/
protected $trustForwarded = false;
/**
* Indicates if signed_request is allowed in query parameters.
*
* @var boolean
*/
protected $allowSignedRequest = true;
/**
* Initialize a Facebook Application.
*
@@ -219,6 +241,9 @@ abstract class BaseFacebook
* - appId: the application ID
* - secret: the application secret
* - fileUpload: (optional) boolean indicating if file uploads are enabled
* - allowSignedRequest: (optional) boolean indicating if signed_request is
* allowed in query parameters or POST body. Should be
* false for non-canvas apps. Defaults to true.
*
* @param array $config The application configuration
*/
@@ -231,6 +256,10 @@ abstract class BaseFacebook
if (isset($config['trustForwarded']) && $config['trustForwarded']) {
$this->trustForwarded = true;
}
if (isset($config['allowSignedRequest'])
&& !$config['allowSignedRequest']) {
$this->allowSignedRequest = false;
}
$state = $this->getPersistentData('state');
if (!empty($state)) {
$this->state = $state;
@@ -241,6 +270,7 @@ abstract class BaseFacebook
* Set the Application ID.
*
* @param string $appId The Application ID
*
* @return BaseFacebook
*/
public function setAppId($appId) {
@@ -261,8 +291,10 @@ abstract class BaseFacebook
* Set the App Secret.
*
* @param string $apiSecret The App Secret
*
* @return BaseFacebook
* @deprecated
* @deprecated Use setAppSecret instead.
* @see setAppSecret()
*/
public function setApiSecret($apiSecret) {
$this->setAppSecret($apiSecret);
@@ -273,6 +305,7 @@ abstract class BaseFacebook
* Set the App Secret.
*
* @param string $appSecret The App Secret
*
* @return BaseFacebook
*/
public function setAppSecret($appSecret) {
@@ -284,7 +317,9 @@ abstract class BaseFacebook
* Get the App Secret.
*
* @return string the App Secret
* @deprecated
*
* @deprecated Use getAppSecret instead.
* @see getAppSecret()
*/
public function getApiSecret() {
return $this->getAppSecret();
@@ -303,6 +338,7 @@ abstract class BaseFacebook
* Set the file upload support status.
*
* @param boolean $fileUploadSupport The file upload support status.
*
* @return BaseFacebook
*/
public function setFileUploadSupport($fileUploadSupport) {
@@ -320,11 +356,12 @@ abstract class BaseFacebook
}
/**
* DEPRECATED! Please use getFileUploadSupport instead.
*
* Get the file upload support status.
*
* @return boolean true if and only if the server supports file upload.
*
* @deprecated Use getFileUploadSupport instead.
* @see getFileUploadSupport()
*/
public function useFileUploadSupport() {
return $this->getFileUploadSupport();
@@ -336,6 +373,7 @@ abstract class BaseFacebook
* to use it.
*
* @param string $access_token an access token.
*
* @return BaseFacebook
*/
public function setAccessToken($access_token) {
@@ -488,9 +526,10 @@ abstract class BaseFacebook
*/
public function getSignedRequest() {
if (!$this->signedRequest) {
if (!empty($_REQUEST['signed_request'])) {
if ($this->allowSignedRequest && !empty($_REQUEST['signed_request'])) {
$this->signedRequest = $this->parseSignedRequest(
$_REQUEST['signed_request']);
$_REQUEST['signed_request']
);
} else if (!empty($_COOKIE[$this->getSignedRequestCookieName()])) {
$this->signedRequest = $this->parseSignedRequest(
$_COOKIE[$this->getSignedRequestCookieName()]);
@@ -529,6 +568,11 @@ abstract class BaseFacebook
if ($signed_request) {
if (array_key_exists('user_id', $signed_request)) {
$user = $signed_request['user_id'];
if($user != $this->getPersistentData('user_id')){
$this->clearAllPersistentData();
}
$this->setPersistentData('user_id', $signed_request['user_id']);
return $user;
}
@@ -584,11 +628,15 @@ abstract class BaseFacebook
return $this->getUrl(
'www',
'dialog/oauth',
array_merge(array(
'client_id' => $this->getAppId(),
'redirect_uri' => $currentUrl, // possibly overwritten
'state' => $this->state),
$params));
array_merge(
array(
'client_id' => $this->getAppId(),
'redirect_uri' => $currentUrl, // possibly overwritten
'state' => $this->state,
'sdk' => 'php-sdk-'.self::VERSION
),
$params
));
}
/**
@@ -614,24 +662,14 @@ abstract class BaseFacebook
/**
* Get a login status URL to fetch the status from Facebook.
*
* The parameters:
* - ok_session: the URL to go to if a session is found
* - no_session: the URL to go to if the user is not connected
* - no_user: the URL to go to if the user is not signed into facebook
*
* @param array $params Provide custom parameters
* @return string The URL for the logout flow
*/
public function getLoginStatusUrl($params=array()) {
return $this->getUrl(
'www',
'extern/login_status.php',
return $this->getLoginUrl(
array_merge(array(
'api_key' => $this->getAppId(),
'no_session' => $this->getCurrentUrl(),
'no_user' => $this->getCurrentUrl(),
'ok_session' => $this->getCurrentUrl(),
'session_version' => 3,
'response_type' => 'code',
'display' => 'none',
), $params)
);
}
@@ -664,7 +702,7 @@ abstract class BaseFacebook
}
/**
* Constructs and returns the name of the coookie that potentially contain
* Constructs and returns the name of the cookie that potentially contain
* metadata. The cookie is not set by the BaseFacebook class, but it may be
* set by the JavaScript SDK.
*
@@ -683,20 +721,16 @@ abstract class BaseFacebook
* code could not be determined.
*/
protected function getCode() {
if (isset($_REQUEST['code'])) {
if ($this->state !== null &&
isset($_REQUEST['state']) &&
$this->state === $_REQUEST['state']) {
if (!isset($_REQUEST['code']) || !isset($_REQUEST['state'])) {
return false;
}
if ($this->state === $_REQUEST['state']) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $_REQUEST['code'];
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
}
}
self::errorLog('CSRF state token does not match one provided.');
return false;
}
@@ -727,7 +761,7 @@ abstract class BaseFacebook
* @return string The application access token, useful for gathering
* public information about users and applications.
*/
protected function getApplicationAccessToken() {
public function getApplicationAccessToken() {
return $this->appId.'|'.$this->appSecret;
}
@@ -752,6 +786,8 @@ abstract class BaseFacebook
* either logged in to Facebook or has granted an offline access permission.
*
* @param string $code An authorization code.
* @param string $redirect_uri Optional redirect URI. Default null
*
* @return mixed An access token exchanged for the authorization code, or
* false if an access token could not be generated.
*/
@@ -894,9 +930,13 @@ abstract class BaseFacebook
$params['access_token'] = $this->getAccessToken();
}
if (isset($params['access_token']) && !isset($params['appsecret_proof'])) {
$params['appsecret_proof'] = $this->getAppSecretProof($params['access_token']);
}
// json_encode all params values that are not strings
foreach ($params as $key => $value) {
if (!is_string($value)) {
if (!is_string($value) && !($value instanceof CURLFile)) {
$params[$key] = json_encode($value);
}
}
@@ -904,6 +944,19 @@ abstract class BaseFacebook
return $this->makeRequest($url, $params);
}
/**
* Generate a proof of App Secret
* This is required for all API calls originating from a server
* It is a sha256 hash of the access_token made using the app secret
*
* @param string $access_token The access_token to be hashed (required)
*
* @return string The sha256 hash of the access_token
*/
protected function getAppSecretProof($access_token) {
return hash_hmac('sha256', $access_token, $this->getAppSecret());
}
/**
* Makes an HTTP request. This method can be overridden by subclasses if
* developers want to do fancier things or use something other than curl to
@@ -941,11 +994,13 @@ abstract class BaseFacebook
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
$errno = curl_errno($ch);
// CURLE_SSL_CACERT || CURLE_SSL_CACERT_BADFILE
if ($errno == 60 || $errno == 77) {
self::errorLog('Invalid or no certificate authority found, '.
'using bundled information');
curl_setopt($ch, CURLOPT_CAINFO,
dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
dirname(__FILE__) . DIRECTORY_SEPARATOR . 'fb_ca_chain_bundle.crt');
$result = curl_exec($ch);
}
@@ -987,16 +1042,25 @@ abstract class BaseFacebook
* Parses a signed_request and validates the signature.
*
* @param string $signed_request A signed token
*
* @return array The payload inside it or null if the sig is wrong
*/
protected function parseSignedRequest($signed_request) {
if (!$signed_request || strpos($signed_request, '.') === false) {
self::errorLog('Signed request was invalid!');
return null;
}
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = self::base64UrlDecode($encoded_sig);
$data = json_decode(self::base64UrlDecode($payload), true);
if (strtoupper($data['algorithm']) !== self::SIGNED_REQUEST_ALGORITHM) {
if (!isset($data['algorithm'])
|| strtoupper($data['algorithm']) !== self::SIGNED_REQUEST_ALGORITHM
) {
self::errorLog(
'Unknown algorithm. Expected ' . self::SIGNED_REQUEST_ALGORITHM);
return null;
@@ -1005,18 +1069,30 @@ abstract class BaseFacebook
// check sig
$expected_sig = hash_hmac('sha256', $payload,
$this->getAppSecret(), $raw = true);
if ($sig !== $expected_sig) {
if (strlen($expected_sig) !== strlen($sig)) {
self::errorLog('Bad Signed JSON signature!');
return null;
}
return $data;
$result = 0;
for ($i = 0; $i < strlen($expected_sig); $i++) {
$result |= ord($expected_sig[$i]) ^ ord($sig[$i]);
}
if ($result == 0) {
return $data;
} else {
self::errorLog('Bad Signed JSON signature!');
return null;
}
}
/**
* Makes a signed_request blob using the given data.
*
* @param array The data array.
* @param array $data The data array.
*
* @return string The signed request.
*/
protected function makeSignedRequest($data) {
@@ -1036,7 +1112,8 @@ abstract class BaseFacebook
/**
* Build the URL for api given parameters.
*
* @param $method String the method name.
* @param string $method The method name.
*
* @return string The URL for the given parameters
*/
protected function getApiUrl($method) {
@@ -1113,9 +1190,9 @@ abstract class BaseFacebook
/**
* Build the URL for given domain alias, path and parameters.
*
* @param $name string The name of the domain
* @param $path string Optional path (without a leading slash)
* @param $params array Optional query parameters
* @param string $name The name of the domain
* @param string $path Optional path (without a leading slash)
* @param array $params Optional query parameters
*
* @return string The URL for the given parameters
*/
@@ -1134,13 +1211,26 @@ abstract class BaseFacebook
return $url;
}
/**
* Returns the HTTP Host
*
* @return string The HTTP Host
*/
protected function getHttpHost() {
if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
return $_SERVER['HTTP_X_FORWARDED_HOST'];
$forwardProxies = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
if (!empty($forwardProxies)) {
return $forwardProxies[0];
}
}
return $_SERVER['HTTP_HOST'];
}
/**
* Returns the HTTP Protocol
*
* @return string The HTTP Protocol
*/
protected function getHttpProtocol() {
if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
@@ -1162,7 +1252,9 @@ abstract class BaseFacebook
}
/**
* Get the base domain used for the cookie.
* Returns the base domain used for the cookie.
*
* @return string The base domain
*/
protected function getBaseDomain() {
// The base domain is stored in the metadata cookie if not we fallback
@@ -1175,8 +1267,6 @@ abstract class BaseFacebook
return $this->getHttpHost();
}
/**
/**
* Returns the Current URL, stripping it of known FB parameters that should
* not persist.
@@ -1223,13 +1313,14 @@ abstract class BaseFacebook
* params that should be stripped out.
*
* @param string $param A key or key/value pair within a URL's query (e.g.
* 'foo=a', 'foo=', or 'foo'.
* 'foo=a', 'foo=', or 'foo'.
*
* @return boolean
*/
protected function shouldRetainParam($param) {
foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) {
if (strpos($param, $drop_query_param.'=') === 0) {
if ($param === $drop_query_param ||
strpos($param, $drop_query_param.'=') === 0) {
return false;
}
}
@@ -1242,7 +1333,7 @@ abstract class BaseFacebook
* because the access token is no longer valid. If that is
* the case, then we destroy the session.
*
* @param $result array A record storing the error message returned
* @param array $result A record storing the error message returned
* by a failed API call.
*/
protected function throwAPIException($result) {
@@ -1291,8 +1382,9 @@ abstract class BaseFacebook
* _ instead of /
* No padded =
*
* @param string $input base64UrlEncoded string
* @return string
* @param string $input base64UrlEncoded input
*
* @return string The decoded string
*/
protected static function base64UrlDecode($input) {
return base64_decode(strtr($input, '-_', '+/'));
@@ -1304,8 +1396,8 @@ abstract class BaseFacebook
* - instead of +
* _ instead of /
*
* @param string $input string
* @return string base64Url encoded string
* @param string $input The input to encode
* @return string The base64Url encoded input, as a string.
*/
protected static function base64UrlEncode($input) {
$str = strtr(base64_encode($input), '+/', '-_');
@@ -1345,7 +1437,7 @@ abstract class BaseFacebook
/**
* Parses the metadata cookie that our Javascript API set
*
* @return an array mapping key to value
* @return array an array mapping key to value
*/
protected function getMetadataCookie() {
$cookie_name = $this->getMetadataCookieName();
@@ -1373,6 +1465,14 @@ abstract class BaseFacebook
return $metadata;
}
/**
* Finds whether the given domain is allowed or not
*
* @param string $big The value to be checked against $small
* @param string $small The input string
*
* @return boolean Returns TRUE if $big matches $small
*/
protected static function isAllowedDomain($big, $small) {
if ($big === $small) {
return true;
@@ -1380,6 +1480,14 @@ abstract class BaseFacebook
return self::endsWith($big, '.'.$small);
}
/**
* Checks if $big string ends with $small string
*
* @param string $big The value to be checked against $small
* @param string $small The input string
*
* @return boolean TRUE if $big ends with $small
*/
protected static function endsWith($big, $small) {
$len = strlen($small);
if ($len === 0) {
@@ -1423,6 +1531,7 @@ abstract class BaseFacebook
* Clear the data with $key from the persistent storage
*
* @param string $key
*
* @return void
*/
abstract protected function clearPersistentData($key);

View File

@@ -23,13 +23,22 @@ require_once "base_facebook.php";
*/
class Facebook extends BaseFacebook
{
/**
* Cookie prefix
*/
const FBSS_COOKIE_NAME = 'fbss';
// We can set this to a high number because the main session
// expiration will trump this.
/**
* We can set this to a high number because the main session
* expiration will trump this.
*/
const FBSS_COOKIE_EXPIRE = 31556926; // 1 year
// Stores the shared session ID if one is set.
/**
* Stores the shared session ID if one is set.
*
* @var string
*/
protected $sharedSessionID;
/**
@@ -38,25 +47,45 @@ class Facebook extends BaseFacebook
* access token if during the course of execution
* we discover them.
*
* @param Array $config the application configuration. Additionally
* @param array $config the application configuration. Additionally
* accepts "sharedSession" as a boolean to turn on a secondary
* cookie for environments with a shared session (that is, your app
* shares the domain with other apps).
* @see BaseFacebook::__construct in facebook.php
*
* @see BaseFacebook::__construct
*/
public function __construct($config) {
if (!session_id()) {
if ((function_exists('session_status')
&& session_status() !== PHP_SESSION_ACTIVE) || !session_id()) {
session_start();
}
parent::__construct($config);
if (!empty($config['sharedSession'])) {
$this->initSharedSession();
// re-load the persisted state, since parent
// attempted to read out of non-shared cookie
$state = $this->getPersistentData('state');
if (!empty($state)) {
$this->state = $state;
} else {
$this->state = null;
}
}
}
/**
* Supported keys for persistent data
*
* @var array
*/
protected static $kSupportedKeys =
array('state', 'code', 'access_token', 'user_id');
/**
* Initiates Shared Session
*/
protected function initSharedSession() {
$cookie_name = $this->getSharedSessionCookieName();
if (isset($_COOKIE[$cookie_name])) {
@@ -95,10 +124,16 @@ class Facebook extends BaseFacebook
/**
* Provides the implementations of the inherited abstract
* methods. The implementation uses PHP sessions to maintain
* methods. The implementation uses PHP sessions to maintain
* a store for authorization codes, user ids, CSRF states, and
* access tokens.
*/
/**
* {@inheritdoc}
*
* @see BaseFacebook::setPersistentData()
*/
protected function setPersistentData($key, $value) {
if (!in_array($key, self::$kSupportedKeys)) {
self::errorLog('Unsupported key passed to setPersistentData.');
@@ -109,6 +144,11 @@ class Facebook extends BaseFacebook
$_SESSION[$session_var_name] = $value;
}
/**
* {@inheritdoc}
*
* @see BaseFacebook::getPersistentData()
*/
protected function getPersistentData($key, $default = false) {
if (!in_array($key, self::$kSupportedKeys)) {
self::errorLog('Unsupported key passed to getPersistentData.');
@@ -120,6 +160,11 @@ class Facebook extends BaseFacebook
$_SESSION[$session_var_name] : $default;
}
/**
* {@inheritdoc}
*
* @see BaseFacebook::clearPersistentData()
*/
protected function clearPersistentData($key) {
if (!in_array($key, self::$kSupportedKeys)) {
self::errorLog('Unsupported key passed to clearPersistentData.');
@@ -127,9 +172,16 @@ class Facebook extends BaseFacebook
}
$session_var_name = $this->constructSessionVariableName($key);
unset($_SESSION[$session_var_name]);
if (isset($_SESSION[$session_var_name])) {
unset($_SESSION[$session_var_name]);
}
}
/**
* {@inheritdoc}
*
* @see BaseFacebook::clearAllPersistentData()
*/
protected function clearAllPersistentData() {
foreach (self::$kSupportedKeys as $key) {
$this->clearPersistentData($key);
@@ -139,6 +191,9 @@ class Facebook extends BaseFacebook
}
}
/**
* Deletes Shared session cookie
*/
protected function deleteSharedSessionCookie() {
$cookie_name = $this->getSharedSessionCookieName();
unset($_COOKIE[$cookie_name]);
@@ -146,10 +201,23 @@ class Facebook extends BaseFacebook
setcookie($cookie_name, '', 1, '/', '.'.$base_domain);
}
/**
* Returns the Shared session cookie name
*
* @return string The Shared session cookie name
*/
protected function getSharedSessionCookieName() {
return self::FBSS_COOKIE_NAME . '_' . $this->getAppId();
}
/**
* Constructs and returns the name of the session key.
*
* @see setPersistentData()
* @param string $key The key for which the session variable name to construct.
*
* @return string The name of the session key.
*/
protected function constructSessionVariableName($key) {
$parts = array('fb', $this->getAppId(), $key);
if ($this->sharedSessionID) {

View File

@@ -2,6 +2,8 @@
// http://code.google.com/p/simple-linkedinphp/
// 3.2.0 - November 29, 2011
// hacked into the code to handel new scope (r_basicprofile+r_emailaddress) - until Paul update linkedinphp library!
// Facyla note 20131219 : this in fact should not be hacked, as Linkedin lets developpers define the wanted scope
// in Linkedin application settings, when creating the (required) application and API access
/**
* This file defines the 'LinkedIn' class. This class is designed to be a
@@ -122,8 +124,8 @@ class LinkedIn {
const _URL_ACCESS = 'https://api.linkedin.com/uas/oauth/accessToken';
const _URL_API = 'https://api.linkedin.com';
const _URL_AUTH = 'https://www.linkedin.com/uas/oauth/authenticate?oauth_token=';
// const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken';
const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress+rw_nus';
const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken';
// const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress+rw_nus+r_network';
const _URL_REVOKE = 'https://api.linkedin.com/uas/oauth/invalidateToken';
// Library version
@@ -441,7 +443,7 @@ class LinkedIn {
* http://developer.linkedin.com/docs/DOC-1327
*
* @param str $cid
* Company ID you want the producte for.
* Company ID you want the product for.
* @param str $options
* [OPTIONAL] Data retrieval options.
*
@@ -670,6 +672,10 @@ class LinkedIn {
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($handle, CURLOPT_URL, $url);
curl_setopt($handle, CURLOPT_VERBOSE, FALSE);
if ( isset ( Hybrid_Auth::$config["proxy"] ) ) {
curl_setopt($handle, CURLOPT_PROXY, Hybrid_Auth::$config["proxy"]);
}
// configure the header we are sending to LinkedIn - http://developer.linkedin.com/docs/DOC-1203
$header = array($oauth_req->to_header(self::_API_OAUTH_REALM));
@@ -696,6 +702,9 @@ class LinkedIn {
// gather the response
$return_data['linkedin'] = curl_exec($handle);
if( $return_data['linkedin'] === FALSE ) {
Hybrid_Logger::error( "LinkedIn::fetch(). curl_exec error: ", curl_error($ch) );
}
$return_data['info'] = curl_getinfo($handle);
$return_data['oauth']['header'] = $oauth_req->to_header(self::_API_OAUTH_REALM);
$return_data['oauth']['string'] = $oauth_req->base_string;
@@ -2056,10 +2065,10 @@ class LinkedIn {
* The group id.
* @param str $xml
* The group settings to set. The settings are:
* -<show-group-logo-in-profle>
* -<show-group-logo-in-profile>
* -<contact-email>
* -<email-digest-frequency>
* -<email-annoucements-from-managers>
* -<email-announcements-from-managers>
* -<allow-messages-from-members>
* -<email-for-every-new-post>
*
@@ -2255,7 +2264,7 @@ class LinkedIn {
// send request
$response = $this->fetch('POST', $share_url, $data);
} else {
// data contraints/rules not met, raise an exception
// data constraints/rules not met, raise an exception
throw new LinkedInException('LinkedIn->share(): sharing data constraints not met; check that you have supplied valid content and combinations of content to share.');
}
} else {
@@ -2601,7 +2610,7 @@ class LinkedIn {
public static function xmlToArray($xml) {
// check passed data
if(!is_string($xml)) {
// bad data possed
// bad data passed
throw new LinkedInException('LinkedIn->xmlToArray(): bad data passed, $xml must be a non-zero length string.');
}

View File

@@ -1,14 +1,15 @@
<?php
// http://oauth.googlecode.com/svn/code/php/OAuth.php
// rev 1261, Mar 29, 2011 morten.fangel
// modified on Dec 29, 2019 to remove OAuth PECL conflict
// rev 1276, July 4, 2014
// vim: foldmethod=marker
/* Generic exception class
*/
class OAuthExceptionPHP extends Exception {
// pass
if (!class_exists('OAuthException')) {
class OAuthException extends Exception {
// pass
}
}
class OAuthConsumer {
@@ -262,6 +263,9 @@ class OAuthRequest {
$scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
? 'http'
: 'https';
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$scheme = $_SERVER['HTTP_X_FORWARDED_PROTO'];
}
$http_url = ($http_url) ? $http_url : $scheme .
'://' . $_SERVER['SERVER_NAME'] .
':' .
@@ -447,7 +451,7 @@ class OAuthRequest {
foreach ($this->parameters as $k => $v) {
if (substr($k, 0, 5) != "oauth") continue;
if (is_array($v)) {
throw new OAuthExceptionPHP('Arrays not supported in headers');
throw new OAuthException('Arrays not supported in headers');
}
$out .= ($first) ? ' ' : ',';
$out .= OAuthUtil::urlencode_rfc3986($k) .
@@ -580,7 +584,7 @@ class OAuthServer {
$version = '1.0';
}
if ($version !== $this->version) {
throw new OAuthExceptionPHP("OAuth version '$version' not supported");
throw new OAuthException("OAuth version '$version' not supported");
}
return $version;
}
@@ -596,12 +600,12 @@ class OAuthServer {
if (!$signature_method) {
// According to chapter 7 ("Accessing Protected Ressources") the signature-method
// parameter is required, and we can't just fallback to PLAINTEXT
throw new OAuthExceptionPHP('No signature method parameter. This parameter is required');
throw new OAuthException('No signature method parameter. This parameter is required');
}
if (!in_array($signature_method,
array_keys($this->signature_methods))) {
throw new OAuthExceptionPHP(
throw new OAuthException(
"Signature method '$signature_method' not supported " .
"try one of the following: " .
implode(", ", array_keys($this->signature_methods))
@@ -619,12 +623,12 @@ class OAuthServer {
: NULL;
if (!$consumer_key) {
throw new OAuthExceptionPHP("Invalid consumer key");
throw new OAuthException("Invalid consumer key");
}
$consumer = $this->data_store->lookup_consumer($consumer_key);
if (!$consumer) {
throw new OAuthExceptionPHP("Invalid consumer");
throw new OAuthException("Invalid consumer");
}
return $consumer;
@@ -642,7 +646,7 @@ class OAuthServer {
$consumer, $token_type, $token_field
);
if (!$token) {
throw new OAuthExceptionPHP("Invalid $token_type token: $token_field");
throw new OAuthException("Invalid $token_type token: $token_field");
}
return $token;
}
@@ -674,7 +678,7 @@ class OAuthServer {
);
if (!$valid_sig) {
throw new OAuthExceptionPHP("Invalid signature");
throw new OAuthException("Invalid signature");
}
}
@@ -683,14 +687,14 @@ class OAuthServer {
*/
private function check_timestamp($timestamp) {
if( ! $timestamp )
throw new OAuthExceptionPHP(
throw new OAuthException(
'Missing timestamp parameter. The parameter is required'
);
// verify that timestamp is recentish
$now = time();
if (abs($now - $timestamp) > $this->timestamp_threshold) {
throw new OAuthExceptionPHP(
throw new OAuthException(
"Expired timestamp, yours $timestamp, ours $now"
);
}
@@ -701,7 +705,7 @@ class OAuthServer {
*/
private function check_nonce($consumer, $token, $nonce, $timestamp) {
if( ! $nonce )
throw new OAuthExceptionPHP(
throw new OAuthException(
'Missing nonce parameter. The parameter is required'
);
@@ -713,7 +717,7 @@ class OAuthServer {
$timestamp
);
if ($found) {
throw new OAuthExceptionPHP("Nonce already used: $nonce");
throw new OAuthException("Nonce already used: $nonce");
}
}

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
// A service client for the OAuth 1/1.0a flow.
@@ -108,31 +108,31 @@ class OAuth1Client{
}
/**
* GET wrappwer for provider apis request
* GET wrapper for provider apis request
*/
function get($url, $parameters = array())
function get($url, $parameters = array(), $content_type = NULL)
{
return $this->api($url, 'GET', $parameters);
return $this->api($url, 'GET', $parameters, NULL, $content_type);
}
/**
* POST wreapper for provider apis request
* POST wrapper for provider apis request
*/
function post($url, $parameters = array())
function post($url, $parameters = array(), $body = NULL, $content_type = NULL, $multipart = false)
{
return $this->api($url, 'POST', $parameters);
return $this->api($url, 'POST', $parameters, $body, $content_type, $multipart );
}
/**
* Format and sign an oauth for provider api
*/
function api( $url, $method = 'GET', $parameters = array() )
function api( $url, $method = 'GET', $parameters = array(), $body = NULL, $content_type = NULL, $multipart = false )
{
if ( strrpos($url, 'http://') !== 0 && strrpos($url, 'https://') !== 0 ) {
$url = $this->api_base_url . $url;
}
$response = $this->signedRequest( $url, $method, $parameters );
$response = $this->signedRequest( $url, $method, $parameters, $body, $content_type, $multipart );
if( $this->decode_json ){
$response = json_decode( $response );
@@ -144,20 +144,34 @@ class OAuth1Client{
/**
* Make signed request
*/
function signedRequest( $url, $method, $parameters )
function signedRequest( $url, $method, $parameters, $body = NULL, $content_type = NULL, $multipart = false )
{
$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters);
$signature_parameters = array();
// when making a multipart request, use only oauth_* keys for signature
foreach( $parameters AS $key => $value ){
if( !$multipart || strpos( $key, 'oauth_' ) === 0 ){
$signature_parameters[$key] = $value;
}
}
$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $signature_parameters);
$request->sign_request($this->sha1_method, $this->consumer, $this->token);
switch ($method) {
case 'GET': return $this->request( $request->to_url(), 'GET' );
default : return $this->request( $request->get_normalized_http_url(), $method, $request->to_postdata(), $request->to_header() ) ;
case 'GET': return $this->request( $request->to_url(), 'GET', NULL, NULL, $content_type );
default :
if ($body)
return $this->request( $request->to_url(), $method, $body, $request->to_header(), $content_type );
else
return $this->request( $request->get_normalized_http_url(), $method, ($multipart ? $parameters : $request->to_postdata()), $request->to_header(), $content_type, $multipart ) ;
}
}
/**
* Make http request
*/
function request( $url, $method, $postfields = NULL, $auth_header = null )
function request( $url, $method, $postfields = NULL, $auth_header = NULL, $content_type = NULL, $multipart = false )
{
Hybrid_Logger::info( "Enter OAuth1Client::request( $method, $url )" );
Hybrid_Logger::debug( "OAuth1Client::request(). dump post fields: ", serialize( $postfields ) );
@@ -174,6 +188,12 @@ class OAuth1Client{
curl_setopt( $ci, CURLOPT_SSL_VERIFYPEER, $this->curl_ssl_verifypeer );
curl_setopt( $ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader') );
curl_setopt( $ci, CURLOPT_HEADER , FALSE );
if( $multipart ){
curl_setopt( $ci, CURLOPT_HTTPHEADER, array( 'Expect:', $auth_header ) );
}elseif ($content_type)
curl_setopt( $ci, CURLOPT_HTTPHEADER, array('Expect:', "Content-Type: $content_type") );
if($this->curl_proxy){
curl_setopt( $ci, CURLOPT_PROXY , $this->curl_proxy);
@@ -187,7 +207,7 @@ class OAuth1Client{
curl_setopt( $ci, CURLOPT_POSTFIELDS, $postfields );
}
if ( !empty($auth_header) && $this->curl_auth_header ){
if ( !empty($auth_header) && $this->curl_auth_header && !$multipart ){
curl_setopt( $ci, CURLOPT_HTTPHEADER, array( 'Content-Type: application/atom+xml', $auth_header ) );
}
break;
@@ -200,6 +220,10 @@ class OAuth1Client{
curl_setopt($ci, CURLOPT_URL, $url);
$response = curl_exec($ci);
if( $response === FALSE ) {
Hybrid_Logger::error( "OAuth1Client::request(). curl_exec error: ", curl_error($ci) );
}
Hybrid_Logger::debug( "OAuth1Client::request(). dump request info: ", serialize( curl_getinfo($ci) ) );
Hybrid_Logger::debug( "OAuth1Client::request(). dump request result: ", serialize( $response ) );

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
// A service client for the OAuth 2 flow.
@@ -30,6 +30,7 @@ class OAuth2Client
public $curl_time_out = 30;
public $curl_connect_time_out = 30;
public $curl_ssl_verifypeer = false;
public $curl_ssl_verifyhost = false;
public $curl_header = array();
public $curl_useragent = "OAuth/2 Simple PHP Client v0.1; HybridAuth http://hybridauth.sourceforge.net/";
public $curl_authenticate_method = "POST";
@@ -61,7 +62,7 @@ class OAuth2Client
foreach( $extras as $k=>$v )
$params[$k] = $v;
return $this->authorize_url . "?" . http_build_query( $params );
return $this->authorize_url . "?" . http_build_query($params, '', '&');
}
public function authenticate( $code )
@@ -146,7 +147,7 @@ class OAuth2Client
}
/**
* GET wrappwer for provider apis request
* GET wrapper for provider apis request
*/
function get( $url, $parameters = array() )
{
@@ -154,7 +155,7 @@ class OAuth2Client
}
/**
* POST wreapper for provider apis request
* POST wrapper for provider apis request
*/
function post( $url, $parameters = array() )
{
@@ -194,7 +195,7 @@ class OAuth2Client
Hybrid_Logger::debug( "OAuth2Client::request(). dump request params: ", serialize( $params ) );
if( $type == "GET" ){
$url = $url . ( strpos( $url, '?' ) ? '&' : '?' ) . http_build_query( $params );
$url = $url . ( strpos( $url, '?' ) ? '&' : '?' ) . http_build_query($params, '', '&');
}
$this->http_info = array();
@@ -206,6 +207,7 @@ class OAuth2Client
curl_setopt($ch, CURLOPT_USERAGENT , $this->curl_useragent );
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , $this->curl_connect_time_out );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , $this->curl_ssl_verifypeer );
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST , $this->curl_ssl_verifyhost );
curl_setopt($ch, CURLOPT_HTTPHEADER , $this->curl_header );
if($this->curl_proxy){
@@ -218,6 +220,9 @@ class OAuth2Client
}
$response = curl_exec($ch);
if( $response === FALSE ) {
Hybrid_Logger::error( "OAuth2Client::request(). curl_exec error: ", curl_error($ch) );
}
Hybrid_Logger::debug( "OAuth2Client::request(). dump request info: ", serialize( curl_getinfo($ch) ) );
Hybrid_Logger::debug( "OAuth2Client::request(). dump request result: ", serialize( $response ) );
@@ -233,11 +238,11 @@ class OAuth2Client
{
if( json_decode( $result ) ) return json_decode( $result );
parse_str( $result, $ouput );
parse_str( $result, $output );
$result = new StdClass();
foreach( $ouput as $k => $v )
foreach( $output as $k => $v )
$result->$k = $v;
return $result;

View File

@@ -49,7 +49,7 @@ class LightOpenID
$this->trustRoot = (strpos($host, '://') ? $host : 'https://' . $host);
}
if(($host_end = strpos($this->trustRoot, '/', 8)) !== false) {
if(strlen($this->trustRoot >= 8) && ($host_end = strpos($this->trustRoot, '/', 8)) !== false) {
$this->trustRoot = substr($this->trustRoot, 0, $host_end);
}
@@ -204,6 +204,9 @@ class LightOpenID
curl_setopt($curl, CURLOPT_HTTPGET, true);
}
$response = curl_exec($curl);
if( $response === FALSE ) {
Hybrid_Logger::error( "LightOpenID::request_curl(). curl_exec error: ", curl_error($curl) );
}
if($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
curl_setopt($curl, CURLOPT_HTTPGET, true);
@@ -626,7 +629,7 @@ class LightOpenID
{
$params = array();
# We always use SREG 1.1, even if the server is advertising only support for 1.0.
# That's because it's fully backwards compatibile with 1.0, and some providers
# That's because it's fully backwards compatible with 1.0, and some providers
# advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
$params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
if ($this->required) {
@@ -676,7 +679,7 @@ class LightOpenID
$params['openid.ax.count.' . $alias] = $count;
}
# Don't send empty ax.requied and ax.if_available.
# Don't send empty ax.required and ax.if_available.
# Google and possibly other providers refuse to support ax when one of these is empty.
if($required) {
$params['openid.ax.required'] = implode(',', $required);
@@ -809,7 +812,7 @@ class LightOpenID
if ($this->data['openid_return_to'] != $this->returnUrl) {
# The return_to url must match the url of current request.
# I'm assuing that noone will set the returnUrl to something that doesn't make sense.
# I'm assuming that no one will set the returnUrl to something that doesn't make sense.
return false;
}
@@ -818,7 +821,7 @@ class LightOpenID
foreach (explode(',', $this->data['openid_signed']) as $item) {
# Checking whether magic_quotes_gpc is turned on, because
# the function may fail if it is. For example, when fetching
# AX namePerson, it might containg an apostrophe, which will be escaped.
# AX namePerson, it might contain an apostrophe, which will be escaped.
# In such case, validation would fail, since we'd send different data than OP
# wants to verify. stripslashes() should solve that problem, but we can't
# use it when magic_quotes is off.
@@ -900,7 +903,7 @@ class LightOpenID
}
/**
* Gets AX/SREG attributes provided by OP. should be used only after successful validaton.
* Gets AX/SREG attributes provided by OP. should be used only after successful validation.
* Note that it does not guarantee that any of the required/optional parameters will be present,
* or that there will be no other attributes besides those specified.
* In other words. OP may provide whatever information it wants to.

View File

@@ -1,8 +1,8 @@
<?php
/*!
/**
* HybridAuth
* http://hybridauth.sourceforge.net | https://github.com/hybridauth/hybridauth
* (c) 2009-2011 HybridAuth authors | hybridauth.sourceforge.net/licenses.html
* http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
* (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
*/
// ------------------------------------------------------------------------