Skip to content

Instantly share code, notes, and snippets.

@mehlah
Created April 6, 2012 11:32
Show Gist options
  • Save mehlah/2319037 to your computer and use it in GitHub Desktop.
Save mehlah/2319037 to your computer and use it in GitHub Desktop.
Auth Oauth adapter Lithium
<?php
namespace li3_omniauth;
class Consumer extends \lithium\core\StaticObject {
/**
* Holds an instance of the oauth service class
*
* @see \li3_oauth\extensions\services\Oauth
*/
protected static $_service = null;
protected static $_classes = array(
'oauth' => '\li3_omniauth\extensions\service\Oauth',
'oauth2' => '\li3_omniauth\extensions\service\Oauth2'
);
/**
* Configure the Consumer to access the Oauth service layer
* {{{
* Consumer::config(array(
* 'host' => 'localhost',
* 'oauth_consumer_key' => 'key',
* 'oauth_consumer_secret' => 'secret',
* 'request_token' => 'libraries/oauth_php/example/request_token.php',
* 'access_token' => 'libraries/oauth_php/example/access_token.php',
* ));
* }}}
*
* @param array $config
* - host: the oauth domain
* - oauth_consumer_key: key from oauth service provider
* - oauth_consumer_secret: secret from oauth service provider
* - oauth_consumer_key: key from oauth service provider
* - authorize: path to authorize url
* - request_token: path to request token url
* - access_token: path to access token url
* - service: service class name oauth/oauth2
*
* @return void
*/
public static function config($config) {
if (isset($config['service'])) {
static::$_service = new static::$_classes[$config['service']]($config);
} else {
static::$_service = new static::$_classes['oauth']($config);
}
}
/**
* Magic method to pass through HTTP methods. i.e.`Consumer::post()`
*
* @param string $method
* @param string $params
* @return mixed
*/
public static function __callStatic($method, $params) {
return static::$_service->invokeMethod($method, $params);
}
/**
* Signs and Sends a post request to the request token endpoint with optional params
*
* @param string $type the type of token to get. request|access
* @param array $options optional params for the request
* - `method`: POST
* - `oauth_signature_method`: HMAC-SHA1
* @return string
*/
public static function token($type, array $options = array()) {
return static::$_service->token($type, $options);
}
/**
* get url from remote authorization endpoint along with request params
*
* @param array $token
* @param array $options
* @return string
*/
public static function authorize(array $token, array $options = array()) {
return static::$_service->url('authorize', compact('token') + $options);
}
/**
* get url from remote authenticated endpoint along with token
*
* @param array $token
* @param array $options
* @return string
*/
public static function authenticate(array $token, array $options = array()) {
return static::$_service->url('authenticate', compact('token') + $options);
}
/**
* undocumented function
*
* @param string $key
* @param string $value
* @return void
*/
public static function store($key, $value) {
return static::$_service->storage->write($key, $value);
}
/**
* undocumented function
*
* @param string $key
* @return void
*/
public static function fetch($key) {
return static::$_service->storage->read($key);
}
/**
* undocumented function
*
* @param string $key
* @return void
*/
public static function delete($key) {
return static::$_service->storage->remove($key);
}
public static function serviceConfig($key) {
return static::$_service->config($key);
}
}
?>
<?php
Auth::config(array('default' => array(
'adapter' => 'Oauth',
'strategies' => array('Github' => array(
'client_id' => 'xxx',
'client_secret' => 'xxx',
'scope' => array()
))
)));
?>
<?php
namespace li3_omniauth\extensions\service;
use li3_omniauth\Consumer;
/**
* Oauth service class for handling requests/response to consumers and from providers
*
*
*/
class Oauth2 extends \lithium\net\http\Service {
protected $_autoConfig = array('classes' => 'merge');
/**
* Fully-namespaced class references
*
* @var array
*/
protected $_classes = array(
'media' => '\lithium\net\http\Media',
'request' => '\lithium\net\http\Request',
'response' => '\lithium\net\http\Response',
'socket' => '\lithium\net\socket\Context'
);
/**
* Constructor
*
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-11.2
* @param array $config
* - host: the oauth domain
* - oauth_consumer_secret: secret from oauth service provider
* - oauth_consumer_key: key from oauth service provider
* - authorize: path to authorize url
* - request_token: path to request token url
* - access_token: path to access token url
*/
public function __construct($config = array()) {
$defaults = array(
'scheme' => 'https',
'host' => 'localhost',
'port' => 443,
'access' => '',
'authorize' => '',
'client_id' => 'key',
'client_secret' => 'secret',
'response_type' => 'code',
'redirect_uri' => '',
'scope' => '',
'state' => '',
'code' => '',
'grant_type' => ''
);
$config += $defaults;
parent::__construct($config);
}
/**
* If a key is set returns the value of that key
* Without a key it will return config array
*
* @param string $key eg `oauth_consumer_key`
* @return void
*/
public function config($key = null) {
if (isset($this->_config[$key])) {
return $this->_config[$key];
}
if ($key !== null) {
return $key;
}
return $this->_config;
}
/**
* Requests a token of a particular type
*
* @param string $query
* @return array parameters sent from the response body
*/
public function token($type, array $options = array()) {
$defaults = array('params' => array(
'client_id', 'client_secret'
));
$options = array_merge_recursive($options, $defaults);
$this->_parseParams($options);
$url = $this->_config[$type];
$result = parent::get($url, $options['params']);
return $result;
}
/**
* Send request with the given options and data. The token should be part of the options.
*
* @param string $method
* @param string $path
* @param array $data encoded for the request
* @param array $options oauth parameters
* - headers : send parameters in the header. (default: true)
* - realm : the realm to authenticate. (default: app directory name)
* @return mixed the response from api call
*/
public function send($method, $path = null, $data = array(), array $options = array()) {
self::_parseParams($options);
$data += $options['params'];
$defaults = array('headers' => true, 'realm' => basename(LITHIUM_APP_PATH));
$url = $this->config($path);
$options['host'] = $this->_config['host'];
$response = parent::send($method, $url, $data);
$hasToken = (strpos($response, 'access_token=') !== false);
$isJson = (strpos($response, '"data":') !== false);
if ($hasToken && !$isJson) {
return $this->_decode($response);
}
return $response;
}
/**
* A utility method to return an authorize or authenticate url for redirect
*
* @param string $url the url key for the required url
* @param array $options
* - `token`: (array) adds the access_token to the query params
* - `usePort`: (boolean) use the port in the signature base string
* - `params`: (array) use these as additional parameters on the url
* @return string the full url
*/
public function url($url = null, array $options = array()) {
$defaults = array(
'token' => array('access_token' => false),
'usePort' => false,
'params' => array()
);
$options += $defaults;
$host = $this->_config['host'];
$url = $url ? $this->config($url) : null;
self::_parseParams($options);
$params = !empty($options['params'])? '?' . http_build_query($options['params']) : '';
$base = $host;
$base .= ($options['usePort']) ? ":{$this->_config['port']}" : null;
return "{$this->_config['scheme']}://" . str_replace('//', '/', "{$base}/{$url}{$params}");
}
/**
* A utility method to return an authorize or authenticate url for redirect
*
* @param array $options contains the 'params' sub-array
* @return void
*/
protected function _parseParams(&$options) {
$defaults = array('params' => array());
$options += $defaults;
if (isset($options['token']['access_token']) && $options['token']['access_token']) {
$options['params']['access_token'] = $options['token']['access_token'];
}
if (isset($options['code']) && $options['code']) {
$options['params']['code'] = $options['code'];
}
foreach($options['params'] as $key => $value) {
if (isset($this->_config[$value]) && $this->_config[$value]) {
$options['params'][$value] = $this->_config[$value];
unset($options['params'][$key]);
}
}
}
/**
* Decodes the response body.
*
* @param string $query
* @return array parameters sent from the response body
*/
protected function _decode($query = null) {
parse_str($query, $data);
return $data;
}
}
?>
<?php
use lithium\net\http\Router;
use lithium\action\Response;
use li3_omniauth\Consumer;
use lithium\storage\Session;
Router::connect('/auth/github', array(), function($request){
// This should come from Auth::config
Consumer::config(array(
'service' => 'oauth2',
'host' => 'github.com',
'client_id' => 'd4aa8199cf2ac9e8a4be',
'client_secret' => 'fdee16952602692c0152296b6f8cfe838df3ce2a',
'access' => '/login/oauth/access_token',
'authorize' => '/login/oauth/authorize'
));
$token = array();
$location = Consumer::authorize($token, array(
'params' => array(
'client_id'
)
));
return new Response(compact('location'));
});
Router::connect('/auth/github/callback', array(), function($request){
Consumer::config(array(
'service' => 'oauth2',
'host' => 'github.com',
'client_id' => 'd4aa8199cf2ac9e8a4be',
'client_secret' => 'fdee16952602692c0152296b6f8cfe838df3ce2a',
'access' => '/login/oauth/access_token',
'authorize' => '/login/oauth/authorize'
));
if (!empty($request->query['error']) || !empty($request->query['error_reason'])) {
// TODO: handle me!
}
$code = $request->query['code'];
$access = Consumer::token('access', compact('code'));
Session::delete('oauth.access');
Session::write('oauth.access', $access);
return new Response(array('location' => 'Sessions::create'));
});
?>
@mehlah
Copy link
Author

mehlah commented Apr 19, 2012

Oauth Auth adapter check method fetch user data based on configured srategy (Github, Twitter etc...).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment