Skip to content

Commit

Permalink
Merge pull request #25 from hkulekci/feature/oauth
Browse files Browse the repository at this point in the history
OAuth Implementation For Rest APIs
  • Loading branch information
hkulekci committed Dec 5, 2015
2 parents d8498fa + 9096bf1 commit 85b9356
Show file tree
Hide file tree
Showing 15 changed files with 487 additions and 16 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"zfcampus/zf-content-validation": "~1.0",
"zfcampus/zf-hal": "~1.0",
"zfcampus/zf-mvc-auth": "~1.0",
"zfcampus/zf-rest": "~1.0"
"zfcampus/zf-rest": "~1.0",
"predis/predis": "1.0.3"
},

"require-dev": {
Expand Down
9 changes: 9 additions & 0 deletions config/autoload/auth.local.php.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
/**
* Auth Configuration
*/

return [
'zf-oauth2' => [
],
];
91 changes: 91 additions & 0 deletions module/Api/Module.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?php
namespace Api;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use ZF\ApiProblem\ApiProblem;
use ZF\ApiProblem\ApiProblemResponse;
use ZF\MvcAuth\MvcAuthEvent;

class Module
{
public function getConfig()
Expand All @@ -18,4 +24,89 @@ public function getAutoloaderConfig()
),
);
}

public function onBootstrap(MvcEvent $event)
{
$eventManager = $event->getApplication()->getEventManager();

$eventManager->attach(
MvcAuthEvent::EVENT_AUTHENTICATION_POST,
array($this, 'eventAuthenticationPost'),
900
);

$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);

$event->getApplication()->getEventManager()->attach(
MvcEvent::EVENT_DISPATCH_ERROR,
array($this, 'dispatchError'),
9000
);
}

public function eventAuthenticationPost(MvcAuthEvent $event)
{
// Manupilating Identity Data
$identity = $event->getIdentity();
$oauth2Closure = $event->getMvcEvent()
->getApplication()
->getServiceManager()
->get(\ZF\OAuth2\Service\OAuth2Server::class);

if (!!$identity) {
if ($identity instanceof \ZF\MvcAuth\Identity\AuthenticatedIdentity) {
$userData = $oauth2Closure()->getStorage('user_credentials')->getUser($identity->getName());
if (is_array($identity->getAuthenticationIdentity())) {
$userData = array_merge($userData, $identity->getAuthenticationIdentity());
}
$identity = new \ZF\MvcAuth\Identity\AuthenticatedIdentity($userData);
$event->setIdentity($identity);
}
//MvcEvent did not understand when manipulated MvcAuthEvent identity
$event->getMvcEvent()->setParam('ZF\MvcAuth\Identity', $identity);
}

return $event;
}

public function dispatchError(MvcEvent $event)
{
$problem = null;
if ($event->isError()) {
$exception = $event->getParam("exception");

// There are some other errors like that :
// "error-controller-cannot-dispatch",
// "error-controller-invalid",
// "error-controller-not-found",
// "error-router-no-match",
if ($event->getError() === 'error-controller-not-found') {
$problem = new ApiProblem(404, "Endpoint controller not found!");
} elseif ($event->getError() === 'error-router-no-match') {
$problem = new ApiProblem(404, "Not found!");
} elseif ($exception instanceof \Exception) {
$className = explode('\\', get_class($exception));
$problem = new ApiProblem($exception->getCode(), end($className) . ' error.');

if ($event->getTarget() instanceof ServiceLocatorAwareInterface) {
$logger = $event->getTarget()->getServiceLocator()->get('logger');
} else {
$logger = $event->getTarget()->getServiceManager()->get('logger');
}

$logger = $event->getTarget()->getServiceManager()->get('logger');
$logger->err($exception->getMessage(), array(
'controller' => $event->getControllerClass(),
));
}
} else {
$problem = new ApiProblem(500, "Unknown Error!");
}

$response = new ApiProblemResponse($problem);
$event->stopPropagation();

return $response;
}
}
96 changes: 87 additions & 9 deletions module/Api/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
return [
'service_manager' => [
'factories' => [
'Api\V1\User\UserResource' => 'Api\V1\User\UserResourceFactory',
Api\V1\User\UserResource::class => Api\V1\User\UserResourceFactory::class,
Api\OAuth\Storage\Adapter\Redis::class => Api\OAuth\Storage\Adapter\RedisFactory::class,
Api\OAuth\Storage\Adapter\Pdo::class => Api\OAuth\Storage\Adapter\PdoFactory::class,
ZF\OAuth2\Service\OAuth2Server::class => ZF\MvcAuth\Factory\NamedOAuth2ServerFactory::class,
],
],
'router' => array(
Expand All @@ -15,7 +18,36 @@
'controller' => 'Api\V1\User\Controller',
),
),
),
), // end of api.rest.user
'oauth' => array(
'options' => array(
'route' => '/oauth',
),
'type' => 'Segment', // regex type will be remove.
'child_routes' => array(
'token' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/token',
'defaults' => array(
'action' => 'token',
),
),
),
'resource' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '',
),
),
'code' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '',
),
),
)
), // end of oauth
),
),
'zf-versioning' => array(
Expand All @@ -25,7 +57,7 @@
),
'zf-rest' => array(
'Api\V1\User\Controller' => array(
'listener' => 'Api\V1\User\UserResource',
'listener' => Api\V1\User\UserResource::class,
'route_name' => 'api.rest.user',
'route_identifier_name' => 'user_id',
'collection_name' => 'user',
Expand All @@ -38,8 +70,8 @@
'collection_query_whitelist' => array(),
'page_size' => 25,
'page_size_param' => null,
'entity_class' => 'Api\V1\User\UserEntity',
'collection_class' => 'Api\V1\User\UserCollection',
'entity_class' => Api\V1\User\UserEntity::class,
'collection_class' => Api\V1\User\UserCollection::class,
'service_name' => 'User',
),
),
Expand Down Expand Up @@ -67,7 +99,7 @@
'entity_identifier_name' => 'id',
'route_name' => 'api.rest.user',
'route_identifier_name' => 'user_id',
'hydrator' => 'Zend\Stdlib\Hydrator\ObjectProperty',
'hydrator' => Zend\Stdlib\Hydrator\ObjectProperty::class,
),
'Api\V1\User\UserCollection' => array(
'entity_identifier_name' => 'id',
Expand All @@ -87,8 +119,54 @@

),
),
'zf-mvc-auth' => array(
'authorization' => array(
'zf-mvc-auth' => [
'authorization' => [
'deny_by_default' => true,
'ZF\OAuth2\Controller\Auth' => [
'actions' => [
'token' => [
'POST' => false,
],
'authorize' => [
'GET' => false,
'POST' => false,
],
],
],
],
'authentication' => [
'adapters' => [
'zingatOAuth2' => [
'adapter' => ZF\MvcAuth\Authentication\OAuth2Adapter::class,
'storage' => []
],
],
'map' => [
'Api\V1' => 'zingatOAuth2',
],
'access_lifetime' => 7200,
],
],
'zf-oauth2' => [
'storage' => [
'client_credentials' => \Api\OAuth\Storage\Adapter\Pdo::class,
'user_credentials' => \Api\OAuth\Storage\Adapter\Pdo::class,
'access_token' => \Api\OAuth\Storage\Adapter\Redis::class,
'scope' => \Api\OAuth\Storage\Adapter\Pdo::class,
'authorization_code' => \Api\OAuth\Storage\Adapter\Redis::class,
'refresh_token' => \Api\OAuth\Storage\Adapter\Redis::class,
],
'grant_types' => [
'client_credentials' => true, // Default Value
'authorization_code' => true, // Default Value
'password' => true, // Default Value
'refresh_token' => true, // Default Value
'jwt' => false,
],
'allow_implicit' => false,
'options' => array(
'always_issue_new_refresh_token' => true,
),
),
'access_lifetime' => 7200,
],
];
13 changes: 13 additions & 0 deletions module/Api/src/Api/Exception/ApplicationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* Application Exception
*
* @since Nov 2015
* @author Haydar KULEKCI <[email protected]>
*/
namespace Api\Exception;

class ApplicationException extends \Exception
{
// Maybe in future, in here, we should create some static factory methods
}
13 changes: 13 additions & 0 deletions module/Api/src/Api/Exception/AuthException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* OAuth Exception
*
* @since Nov 2015
* @author Haydar KULEKCI <[email protected]>
*/
namespace Api\Exception;

class AuthException extends \Exception
{
// Maybe in future, in here, we should create some static factory methods
}
13 changes: 13 additions & 0 deletions module/Api/src/Api/Exception/CacheException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* Cache Exception
*
* @since Nov 2015
* @author Haydar KULEKCI <[email protected]>
*/
namespace Api\Exception;

class CacheException extends \Exception
{
// Maybe in future, in here, we should create some static factory methods
}
13 changes: 13 additions & 0 deletions module/Api/src/Api/Exception/DatabaseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
/**
* Database Exception
*
* @since Nov 2015
* @author Haydar KULEKCI <[email protected]>
*/
namespace Api\Exception;

class DatabaseException extends \Exception
{
// Maybe in future, in here, we should create some static factory methods
}
Loading

0 comments on commit 85b9356

Please sign in to comment.