Skip to content

Instantly share code, notes, and snippets.

@christopher-b
Last active December 16, 2015 20:49
Show Gist options
  • Save christopher-b/5495515 to your computer and use it in GitHub Desktop.
Save christopher-b/5495515 to your computer and use it in GitHub Desktop.
A Zend Auth Adapter implementation for OAuth. Created for use with LTI tools.
<?php
class Dashboard_Model_OAuth_Consumer extends OCAD_Db_Row
{
public function recordRequest($timestamp, $nonce)
{
if( $timestamp > $this->timestamp )
{
// Update saved timestamp
$this->timestamp = $timestamp;
$this->setNonces(array($nonce)); // Clear saved nonces
$this->save();
}
else
{
// Add current nonce to nonces saved for this timestamp
$nonces = $this->getNonces();
$nonces[] = $nonce;
$this->setNonces($nonces);
}
$this->save();
}
public function getNonces()
{
return json_decode($this->nonces);
}
public function setNonces(array $nonces)
{
$this->nonces = json_encode($nonces);
}
}
<?php
class OCAD_Authentication_Adapter_OAuth implements Zend_Auth_Adapter_Interface
{
/*
* Required OAuth parameters
* @var array
*/
protected $_required = array("oauth_consumer_key", "oauth_signature", "oauth_nonce", "oauth_timestamp", "lis_person_sourcedid");
/**
* @var Zend_Controller_Request_Http
*/
protected $_request;
/**
* @var array
*/
protected $_config;
public function __construct($config = null, $request = null)
{
$this->_config = $config;
$this->_request = $request;
}
/**
* Implementation of interface method
*/
public function authenticate()
{
$errors = array();
$oauthSignature = $this->_request->get('oauth_signature');
$oauthTimestamp = $this->_request->get('oauth_timestamp');
$oauthNonce = $this->_request->get('oauth_nonce');
$oauthKey = $this->_request->get('oauth_consumer_key');
$username = $this->_request->get('lis_person_sourcedid');
try
{
$consumer = $this->_getConsumer($oauthKey);
if( abs(time() - $oauthTimestamp) > $this->_config['maxTimestampOffset'] )
{
throw new OCAD_Exception('The OAuth timestamp is invalid (differs from server time)');
}
if($oauthTimestamp < $consumer->timestamp)
{
throw new OCAD_Exception('The OAuth timestamp is invalid (less than a previously used value)');
}
if( in_array($oauthNonce, $consumer->getNonces()) )
{
throw new OCAD_Exception('The OAuth nonce has alread been used');
}
if($this->_getSignature($consumer) !== $oauthSignature)
{
throw new OCAD_Exception("Couldn't validate signature");
}
// Signature is valid
$consumer->recordRequest($oauthTimestamp, $oauthNonce);
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $username, array());
}
catch (OCAD_Exception $e)
{
$errors[] = $e->getMessage();
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $errors);
}
}
/**
* Determines if the request has required params to do authentication
*/
public function canAuthenticate()
{
foreach($this->_required as $param)
{
if(!$this->_request->has($param))
{
return false;
}
}
return true;
}
public function getLoginUrl()
{
return false;
}
public function getLogoutUrl()
{
return $this->_logoutUrl;
}
/**
* Returns the signature for this request, for the given consumer
*/
protected function _getSignature($consumer)
{
$signer = new Zend_Oauth_Signature_Hmac($consumer->secret, null, 'sha1');
return $signer->sign($this->_getRequestParams(), Zend_Oauth::POST, $this->_getOAuthUrl());
}
/**
* Returns a consumser object for this key
* @return MyCourses_Model_OAuth_Consumer
*/
protected function _getConsumer($consumerKey)
{
// Get key
$table = OCAD_Db_Table::factory('MyCourses_Model_OAuth_Consumer_Table');
$select = $table->select()->where('id = ?', $consumerKey);
$consumer = $table->fetchRow($select);
if($consumer === NULL)
{
throw new OCAD_Exception('OAuth Consumer not found');
}
return $consumer;
}
/**
* URL used in signature
*/
protected function _getOAuthUrl()
{
return (($_SERVER['HTTPS'] === 'on') ? 'https://':'http://') . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
}
/**
* Params used in signature
*/
protected function _getRequestParams()
{
return array_merge($_GET, $_POST);
}
}
CREATE TABLE `oauth_consumers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`secret` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`timestamp` int(11) NOT NULL,
`nonces` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
<?php
class Dashboard_Model_OAuth_Consumer_Table extends OCAD_Db_Table
{
protected $_name = 'oauth_consumers';
protected $_primary = 'id';
protected $_rowClass = 'Dashboard_Model_OAuth_Consumer';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment