Last active
December 16, 2015 20:49
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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