@ -1,2 +1,22 @@ | |||||
# Gear JWT | |||||
# Gear/Auth | |||||
```php | |||||
// routes that are ignored by auth | |||||
$routes = array( | |||||
'/', | |||||
); | |||||
$app->register('auth', 'Gear\Middleware\AuthMiddleware', array($routes)); | |||||
// adding jwtHelper | |||||
$options = array( | |||||
env('JWT_SECRET'), | |||||
env('JWT_URL'), | |||||
env('JWT_EXPIRED_AT'), | |||||
); | |||||
$app->register('jwtHelper', 'Gear\Helpers\JwtHelper', $options); | |||||
// adding filters | |||||
$app->before('start', array(new Gear\Filters\AuthFilter, 'before')); | |||||
``` |
@ -0,0 +1,17 @@ | |||||
{ | |||||
"name": "gear/auth", | |||||
"type": "libary", | |||||
"license": "MIT", | |||||
"authors": [ | |||||
{ "name": "Björn Hase", "email": "me@tentakelfabrik.de" } | |||||
], | |||||
"require": { | |||||
"php": "^7.0", | |||||
"firebase/php-jwt": "^5.0" | |||||
}, | |||||
"autoload": { | |||||
"psr-4": { | |||||
"Gear\\": "src/" | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,29 @@ | |||||
<?php | |||||
namespace Gear\Auth\Filters; | |||||
use Gear\FlightAbstract; | |||||
/** | |||||
* Filter for Auth | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/gear/gear-jwt | |||||
*/ | |||||
class AuthFilter extends FlightAbstract | |||||
{ | |||||
/** | |||||
* if result of auth is false halt app and set response to 403 | |||||
* | |||||
* | |||||
* @param array $params | |||||
* @param array $output | |||||
*/ | |||||
public function before(&$params, &$output) | |||||
{ | |||||
if (!$this->app->auth()->attempt()) { | |||||
$this->app->halt(403, 'Access Denied!'); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,67 @@ | |||||
<?php | |||||
namespace Gear\Auth; | |||||
use Firebase\JWT\JWT; | |||||
/** | |||||
* Wrapper for Firebase JWT | |||||
* | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/gear/gear-jwt | |||||
*/ | |||||
class Jwt | |||||
{ | |||||
/** | |||||
* | |||||
* @param string $secret | |||||
* @param string $url | |||||
* @param string $expiredAt | |||||
*/ | |||||
public function __construct($secret, $url, $expiredAt) | |||||
{ | |||||
$this->secret = $secret; | |||||
$this->url = $url; | |||||
$this->expiredAt = $expiredAt; | |||||
} | |||||
/** | |||||
* encode JWT, adding Data | |||||
* | |||||
* @param array $data | |||||
* @return object | |||||
*/ | |||||
public function encode($data = NULL) | |||||
{ | |||||
// current time | |||||
$time = time(); | |||||
// create token | |||||
$token = array( | |||||
'iss' => $this->url, | |||||
'iat' => $time, | |||||
'nbf' => $time, | |||||
'exp' => $time + $this->expiredAt | |||||
); | |||||
if ($data) { | |||||
$token['data'] = $data; | |||||
} | |||||
return JWT::encode($token, $this->secret); | |||||
} | |||||
/** | |||||
* decode JWT | |||||
* | |||||
* @param string $token | |||||
* @return array | |||||
*/ | |||||
public function decode($token) | |||||
{ | |||||
return JWT::decode($token, $this->secret, array('HS256')); | |||||
} | |||||
} |
@ -0,0 +1,16 @@ | |||||
<?php | |||||
namespace Gear\Auth\Middleware; | |||||
/** | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/gear/gear-jwt | |||||
*/ | |||||
interface AuthInterface | |||||
{ | |||||
public function check($token); | |||||
public function getUser(); | |||||
} |
@ -0,0 +1,75 @@ | |||||
<?php | |||||
namespace Gear\Auth\Middleware; | |||||
use Gear/FlightAbstract; | |||||
/** | |||||
* Abstract AuthMiddleware for Flight | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* @link https://gitlab.tentakelfabrik.de/gear/gear-jwt | |||||
*/ | |||||
abstract class AuthMiddlewareAbstract extends FlightAbstract implements AuthInterface | |||||
{ | |||||
/** routes that are allowed and have not to authenficate */ | |||||
protected $allowed = []; | |||||
/** result of attempt */ | |||||
protected $result = false; | |||||
/** | |||||
* | |||||
* | |||||
* @param array $allowed | |||||
*/ | |||||
public function __construct($allowed) | |||||
{ | |||||
parent::__construct(); | |||||
$this->allowed = $allowed; | |||||
} | |||||
/** | |||||
* attempt | |||||
* | |||||
* | |||||
* @return mixed | |||||
*/ | |||||
public function attempt() | |||||
{ | |||||
$match = NULL; | |||||
// search for pattern if route | |||||
foreach($this->app->router()->getRoutes() as $route) { | |||||
if ($route->matchUrl($this->app->request()->url)) { | |||||
$match = $route; | |||||
break; | |||||
} | |||||
} | |||||
// if pattern is not in the allowed, get HTTP_AUTHORIZATION and parse bearer-token | |||||
if (!in_array($match->pattern, $this->routes)) { | |||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) || isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { | |||||
if (isset($_SERVER['HTTP_AUTHORIZATION'])) { | |||||
$header = $_SERVER['HTTP_AUTHORIZATION']; | |||||
} | |||||
if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { | |||||
$header = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; | |||||
} | |||||
$token = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header)); | |||||
$this->check($token); | |||||
} | |||||
} | |||||
// if route not found, set $result to true | |||||
if (!$match) { | |||||
$this->result = true; | |||||
} | |||||
return $this->result; | |||||
} | |||||
} |