From a40067ca554d6c7ee9454ca0b30868e6d59e8488 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Wed, 21 Jan 2015 17:20:04 -0500 Subject: [PATCH] Moved REST authorization boilerplate to Zend Acl_plugin --- .../controllers/plugins/Acl_plugin.php | 54 ++++++++- .../rest/controllers/MediaController.php | 105 ------------------ 2 files changed, 50 insertions(+), 109 deletions(-) diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php index 32ddb157d..1918430ea 100644 --- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php +++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php @@ -110,12 +110,17 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract { $controller = strtolower($request->getControllerName()); Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance()); - - //Ignore authentication for all access to the rest API. We do auth via API keys for this - //and/or by OAuth. + if (in_array($controller, array("api", "auth", "locale", "upgrade"))) { $this->setRoleName("G"); } elseif (!Zend_Auth::getInstance()->hasIdentity()) { + + // If we don't have an identity and we're making a RESTful request, + // we need to do API key verification + if ($request->getModuleName() == "rest") { + $this->verifyAuth(); + return; + } if ($controller !== 'login') { @@ -138,7 +143,12 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract } } } else { - + // If we have an identity and we're making a RESTful request, + // we need to check the CSRF token + if ($request->_action != "get" && $request->getModuleName() == "rest") { + $this->verifyCSRFToken($request->getParam("csrf_token")); + } + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); $this->setRoleName($userInfo->type); @@ -164,6 +174,42 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract } } + private function verifyAuth() { + if ($this->verifyAPIKey()) { + return true; + } + + $this->getResponse() + ->setHttpResponseCode(401) + ->appendBody("ERROR: Incorrect API key."); + return false; + } + + private function verifyCSRFToken($token) { + $current_namespace = new Zend_Session_Namespace('csrf_namespace'); + $observed_csrf_token = $token; + $expected_csrf_token = $current_namespace->authtoken; + + $this->getResponse() + ->setHttpResponseCode(401) + ->appendBody("ERROR: CSRF token mismatch."); + + return ($observed_csrf_token == $expected_csrf_token); + } + + private function verifyAPIKey() { + // The API key is passed in via HTTP "basic authentication": + // http://en.wikipedia.org/wiki/Basic_access_authentication + $CC_CONFIG = Config::getConfig(); + + // Decode the API key that was passed to us in the HTTP request. + $authHeader = $this->getRequest()->getHeader("Authorization"); + $encodedRequestApiKey = substr($authHeader, strlen("Basic ")); + $encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":"); + + return ($encodedRequestApiKey === $encodedStoredApiKey); + } + /** * Deny Access Function * Redirects to errorPage, this can be called from an action using the action helper diff --git a/airtime_mvc/application/modules/rest/controllers/MediaController.php b/airtime_mvc/application/modules/rest/controllers/MediaController.php index 232ac3529..a5ee08fd9 100644 --- a/airtime_mvc/application/modules/rest/controllers/MediaController.php +++ b/airtime_mvc/application/modules/rest/controllers/MediaController.php @@ -30,11 +30,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function indexAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - $files_array = array(); foreach (CcFilesQuery::create()->find() as $file) { @@ -54,11 +49,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function downloadAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - $id = $this->getId(); if (!$id) { return; @@ -80,11 +70,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function getAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - $id = $this->getId(); if (!$id) { return; @@ -103,11 +88,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function postAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - //If we do get an ID on a POST, then that doesn't make any sense //since POST is only for creating. if ($id = $this->_getParam('id', false)) { @@ -168,11 +148,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function putAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - $id = $this->getId(); if (!$id) { return; @@ -236,11 +211,6 @@ class Rest_MediaController extends Zend_Rest_Controller public function deleteAction() { - if (!$this->verifyAuth(true, true)) - { - return; - } - $id = $this->getId(); if (!$id) { return; @@ -271,81 +241,6 @@ class Rest_MediaController extends Zend_Rest_Controller return $id; } - private function verifyAuth($checkApiKey, $checkSession) - { - // Session takes precedence over API key for now: - if ($checkSession && $this->verifySession()) { - // CSRF token validation only applies to session based authorization. - if(!$this->verifyCSRFToken($this->_getParam('csrf_token'))){ - $resp = $this->getResponse(); - $resp->setHttpResponseCode(401); - $resp->appendBody("ERROR: Token Missmatch."); - return false; - } - return true; - } - - if ($checkApiKey && $this->verifyAPIKey()) - { - return true; - } - - $resp = $this->getResponse(); - $resp->setHttpResponseCode(401); - $resp->appendBody("ERROR: Incorrect API key."); - - return false; - } - - private function verifyCSRFToken($token){ - $current_namespace = new Zend_Session_Namespace('csrf_namespace'); - $observed_csrf_token = $token; - $expected_csrf_token = $current_namespace->authtoken; - - if($observed_csrf_token == $expected_csrf_token){ - return true; - }else{ - return false; - } - } - - private function verifyAPIKey() - { - //The API key is passed in via HTTP "basic authentication": - // http://en.wikipedia.org/wiki/Basic_access_authentication - - $CC_CONFIG = Config::getConfig(); - - //Decode the API key that was passed to us in the HTTP request. - $authHeader = $this->getRequest()->getHeader("Authorization"); - $encodedRequestApiKey = substr($authHeader, strlen("Basic ")); - $encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":"); - - if ($encodedRequestApiKey === $encodedStoredApiKey) - { - return true; - } else { - return false; - } - - return false; - } - - private function verifySession() - { - $auth = Zend_Auth::getInstance(); - if ($auth->hasIdentity()) - { - return true; - } - return false; - - //Token checking stub code. We'd need to change LoginController.php to generate a token too, but - //but luckily all the token code already exists and works. - //$auth = new Application_Model_Auth(); - //$auth->checkToken(Application_Model_Preference::getUserId(), $token); - } - private function fileNotFoundResponse() { $resp = $this->getResponse();