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