From 2ed496a754b802ca40eb51231c6b16de908542c1 Mon Sep 17 00:00:00 2001 From: SparoHawk Date: Wed, 9 May 2018 11:26:29 -0400 Subject: [PATCH 1/2] Add option to allow ignoring domains, with HTTP methods --- README.md | 37 ++++++++--- src/Phalcon/Auth/Middleware/Micro.php | 94 ++++++++++++++++++++++----- 2 files changed, 106 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a66ecc3..7170a0d 100755 --- a/README.md +++ b/README.md @@ -51,6 +51,16 @@ ignoreUri[] = regex:/users/:POST,PUT ;; literal strings ignoreUri[] = /auth/user:POST,PUT ignoreUri[] = /auth/application + +; If you want to disable the middleware on certain domains: +;; regex pattern with http methods +ignoreDomain[] = regex:domain\.com +ignoreDomain[] = regex:api\.domain\.com +ignoreDomain[] = regex:.+\.domain\.com + +;; literal strings +ignoreDomain[] = domain.com +ignoreDomain[] = api.domain.com ``` in bootstrap or index file @@ -100,16 +110,23 @@ $app = new Micro($di); $authConfig = [ 'secretKey' => '923753F2317FC1EE5B52DF23951B1', 'payload' => [ - 'exp' => 1440, - 'iss' => 'phalcon-jwt-auth' - ], - 'ignoreUri' => [ - '/', - 'regex:/application/', - 'regex:/users/:POST,PUT', - '/auth/user:POST,PUT', - '/auth/application' - ] + 'exp' => 1440, + 'iss' => 'phalcon-jwt-auth' + ], + 'ignoreUri' => [ + '/', + 'regex:/application/', + 'regex:/users/:POST,PUT', + '/auth/user:POST,PUT', + '/auth/application' + ], + 'ignoreDomain' => [ + 'domain.com', + 'api.domain.com', + 'regex:domain\.com', + 'regex:api\.domain\.com', + 'regex:.+\.domain\.com' + ] ]; // AUTH MICRO diff --git a/src/Phalcon/Auth/Middleware/Micro.php b/src/Phalcon/Auth/Middleware/Micro.php index a6a840b..372f88c 100644 --- a/src/Phalcon/Auth/Middleware/Micro.php +++ b/src/Phalcon/Auth/Middleware/Micro.php @@ -31,6 +31,9 @@ class Micro // ignored urls protected $ignoreUri; + // ignored domains + protected $ignoreDomain; + // JWT secret key protected $secretKey; @@ -57,12 +60,16 @@ public function __construct(MvcMicro $app, array $config=NULL) * [jwtAuth] * secretKey = nSrL7k4/7NcW|AN * payload[exp] = 120 - * payload[iss] = phalcon-jwt-auth - * payload[sub] = 123 - * payload[name] = John Doe - * payload[role] = admin + * payload[iss] = phalcon-jwt-auth + * payload[sub] = 123 + * payload[name] = John Doe + * payload[role] = admin * ignoreUri[] = regex:/register/:POST * ignoreUri[] = /register + * ignoreDomain[] = regex:api\.domain\.com:POST + * ignoreDomain[] = api.domain.com:POST,GET + * ignoreDomain[] = regex:api\.domain\.com + * ignoreDomain[] = api.domain.com */ if(!$config && !$app->getDI()->has(self::$configDi)) { @@ -76,13 +83,17 @@ public function __construct(MvcMicro $app, array $config=NULL) $this->config = $config ?? $app[self::$configDi]->{self::$configSection}; if( !is_array($this->config) ) { - $this->config = (array) $this->config; + $this->config = (array) $this->config; } if(isset($this->config['ignoreUri'])) { $this->ignoreUri = $this->config['ignoreUri']; } + if(isset($this->config['ignoreDomain'])) { + $this->ignoreDomain = $this->config['ignoreDomain']; + } + // secret key is required if(!isset($this->config['secretKey'])) { throw new \InvalidArgumentException('missing jwt secret key'); @@ -136,29 +147,28 @@ protected function setEventChecker() $eventsManager = $this->app->getEventsManager() ?? new EventsManager(); $eventsManager->attach( - "micro:beforeExecuteRoute", - function (Event $event, $app) use($diName) { + 'micro:beforeExecuteRoute', + function (Event $event, $app) use ($diName) { $auth = $app[$diName]; - // check if it has CORS support + // Check if it has CORS support if ($auth->isIgnoreOptionsMethod() && $app['request']->getMethod() == 'OPTIONS') { return true; } - if($auth->isIgnoreUri()) { + if ($auth->isIgnoreUri() || $auth->isIgnoreDomain()) { /** * Let's try to parse if there's a token * but we don't want to get an invalid token */ - if( !$auth->check() && $this->getMessages()[0] != 'missing token') - { + if (!$auth->check() && $this->getMessages()[0] != 'missing token') { return $auth->unauthorized(); } return true; } - if($auth->check()) { + if ($auth->check()) { return true; } @@ -191,7 +201,38 @@ protected function hasMatchIgnoreUri($requestUri, $requestMethod) $methods = ( !$methods || empty($methods) ? false : explode(',', $methods) ); $match = ( $type == 'str' ? $requestUri == $pattern : preg_match("#{$pattern}#", $requestUri) ); - if( $match && (!$methods || in_array($requestMethod, $methods)) ) { + if ($match && (!$methods || in_array($requestMethod, $methods))) { + return true; + } + } + + return false; + } + + /** + * Checks if the domain has a match in the passed self::$ignoreDomain. + * + * @param string $requestDomain + * @param string $requestMethod HTTP METHODS + * + * @return bool + */ + protected function hasMatchIgnoreDomains($requestDomain, $requestMethod) + { + foreach($this->ignoreDomain as $domain) { + if(strpos($domain, 'regex:') === false) { + $type = 'str'; + } else { + $type = 'regex'; + $domain = str_replace('regex:', '', $domain); + } + + list($pattern, $methods) = (strpos($domain, ':') === false ? [$domain, false] : explode(':', $domain )); + $methods = (!$methods || empty($methods) ? false : explode(',', $methods)); + + $match = ($type == 'str' ? $requestDomain == $pattern : preg_match("#{$pattern}#", $requestDomain)); + + if ($match && (!$methods || in_array($requestMethod, $methods))) { return true; } } @@ -222,6 +263,29 @@ public function isIgnoreUri() return $this->hasMatchIgnoreUri($uri, $method); } + /** + * Checks if the SERVER NAME (domain) can bypass the authentication. + * + * @return bool + */ + public function isIgnoreDomain() + { + if (!$this->ignoreDomain) { + return false; + } + + // access request object + $request = $this->app['request']; + + // http method + $method = $request->getMethod(); + + // server name + $domain = $request->getServerName(); + + return $this->hasMatchIgnoreDomains($domain, $method); + } + /** * Authenticates. * @@ -250,7 +314,7 @@ public function make($data) * * @param callable $callback */ - public function onCheck($callback) + public function onCheck($callback) { $this->auth->onCheck($callback); } @@ -299,7 +363,7 @@ public function unauthorized() { */ public function getMessages() { - return $this->auth->getMessages(); + return $this->auth->getMessages(); } /** From b634b97078bee71a222f8670fde40936af633299 Mon Sep 17 00:00:00 2001 From: Esteban De la Rosa Date: Wed, 9 May 2018 11:59:32 -0400 Subject: [PATCH 2/2] Fix method to get the request domain Change "getServerName" to "getHttpHost" in order to get the full domain of the request. --- src/Phalcon/Auth/Middleware/Micro.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Phalcon/Auth/Middleware/Micro.php b/src/Phalcon/Auth/Middleware/Micro.php index 372f88c..32b8027 100644 --- a/src/Phalcon/Auth/Middleware/Micro.php +++ b/src/Phalcon/Auth/Middleware/Micro.php @@ -264,7 +264,7 @@ public function isIgnoreUri() } /** - * Checks if the SERVER NAME (domain) can bypass the authentication. + * Checks if the HTTP HOST (domain) can bypass the authentication. * * @return bool */ @@ -280,8 +280,8 @@ public function isIgnoreDomain() // http method $method = $request->getMethod(); - // server name - $domain = $request->getServerName(); + // http host + $domain = $request->getHttpHost(); return $this->hasMatchIgnoreDomains($domain, $method); }