@ -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; | |||
} | |||
} |