One Hat Cyber Team
Your IP:
216.73.216.102
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
home
/
fluxyjvi
/
www
/
assets
/
images
/
Edit File:
jwt-auth.tar
src/Contracts/Providers/Auth.php 0000644 00000001312 15105647717 0012674 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts\Providers; interface Auth { /** * Check a user's credentials. * * @param array $credentials * @return mixed */ public function byCredentials(array $credentials); /** * Authenticate a user via the id. * * @param mixed $id * @return mixed */ public function byId($id); /** * Get the currently authenticated user. * * @return mixed */ public function user(); } src/Contracts/Providers/JWT.php 0000644 00000000766 15105647717 0012453 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts\Providers; interface JWT { /** * @param array $payload * @return string */ public function encode(array $payload); /** * @param string $token * @return array */ public function decode($token); } src/Contracts/Providers/Storage.php 0000644 00000001534 15105647717 0013405 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts\Providers; interface Storage { /** * @param string $key * @param mixed $value * @param int $minutes * @return void */ public function add($key, $value, $minutes); /** * @param string $key * @param mixed $value * @return void */ public function forever($key, $value); /** * @param string $key * @return mixed */ public function get($key); /** * @param string $key * @return bool */ public function destroy($key); /** * @return void */ public function flush(); } src/Contracts/JWTSubject.php 0000644 00000001152 15105647717 0012004 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts; interface JWTSubject { /** * Get the identifier that will be stored in the subject claim of the JWT. * * @return mixed */ public function getJWTIdentifier(); /** * Return a key value array, containing any custom claims to be added to the JWT. * * @return array */ public function getJWTCustomClaims(); } src/Contracts/Validator.php 0000644 00000001107 15105647720 0011737 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts; interface Validator { /** * Perform some checks on the value. * * @param mixed $value * @return void */ public function check($value); /** * Helper function to return a boolean. * * @param array $value * @return bool */ public function isValid($value); } src/Contracts/Claim.php 0000644 00000001762 15105647720 0011046 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts; interface Claim { /** * Set the claim value, and call a validate method. * * @param mixed $value * @return $this * * @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException */ public function setValue($value); /** * Get the claim value. * * @return mixed */ public function getValue(); /** * Set the claim name. * * @param string $name * @return $this */ public function setName($name); /** * Get the claim name. * * @return string */ public function getName(); /** * Validate the Claim value. * * @param mixed $value * @return bool */ public function validateCreate($value); } src/Contracts/Http/Parser.php 0000644 00000000744 15105647720 0012173 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Contracts\Http; use Illuminate\Http\Request; interface Parser { /** * Parse the request. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request); } src/Console/JWTGenerateSecretCommand.php 0000644 00000006140 15105647720 0014242 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Console; use Illuminate\Console\Command; use Illuminate\Support\Str; class JWTGenerateSecretCommand extends Command { /** * The console command signature. * * @var string */ protected $signature = 'jwt:secret {--s|show : Display the key instead of modifying files.} {--always-no : Skip generating key if it already exists.} {--f|force : Skip confirmation when overwriting an existing key.}'; /** * The console command description. * * @var string */ protected $description = 'Set the JWTAuth secret key used to sign the tokens'; /** * Execute the console command. * * @return void */ public function handle() { $key = Str::random(64); if ($this->option('show')) { $this->comment($key); return; } if (file_exists($path = $this->envPath()) === false) { return $this->displayKey($key); } if (Str::contains(file_get_contents($path), 'JWT_SECRET') === false) { // create new entry file_put_contents($path, PHP_EOL."JWT_SECRET=$key".PHP_EOL, FILE_APPEND); } else { if ($this->option('always-no')) { $this->comment('Secret key already exists. Skipping...'); return; } if ($this->isConfirmed() === false) { $this->comment('Phew... No changes were made to your secret key.'); return; } // update existing entry file_put_contents($path, str_replace( 'JWT_SECRET='.$this->laravel['config']['jwt.secret'], 'JWT_SECRET='.$key, file_get_contents($path) )); } $this->displayKey($key); } /** * Display the key. * * @param string $key * @return void */ protected function displayKey($key) { $this->laravel['config']['jwt.secret'] = $key; $this->info("jwt-auth secret [$key] set successfully."); } /** * Check if the modification is confirmed. * * @return bool */ protected function isConfirmed() { return $this->option('force') ? true : $this->confirm( 'This will invalidate all existing tokens. Are you sure you want to override the secret key?' ); } /** * Get the .env file path. * * @return string */ protected function envPath() { if (method_exists($this->laravel, 'environmentFilePath')) { return $this->laravel->environmentFilePath(); } // check if laravel version Less than 5.4.17 if (version_compare($this->laravel->version(), '5.4.17', '<')) { return $this->laravel->basePath().DIRECTORY_SEPARATOR.'.env'; } return $this->laravel->basePath('.env'); } } src/Exceptions/TokenInvalidException.php 0000644 00000000476 15105647720 0014451 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; class TokenInvalidException extends JWTException { // } src/Exceptions/InvalidClaimException.php 0000644 00000001351 15105647721 0014410 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; use Exception; use Tymon\JWTAuth\Claims\Claim; class InvalidClaimException extends JWTException { /** * Constructor. * * @param \Tymon\JWTAuth\Claims\Claim $claim * @param int $code * @param \Exception|null $previous * @return void */ public function __construct(Claim $claim, $code = 0, Exception $previous = null) { parent::__construct('Invalid value provided for claim ['.$claim->getName().']', $code, $previous); } } src/Exceptions/TokenBlacklistedException.php 0000644 00000000513 15105647721 0015275 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; class TokenBlacklistedException extends TokenInvalidException { // } src/Exceptions/UserNotDefinedException.php 0000644 00000000500 15105647721 0014725 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; class UserNotDefinedException extends JWTException { // } src/Exceptions/JWTException.php 0000644 00000000616 15105647721 0012523 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; use Exception; class JWTException extends Exception { /** * {@inheritdoc} */ protected $message = 'An error occurred'; } src/Exceptions/PayloadException.php 0000644 00000000471 15105647721 0013447 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; class PayloadException extends JWTException { // } src/Exceptions/TokenExpiredException.php 0000644 00000000476 15105647722 0014465 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Exceptions; class TokenExpiredException extends JWTException { // } src/Providers/AbstractServiceProvider.php 0000644 00000024123 15105647722 0014633 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers; use Illuminate\Support\ServiceProvider; use Namshi\JOSE\JWS; use Tymon\JWTAuth\Blacklist; use Tymon\JWTAuth\Claims\Factory as ClaimFactory; use Tymon\JWTAuth\Console\JWTGenerateSecretCommand; use Tymon\JWTAuth\Contracts\Providers\Auth; use Tymon\JWTAuth\Contracts\Providers\JWT as JWTContract; use Tymon\JWTAuth\Contracts\Providers\Storage; use Tymon\JWTAuth\Factory; use Tymon\JWTAuth\Http\Middleware\Authenticate; use Tymon\JWTAuth\Http\Middleware\AuthenticateAndRenew; use Tymon\JWTAuth\Http\Middleware\Check; use Tymon\JWTAuth\Http\Middleware\RefreshToken; use Tymon\JWTAuth\Http\Parser\AuthHeaders; use Tymon\JWTAuth\Http\Parser\InputSource; use Tymon\JWTAuth\Http\Parser\Parser; use Tymon\JWTAuth\Http\Parser\QueryString; use Tymon\JWTAuth\JWT; use Tymon\JWTAuth\JWTAuth; use Tymon\JWTAuth\JWTGuard; use Tymon\JWTAuth\Manager; use Tymon\JWTAuth\Providers\JWT\Lcobucci; use Tymon\JWTAuth\Providers\JWT\Namshi; use Tymon\JWTAuth\Validators\PayloadValidator; abstract class AbstractServiceProvider extends ServiceProvider { /** * The middleware aliases. * * @var array */ protected $middlewareAliases = [ 'jwt.auth' => Authenticate::class, 'jwt.check' => Check::class, 'jwt.refresh' => RefreshToken::class, 'jwt.renew' => AuthenticateAndRenew::class, ]; /** * Boot the service provider. * * @return void */ abstract public function boot(); /** * Register the service provider. * * @return void */ public function register() { $this->registerAliases(); $this->registerJWTProvider(); $this->registerAuthProvider(); $this->registerStorageProvider(); $this->registerJWTBlacklist(); $this->registerManager(); $this->registerTokenParser(); $this->registerJWT(); $this->registerJWTAuth(); $this->registerPayloadValidator(); $this->registerClaimFactory(); $this->registerPayloadFactory(); $this->registerJWTCommand(); $this->commands('tymon.jwt.secret'); } /** * Extend Laravel's Auth. * * @return void */ protected function extendAuthGuard() { $this->app['auth']->extend('jwt', function ($app, $name, array $config) { $guard = new JWTGuard( $app['tymon.jwt'], $app['auth']->createUserProvider($config['provider']), $app['request'] ); $app->refresh('request', $guard, 'setRequest'); return $guard; }); } /** * Bind some aliases. * * @return void */ protected function registerAliases() { $this->app->alias('tymon.jwt', JWT::class); $this->app->alias('tymon.jwt.auth', JWTAuth::class); $this->app->alias('tymon.jwt.provider.jwt', JWTContract::class); $this->app->alias('tymon.jwt.provider.jwt.namshi', Namshi::class); $this->app->alias('tymon.jwt.provider.jwt.lcobucci', Lcobucci::class); $this->app->alias('tymon.jwt.provider.auth', Auth::class); $this->app->alias('tymon.jwt.provider.storage', Storage::class); $this->app->alias('tymon.jwt.manager', Manager::class); $this->app->alias('tymon.jwt.blacklist', Blacklist::class); $this->app->alias('tymon.jwt.payload.factory', Factory::class); $this->app->alias('tymon.jwt.validators.payload', PayloadValidator::class); } /** * Register the bindings for the JSON Web Token provider. * * @return void */ protected function registerJWTProvider() { $this->registerNamshiProvider(); $this->registerLcobucciProvider(); $this->app->singleton('tymon.jwt.provider.jwt', function ($app) { return $this->getConfigInstance('providers.jwt'); }); } /** * Register the bindings for the Lcobucci JWT provider. * * @return void */ protected function registerNamshiProvider() { $this->app->singleton('tymon.jwt.provider.jwt.namshi', function ($app) { return new Namshi( new JWS(['typ' => 'JWT', 'alg' => $this->config('algo')]), $this->config('secret'), $this->config('algo'), $this->config('keys') ); }); } /** * Register the bindings for the Lcobucci JWT provider. * * @return void */ protected function registerLcobucciProvider() { $this->app->singleton('tymon.jwt.provider.jwt.lcobucci', function ($app) { return new Lcobucci( $this->config('secret'), $this->config('algo'), $this->config('keys') ); }); } /** * Register the bindings for the Auth provider. * * @return void */ protected function registerAuthProvider() { $this->app->singleton('tymon.jwt.provider.auth', function () { return $this->getConfigInstance('providers.auth'); }); } /** * Register the bindings for the Storage provider. * * @return void */ protected function registerStorageProvider() { $this->app->singleton('tymon.jwt.provider.storage', function () { return $this->getConfigInstance('providers.storage'); }); } /** * Register the bindings for the JWT Manager. * * @return void */ protected function registerManager() { $this->app->singleton('tymon.jwt.manager', function ($app) { $instance = new Manager( $app['tymon.jwt.provider.jwt'], $app['tymon.jwt.blacklist'], $app['tymon.jwt.payload.factory'] ); return $instance->setBlacklistEnabled((bool) $this->config('blacklist_enabled')) ->setPersistentClaims($this->config('persistent_claims')); }); } /** * Register the bindings for the Token Parser. * * @return void */ protected function registerTokenParser() { $this->app->singleton('tymon.jwt.parser', function ($app) { $parser = new Parser( $app['request'], [ new AuthHeaders, new QueryString, new InputSource, ] ); $app->refresh('request', $parser, 'setRequest'); return $parser; }); } /** * Register the bindings for the main JWT class. * * @return void */ protected function registerJWT() { $this->app->singleton('tymon.jwt', function ($app) { return (new JWT( $app['tymon.jwt.manager'], $app['tymon.jwt.parser'] ))->lockSubject($this->config('lock_subject')); }); } /** * Register the bindings for the main JWTAuth class. * * @return void */ protected function registerJWTAuth() { $this->app->singleton('tymon.jwt.auth', function ($app) { return (new JWTAuth( $app['tymon.jwt.manager'], $app['tymon.jwt.provider.auth'], $app['tymon.jwt.parser'] ))->lockSubject($this->config('lock_subject')); }); } /** * Register the bindings for the Blacklist. * * @return void */ protected function registerJWTBlacklist() { $this->app->singleton('tymon.jwt.blacklist', function ($app) { $instance = new Blacklist($app['tymon.jwt.provider.storage']); return $instance->setGracePeriod($this->config('blacklist_grace_period')) ->setRefreshTTL($this->config('refresh_ttl')); }); } /** * Register the bindings for the payload validator. * * @return void */ protected function registerPayloadValidator() { $this->app->singleton('tymon.jwt.validators.payload', function () { return (new PayloadValidator) ->setRefreshTTL($this->config('refresh_ttl')) ->setRequiredClaims($this->config('required_claims')); }); } /** * Register the bindings for the Claim Factory. * * @return void */ protected function registerClaimFactory() { $this->app->singleton('tymon.jwt.claim.factory', function ($app) { $factory = new ClaimFactory($app['request']); $app->refresh('request', $factory, 'setRequest'); return $factory->setTTL($this->config('ttl')) ->setLeeway($this->config('leeway')); }); } /** * Register the bindings for the Payload Factory. * * @return void */ protected function registerPayloadFactory() { $this->app->singleton('tymon.jwt.payload.factory', function ($app) { return new Factory( $app['tymon.jwt.claim.factory'], $app['tymon.jwt.validators.payload'] ); }); } /** * Register the Artisan command. * * @return void */ protected function registerJWTCommand() { $this->app->singleton('tymon.jwt.secret', function () { return new JWTGenerateSecretCommand; }); } /** * Helper to get the config values. * * @param string $key * @param string $default * @return mixed */ protected function config($key, $default = null) { return config("jwt.$key", $default); } /** * Get an instantiable configuration instance. * * @param string $key * @return mixed */ protected function getConfigInstance($key) { $instance = $this->config($key); if (is_string($instance)) { return $this->app->make($instance); } return $instance; } } src/Providers/LumenServiceProvider.php 0000644 00000001375 15105647722 0014154 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers; use Tymon\JWTAuth\Http\Parser\LumenRouteParams; class LumenServiceProvider extends AbstractServiceProvider { /** * {@inheritdoc} */ public function boot() { $this->app->configure('jwt'); $path = realpath(__DIR__.'/../../config/config.php'); $this->mergeConfigFrom($path, 'jwt'); $this->app->routeMiddleware($this->middlewareAliases); $this->extendAuthGuard(); $this->app['tymon.jwt.parser']->addParser(new LumenRouteParams); } } src/Providers/JWT/Provider.php 0000644 00000007207 15105647722 0012276 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers\JWT; use Illuminate\Support\Arr; abstract class Provider { const ALGO_HS256 = 'HS256'; const ALGO_HS384 = 'HS384'; const ALGO_HS512 = 'HS512'; const ALGO_RS256 = 'RS256'; const ALGO_RS384 = 'RS384'; const ALGO_RS512 = 'RS512'; const ALGO_ES256 = 'ES256'; const ALGO_ES384 = 'ES384'; const ALGO_ES512 = 'ES512'; /** * The secret. * * @var string */ protected $secret; /** * The array of keys. * * @var array */ protected $keys; /** * The used algorithm. * * @var string */ protected $algo; /** * Constructor. * * @param string $secret * @param string $algo * @param array $keys * @return void */ public function __construct($secret, $algo, array $keys) { $this->secret = $secret; $this->algo = $algo; $this->keys = $keys; } /** * Set the algorithm used to sign the token. * * @param string $algo * @return $this */ public function setAlgo($algo) { $this->algo = $algo; return $this; } /** * Get the algorithm used to sign the token. * * @return string */ public function getAlgo() { return $this->algo; } /** * Set the secret used to sign the token. * * @param string $secret * @return $this */ public function setSecret($secret) { $this->secret = $secret; return $this; } /** * Get the secret used to sign the token. * * @return string */ public function getSecret() { return $this->secret; } /** * Set the keys used to sign the token. * * @param array $keys * @return $this */ public function setKeys(array $keys) { $this->keys = $keys; return $this; } /** * Get the array of keys used to sign tokens with an asymmetric algorithm. * * @return array */ public function getKeys() { return $this->keys; } /** * Get the public key used to sign tokens with an asymmetric algorithm. * * @return string|null */ public function getPublicKey() { return Arr::get($this->keys, 'public'); } /** * Get the private key used to sign tokens with an asymmetric algorithm. * * @return string|null */ public function getPrivateKey() { return Arr::get($this->keys, 'private'); } /** * Get the passphrase used to sign tokens * with an asymmetric algorithm. * * @return string|null */ public function getPassphrase() { return Arr::get($this->keys, 'passphrase'); } /** * Get the key used to sign the tokens. * * @return string|null */ protected function getSigningKey() { return $this->isAsymmetric() ? $this->getPrivateKey() : $this->getSecret(); } /** * Get the key used to verify the tokens. * * @return string|null */ protected function getVerificationKey() { return $this->isAsymmetric() ? $this->getPublicKey() : $this->getSecret(); } /** * Determine if the algorithm is asymmetric, and thus requires a public/private key combo. * * @return bool */ abstract protected function isAsymmetric(); } src/Providers/JWT/Lcobucci.php 0000644 00000017561 15105647722 0012233 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers\JWT; use DateTimeImmutable; use DateTimeInterface; use Exception; use Illuminate\Support\Collection; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Signer; use Lcobucci\JWT\Signer\Ecdsa; use Lcobucci\JWT\Signer\Key; use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Rsa; use Lcobucci\JWT\Token\Builder; use Lcobucci\JWT\Token\RegisteredClaims; use Lcobucci\JWT\Validation\Constraint\SignedWith; use Tymon\JWTAuth\Contracts\Providers\JWT; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Exceptions\TokenInvalidException; class Lcobucci extends Provider implements JWT { /** * \Lcobucci\JWT\Signer. */ protected $signer; /** * \Lcobucci\JWT\Configuration. */ protected $config; /** * Create the Lcobucci provider. * * @param string $secret * @param string $algo * @param array $keys * @param \Lcobucci\JWT\Configuration|null $config * @return void */ public function __construct($secret, $algo, array $keys, $config = null) { parent::__construct($secret, $algo, $keys); $this->signer = $this->getSigner(); $this->config = $config ?: $this->buildConfig(); } /** * Signers that this provider supports. * * @var array */ protected $signers = [ self::ALGO_HS256 => Signer\Hmac\Sha256::class, self::ALGO_HS384 => Signer\Hmac\Sha384::class, self::ALGO_HS512 => Signer\Hmac\Sha512::class, self::ALGO_RS256 => Signer\Rsa\Sha256::class, self::ALGO_RS384 => Signer\Rsa\Sha384::class, self::ALGO_RS512 => Signer\Rsa\Sha512::class, self::ALGO_ES256 => Signer\Ecdsa\Sha256::class, self::ALGO_ES384 => Signer\Ecdsa\Sha384::class, self::ALGO_ES512 => Signer\Ecdsa\Sha512::class, ]; /** * Create a JSON Web Token. * * @param array $payload * @return string * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function encode(array $payload) { $builder = $this->getBuilderFromClaims($payload); try { return $builder ->getToken($this->config->signer(), $this->config->signingKey()) ->toString(); } catch (Exception $e) { throw new JWTException('Could not create token: '.$e->getMessage(), $e->getCode(), $e); } } /** * Decode a JSON Web Token. * * @param string $token * @return array * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function decode($token) { try { /** @var \Lcobucci\JWT\Token\Plain */ $token = $this->config->parser()->parse($token); } catch (Exception $e) { throw new TokenInvalidException('Could not decode token: '.$e->getMessage(), $e->getCode(), $e); } if (! $this->config->validator()->validate($token, ...$this->config->validationConstraints())) { throw new TokenInvalidException('Token Signature could not be verified.'); } return Collection::wrap($token->claims()->all()) ->map(function ($claim) { if ($claim instanceof DateTimeInterface) { return $claim->getTimestamp(); } return is_object($claim) && method_exists($claim, 'getValue') ? $claim->getValue() : $claim; }) ->toArray(); } /** * Create an instance of the builder with all of the claims applied. * * @param array $payload * @return \Lcobucci\JWT\Token\Builder */ protected function getBuilderFromClaims(array $payload): Builder { $builder = $this->config->builder(); foreach ($payload as $key => $value) { switch ($key) { case RegisteredClaims::ID: $builder->identifiedBy($value); break; case RegisteredClaims::EXPIRATION_TIME: $builder->expiresAt(DateTimeImmutable::createFromFormat('U', $value)); break; case RegisteredClaims::NOT_BEFORE: $builder->canOnlyBeUsedAfter(DateTimeImmutable::createFromFormat('U', $value)); break; case RegisteredClaims::ISSUED_AT: $builder->issuedAt(DateTimeImmutable::createFromFormat('U', $value)); break; case RegisteredClaims::ISSUER: $builder->issuedBy($value); break; case RegisteredClaims::AUDIENCE: $builder->permittedFor($value); break; case RegisteredClaims::SUBJECT: $builder->relatedTo($value); break; default: $builder->withClaim($key, $value); } } return $builder; } /** * Build the configuration. * * @return \Lcobucci\JWT\Configuration */ protected function buildConfig(): Configuration { $config = $this->isAsymmetric() ? Configuration::forAsymmetricSigner( $this->signer, $this->getSigningKey(), $this->getVerificationKey() ) : Configuration::forSymmetricSigner($this->signer, $this->getSigningKey()); $config->setValidationConstraints( new SignedWith($this->signer, $this->getVerificationKey()) ); return $config; } /** * Get the signer instance. * * @return \Lcobucci\JWT\Signer * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ protected function getSigner() { if (! array_key_exists($this->algo, $this->signers)) { throw new JWTException('The given algorithm could not be found'); } $signer = $this->signers[$this->algo]; if (is_subclass_of($signer, Ecdsa::class)) { return $signer::create(); } return new $signer(); } /** * {@inheritdoc} */ protected function isAsymmetric() { return is_subclass_of($this->signer, Rsa::class) || is_subclass_of($this->signer, Ecdsa::class); } /** * {@inheritdoc} * * @return \Lcobucci\JWT\Signer\Key * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ protected function getSigningKey() { if ($this->isAsymmetric()) { if (! $privateKey = $this->getPrivateKey()) { throw new JWTException('Private key is not set.'); } return $this->getKey($privateKey, $this->getPassphrase() ?? ''); } if (! $secret = $this->getSecret()) { throw new JWTException('Secret is not set.'); } return $this->getKey($secret); } /** * {@inheritdoc} * * @return \Lcobucci\JWT\Signer\Key * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ protected function getVerificationKey() { if ($this->isAsymmetric()) { if (! $public = $this->getPublicKey()) { throw new JWTException('Public key is not set.'); } return $this->getKey($public); } if (! $secret = $this->getSecret()) { throw new JWTException('Secret is not set.'); } return $this->getKey($secret); } /** * Get the signing key instance. */ protected function getKey(string $contents, string $passphrase = ''): Key { return InMemory::plainText($contents, $passphrase); } } src/Providers/Auth/Illuminate.php 0000644 00000002453 15105647723 0013043 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers\Auth; use Illuminate\Contracts\Auth\Guard as GuardContract; use Tymon\JWTAuth\Contracts\Providers\Auth; class Illuminate implements Auth { /** * The authentication guard. * * @var \Illuminate\Contracts\Auth\Guard */ protected $auth; /** * Constructor. * * @param \Illuminate\Contracts\Auth\Guard $auth * @return void */ public function __construct(GuardContract $auth) { $this->auth = $auth; } /** * Check a user's credentials. * * @param array $credentials * @return bool */ public function byCredentials(array $credentials) { return $this->auth->once($credentials); } /** * Authenticate a user via the id. * * @param mixed $id * @return bool */ public function byId($id) { return $this->auth->onceUsingId($id); } /** * Get the currently authenticated user. * * @return mixed */ public function user() { return $this->auth->user(); } } src/Providers/Storage/Illuminate.php 0000644 00000010267 15105647723 0013550 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers\Storage; use BadMethodCallException; use Illuminate\Contracts\Cache\Repository as CacheContract; use Psr\SimpleCache\CacheInterface as PsrCacheInterface; use Tymon\JWTAuth\Contracts\Providers\Storage; class Illuminate implements Storage { /** * The cache repository contract. * * @var \Illuminate\Contracts\Cache\Repository */ protected $cache; /** * The used cache tag. * * @var string */ protected $tag = 'tymon.jwt'; /** * @var bool */ protected $supportsTags; /** * @var string|null */ protected $laravelVersion; /** * Constructor. * * @param \Illuminate\Contracts\Cache\Repository $cache * @return void */ public function __construct(CacheContract $cache) { $this->cache = $cache; } /** * Add a new item into storage. * * @param string $key * @param mixed $value * @param int $minutes * @return void */ public function add($key, $value, $minutes) { // If the laravel version is 5.8 or higher then convert minutes to seconds. if ($this->laravelVersion !== null && is_int($minutes) && version_compare($this->laravelVersion, '5.8', '>=') ) { $minutes = $minutes * 60; } $this->cache()->put($key, $value, $minutes); } /** * Add a new item into storage forever. * * @param string $key * @param mixed $value * @return void */ public function forever($key, $value) { $this->cache()->forever($key, $value); } /** * Get an item from storage. * * @param string $key * @return mixed */ public function get($key) { return $this->cache()->get($key); } /** * Remove an item from storage. * * @param string $key * @return bool */ public function destroy($key) { return $this->cache()->forget($key); } /** * Remove all items associated with the tag. * * @return void */ public function flush() { $this->cache()->flush(); } /** * Return the cache instance with tags attached. * * @return \Illuminate\Contracts\Cache\Repository */ protected function cache() { if ($this->supportsTags === null) { $this->determineTagSupport(); } if ($this->supportsTags) { return $this->cache->tags($this->tag); } return $this->cache; } /** * Set the laravel version. */ public function setLaravelVersion($version) { $this->laravelVersion = $version; return $this; } /** * Detect as best we can whether tags are supported with this repository & store, * and save our result on the $supportsTags flag. * * @return void */ protected function determineTagSupport() { // Laravel >= 5.1.28 if (method_exists($this->cache, 'tags') || $this->cache instanceof PsrCacheInterface) { try { // Attempt the repository tags command, which throws exceptions when unsupported $this->cache->tags($this->tag); $this->supportsTags = true; } catch (BadMethodCallException $ex) { $this->supportsTags = false; } } else { // Laravel <= 5.1.27 if (method_exists($this->cache, 'getStore')) { // Check for the tags function directly on the store $this->supportsTags = method_exists($this->cache->getStore(), 'tags'); } else { // Must be using custom cache repository without getStore(), and all bets are off, // or we are mocking the cache contract (in testing), which will not create a getStore method $this->supportsTags = false; } } } } src/Providers/LaravelServiceProvider.php 0000644 00000003263 15105647723 0014461 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Providers; use Tymon\JWTAuth\Http\Parser\Cookies; use Tymon\JWTAuth\Http\Parser\RouteParams; class LaravelServiceProvider extends AbstractServiceProvider { /** * {@inheritdoc} */ public function boot() { $path = realpath(__DIR__.'/../../config/config.php'); $this->publishes([$path => config_path('jwt.php')], 'config'); $this->mergeConfigFrom($path, 'jwt'); $this->aliasMiddleware(); $this->extendAuthGuard(); $this->app['tymon.jwt.parser']->addParser([ new RouteParams, new Cookies($this->config('decrypt_cookies')), ]); } /** * {@inheritdoc} */ protected function registerStorageProvider() { $this->app->singleton('tymon.jwt.provider.storage', function () { $instance = $this->getConfigInstance('providers.storage'); if (method_exists($instance, 'setLaravelVersion')) { $instance->setLaravelVersion($this->app->version()); } return $instance; }); } /** * Alias the middleware. * * @return void */ protected function aliasMiddleware() { $router = $this->app['router']; $method = method_exists($router, 'aliasMiddleware') ? 'aliasMiddleware' : 'middleware'; foreach ($this->middlewareAliases as $alias => $middleware) { $router->$method($alias, $middleware); } } } src/JWTGuard.php 0000644 00000022703 15105647723 0007511 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use BadMethodCallException; use Illuminate\Auth\GuardHelpers; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Http\Request; use Illuminate\Support\Traits\Macroable; use Tymon\JWTAuth\Contracts\JWTSubject; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Exceptions\UserNotDefinedException; class JWTGuard implements Guard { use GuardHelpers, Macroable { __call as macroCall; } /** * The user we last attempted to retrieve. * * @var \Illuminate\Contracts\Auth\Authenticatable */ protected $lastAttempted; /** * The JWT instance. * * @var \Tymon\JWTAuth\JWT */ protected $jwt; /** * The request instance. * * @var \Illuminate\Http\Request */ protected $request; /** * Instantiate the class. * * @param \Tymon\JWTAuth\JWT $jwt * @param \Illuminate\Contracts\Auth\UserProvider $provider * @param \Illuminate\Http\Request $request * @return void */ public function __construct(JWT $jwt, UserProvider $provider, Request $request) { $this->jwt = $jwt; $this->provider = $provider; $this->request = $request; } /** * Get the currently authenticated user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user() { if ($this->user !== null) { return $this->user; } if ($this->jwt->setRequest($this->request)->getToken() && ($payload = $this->jwt->check(true)) && $this->validateSubject() ) { return $this->user = $this->provider->retrieveById($payload['sub']); } } /** * Get the currently authenticated user or throws an exception. * * @return \Illuminate\Contracts\Auth\Authenticatable * * @throws \Tymon\JWTAuth\Exceptions\UserNotDefinedException */ public function userOrFail() { if (! $user = $this->user()) { throw new UserNotDefinedException; } return $user; } /** * Validate a user's credentials. * * @param array $credentials * @return bool */ public function validate(array $credentials = []) { return (bool) $this->attempt($credentials, false); } /** * Attempt to authenticate the user using the given credentials and return the token. * * @param array $credentials * @param bool $login * @return bool|string */ public function attempt(array $credentials = [], $login = true) { $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); if ($this->hasValidCredentials($user, $credentials)) { return $login ? $this->login($user) : true; } return false; } /** * Create a token for a user. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $user * @return string */ public function login(JWTSubject $user) { $token = $this->jwt->fromUser($user); $this->setToken($token)->setUser($user); return $token; } /** * Logout the user, thus invalidating the token. * * @param bool $forceForever * @return void */ public function logout($forceForever = false) { $this->requireToken()->invalidate($forceForever); $this->user = null; $this->jwt->unsetToken(); } /** * Refresh the token. * * @param bool $forceForever * @param bool $resetClaims * @return string */ public function refresh($forceForever = false, $resetClaims = false) { return $this->requireToken()->refresh($forceForever, $resetClaims); } /** * Invalidate the token. * * @param bool $forceForever * @return \Tymon\JWTAuth\JWT */ public function invalidate($forceForever = false) { return $this->requireToken()->invalidate($forceForever); } /** * Create a new token by User id. * * @param mixed $id * @return string|null */ public function tokenById($id) { if ($user = $this->provider->retrieveById($id)) { return $this->jwt->fromUser($user); } } /** * Log a user into the application using their credentials. * * @param array $credentials * @return bool */ public function once(array $credentials = []) { if ($this->validate($credentials)) { $this->setUser($this->lastAttempted); return true; } return false; } /** * Log the given User into the application. * * @param mixed $id * @return bool */ public function onceUsingId($id) { if ($user = $this->provider->retrieveById($id)) { $this->setUser($user); return true; } return false; } /** * Alias for onceUsingId. * * @param mixed $id * @return bool */ public function byId($id) { return $this->onceUsingId($id); } /** * Add any custom claims. * * @param array $claims * @return $this */ public function claims(array $claims) { $this->jwt->claims($claims); return $this; } /** * Get the raw Payload instance. * * @return \Tymon\JWTAuth\Payload */ public function getPayload() { return $this->requireToken()->getPayload(); } /** * Alias for getPayload(). * * @return \Tymon\JWTAuth\Payload */ public function payload() { return $this->getPayload(); } /** * Set the token. * * @param \Tymon\JWTAuth\Token|string $token * @return $this */ public function setToken($token) { $this->jwt->setToken($token); return $this; } /** * Set the token ttl. * * @param int $ttl * @return $this */ public function setTTL($ttl) { $this->jwt->factory()->setTTL($ttl); return $this; } /** * Get the user provider used by the guard. * * @return \Illuminate\Contracts\Auth\UserProvider */ public function getProvider() { return $this->provider; } /** * Set the user provider used by the guard. * * @param \Illuminate\Contracts\Auth\UserProvider $provider * @return $this */ public function setProvider(UserProvider $provider) { $this->provider = $provider; return $this; } /** * Return the currently cached user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function getUser() { return $this->user; } /** * Get the current request instance. * * @return \Illuminate\Http\Request */ public function getRequest() { return $this->request ?: Request::createFromGlobals(); } /** * Set the current request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } /** * Get the last user we attempted to authenticate. * * @return \Illuminate\Contracts\Auth\Authenticatable */ public function getLastAttempted() { return $this->lastAttempted; } /** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { return $user !== null && $this->provider->validateCredentials($user, $credentials); } /** * Ensure the JWTSubject matches what is in the token. * * @return bool */ protected function validateSubject() { // If the provider doesn't have the necessary method // to get the underlying model name then allow. if (! method_exists($this->provider, 'getModel')) { return true; } return $this->jwt->checkSubjectModel($this->provider->getModel()); } /** * Ensure that a token is available in the request. * * @return \Tymon\JWTAuth\JWT * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ protected function requireToken() { if (! $this->jwt->setRequest($this->getRequest())->getToken()) { throw new JWTException('Token could not be parsed from the request.'); } return $this->jwt; } /** * Magically call the JWT instance. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (method_exists($this->jwt, $method)) { return call_user_func_array([$this->jwt, $method], $parameters); } if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } throw new BadMethodCallException("Method [$method] does not exist."); } } src/Payload.php 0000644 00000014465 15105647723 0007461 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use ArrayAccess; use BadMethodCallException; use Countable; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Contracts\Support\Jsonable; use Illuminate\Support\Arr; use Illuminate\Support\Str; use JsonSerializable; use Tymon\JWTAuth\Claims\Claim; use Tymon\JWTAuth\Claims\Collection; use Tymon\JWTAuth\Exceptions\PayloadException; use Tymon\JWTAuth\Validators\PayloadValidator; class Payload implements ArrayAccess, Arrayable, Countable, Jsonable, JsonSerializable { /** * The collection of claims. * * @var \Tymon\JWTAuth\Claims\Collection */ private $claims; /** * Build the Payload. * * @param \Tymon\JWTAuth\Claims\Collection $claims * @param \Tymon\JWTAuth\Validators\PayloadValidator $validator * @param bool $refreshFlow * @return void */ public function __construct(Collection $claims, PayloadValidator $validator, $refreshFlow = false) { $this->claims = $validator->setRefreshFlow($refreshFlow)->check($claims); } /** * Get the array of claim instances. * * @return \Tymon\JWTAuth\Claims\Collection */ public function getClaims() { return $this->claims; } /** * Checks if a payload matches some expected values. * * @param array $values * @param bool $strict * @return bool */ public function matches(array $values, $strict = false) { if (empty($values)) { return false; } $claims = $this->getClaims(); foreach ($values as $key => $value) { if (! $claims->has($key) || ! $claims->get($key)->matches($value, $strict)) { return false; } } return true; } /** * Checks if a payload strictly matches some expected values. * * @param array $values * @return bool */ public function matchesStrict(array $values) { return $this->matches($values, true); } /** * Get the payload. * * @param mixed $claim * @return mixed */ public function get($claim = null) { $claim = value($claim); if ($claim !== null) { if (is_array($claim)) { return array_map([$this, 'get'], $claim); } return Arr::get($this->toArray(), $claim); } return $this->toArray(); } /** * Get the underlying Claim instance. * * @param string $claim * @return \Tymon\JWTAuth\Claims\Claim */ public function getInternal($claim) { return $this->claims->getByClaimName($claim); } /** * Determine whether the payload has the claim (by instance). * * @param \Tymon\JWTAuth\Claims\Claim $claim * @return bool */ public function has(Claim $claim) { return $this->claims->has($claim->getName()); } /** * Determine whether the payload has the claim (by key). * * @param string $claim * @return bool */ public function hasKey($claim) { return $this->offsetExists($claim); } /** * Get the array of claims. * * @return array */ public function toArray() { return $this->claims->toPlainArray(); } /** * Convert the object into something JSON serializable. * * @return array */ #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->toArray(); } /** * Get the payload as JSON. * * @param int $options * @return string */ public function toJson($options = JSON_UNESCAPED_SLASHES) { return json_encode($this->toArray(), $options); } /** * Get the payload as a string. * * @return string */ public function __toString() { return $this->toJson(); } /** * Determine if an item exists at an offset. * * @param mixed $key * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($key) { return Arr::has($this->toArray(), $key); } /** * Get an item at a given offset. * * @param mixed $key * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($key) { return Arr::get($this->toArray(), $key); } /** * Don't allow changing the payload as it should be immutable. * * @param mixed $key * @param mixed $value * * @throws \Tymon\JWTAuth\Exceptions\PayloadException */ #[\ReturnTypeWillChange] public function offsetSet($key, $value) { throw new PayloadException('The payload is immutable'); } /** * Don't allow changing the payload as it should be immutable. * * @param string $key * @return void * * @throws \Tymon\JWTAuth\Exceptions\PayloadException */ #[\ReturnTypeWillChange] public function offsetUnset($key) { throw new PayloadException('The payload is immutable'); } /** * Count the number of claims. * * @return int */ #[\ReturnTypeWillChange] public function count() { return count($this->toArray()); } /** * Invoke the Payload as a callable function. * * @param mixed $claim * @return mixed */ public function __invoke($claim = null) { return $this->get($claim); } /** * Magically get a claim value. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (preg_match('/get(.+)\b/i', $method, $matches)) { foreach ($this->claims as $claim) { if (get_class($claim) === 'Tymon\\JWTAuth\\Claims\\'.$matches[1]) { return $claim->getValue(); } } } throw new BadMethodCallException(sprintf('The claim [%s] does not exist on the payload.', Str::after($method, 'get'))); } } src/Validators/PayloadValidator.php 0000644 00000005504 15105647723 0013431 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Validators; use Tymon\JWTAuth\Claims\Collection; use Tymon\JWTAuth\Exceptions\TokenInvalidException; class PayloadValidator extends Validator { /** * The required claims. * * @var array */ protected $requiredClaims = [ 'iss', 'iat', 'exp', 'nbf', 'sub', 'jti', ]; /** * The refresh TTL. * * @var int */ protected $refreshTTL = 20160; /** * Run the validations on the payload array. * * @param \Tymon\JWTAuth\Claims\Collection $value * @return \Tymon\JWTAuth\Claims\Collection */ public function check($value) { $this->validateStructure($value); return $this->refreshFlow ? $this->validateRefresh($value) : $this->validatePayload($value); } /** * Ensure the payload contains the required claims and * the claims have the relevant type. * * @param \Tymon\JWTAuth\Claims\Collection $claims * @return void * * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException */ protected function validateStructure(Collection $claims) { if ($this->requiredClaims && ! $claims->hasAllClaims($this->requiredClaims)) { throw new TokenInvalidException('JWT payload does not contain the required claims'); } } /** * Validate the payload timestamps. * * @param \Tymon\JWTAuth\Claims\Collection $claims * @return \Tymon\JWTAuth\Claims\Collection * * @throws \Tymon\JWTAuth\Exceptions\TokenExpiredException * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException */ protected function validatePayload(Collection $claims) { return $claims->validate('payload'); } /** * Check the token in the refresh flow context. * * @param \Tymon\JWTAuth\Claims\Collection $claims * @return \Tymon\JWTAuth\Claims\Collection * * @throws \Tymon\JWTAuth\Exceptions\TokenExpiredException */ protected function validateRefresh(Collection $claims) { return $this->refreshTTL === null ? $claims : $claims->validate('refresh', $this->refreshTTL); } /** * Set the required claims. * * @param array $claims * @return $this */ public function setRequiredClaims(array $claims) { $this->requiredClaims = $claims; return $this; } /** * Set the refresh ttl. * * @param int $ttl * @return $this */ public function setRefreshTTL($ttl) { $this->refreshTTL = $ttl; return $this; } } src/Validators/TokenValidator.php 0000644 00000002177 15105647724 0013124 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Validators; use Tymon\JWTAuth\Exceptions\TokenInvalidException; class TokenValidator extends Validator { /** * Check the structure of the token. * * @param string $value * @return string */ public function check($value) { return $this->validateStructure($value); } /** * @param string $token * @return string * * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException */ protected function validateStructure($token) { $parts = explode('.', $token); if (count($parts) !== 3) { throw new TokenInvalidException('Wrong number of segments'); } $parts = array_filter(array_map('trim', $parts)); if (count($parts) !== 3 || implode('.', $parts) !== $token) { throw new TokenInvalidException('Malformed token'); } return $token; } } src/Validators/Validator.php 0000644 00000001643 15105647724 0012120 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Validators; use Tymon\JWTAuth\Contracts\Validator as ValidatorContract; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Support\RefreshFlow; abstract class Validator implements ValidatorContract { use RefreshFlow; /** * Helper function to return a boolean. * * @param array $value * @return bool */ public function isValid($value) { try { $this->check($value); } catch (JWTException $e) { return false; } return true; } /** * Run the validation. * * @param array $value * @return void */ abstract public function check($value); } src/Facades/JWTProvider.php 0000644 00000001021 15105647724 0011556 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Facades; use Illuminate\Support\Facades\Facade; class JWTProvider extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'tymon.jwt.provider.jwt'; } } src/Facades/JWTFactory.php 0000644 00000001023 15105647724 0011375 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Facades; use Illuminate\Support\Facades\Facade; class JWTFactory extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'tymon.jwt.payload.factory'; } } src/Facades/JWTAuth.php 0000644 00000001005 15105647724 0010667 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Facades; use Illuminate\Support\Facades\Facade; class JWTAuth extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'tymon.jwt.auth'; } } src/Claims/Expiration.php 0000644 00000001204 15105647724 0011406 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Tymon\JWTAuth\Exceptions\TokenExpiredException; class Expiration extends Claim { use DatetimeTrait; /** * {@inheritdoc} */ protected $name = 'exp'; /** * {@inheritdoc} */ public function validatePayload() { if ($this->isPast($this->getValue())) { throw new TokenExpiredException('Token has expired'); } } } src/Claims/Custom.php 0000644 00000000772 15105647724 0010547 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; class Custom extends Claim { /** * @param string $name * @param mixed $value * @return void */ public function __construct($name, $value) { parent::__construct($value); $this->setName($name); } } src/Claims/Collection.php 0000644 00000005206 15105647724 0011365 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Illuminate\Support\Collection as IlluminateCollection; use Illuminate\Support\Str; class Collection extends IlluminateCollection { /** * Create a new collection. * * @param mixed $items * @return void */ public function __construct($items = []) { parent::__construct($this->getArrayableItems($items)); } /** * Get a Claim instance by it's unique name. * * @param string $name * @param callable $callback * @param mixed $default * @return \Tymon\JWTAuth\Claims\Claim */ public function getByClaimName($name, callable $callback = null, $default = null) { return $this->filter(function (Claim $claim) use ($name) { return $claim->getName() === $name; })->first($callback, $default); } /** * Validate each claim under a given context. * * @param string $context * @return $this */ public function validate($context = 'payload') { $args = func_get_args(); array_shift($args); $this->each(function ($claim) use ($context, $args) { call_user_func_array( [$claim, 'validate'.Str::ucfirst($context)], $args ); }); return $this; } /** * Determine if the Collection contains all of the given keys. * * @param mixed $claims * @return bool */ public function hasAllClaims($claims) { return count($claims) && (new static($claims))->diff($this->keys())->isEmpty(); } /** * Get the claims as key/val array. * * @return array */ public function toPlainArray() { return $this->map(function (Claim $claim) { return $claim->getValue(); })->toArray(); } /** * {@inheritdoc} */ protected function getArrayableItems($items) { return $this->sanitizeClaims($items); } /** * Ensure that the given claims array is keyed by the claim name. * * @param mixed $items * @return array */ private function sanitizeClaims($items) { $claims = []; foreach ($items as $key => $value) { if (! is_string($key) && $value instanceof Claim) { $key = $value->getName(); } $claims[$key] = $value; } return $claims; } } src/Claims/Subject.php 0000644 00000000540 15105647724 0010665 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; class Subject extends Claim { /** * {@inheritdoc} */ protected $name = 'sub'; } src/Claims/Factory.php 0000644 00000007747 15105647724 0010715 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Illuminate\Http\Request; use Illuminate\Support\Str; use Tymon\JWTAuth\Support\Utils; class Factory { /** * The request. * * @var \Illuminate\Http\Request */ protected $request; /** * The TTL. * * @var int */ protected $ttl = 60; /** * Time leeway in seconds. * * @var int */ protected $leeway = 0; /** * The classes map. * * @var array */ private $classMap = [ 'aud' => Audience::class, 'exp' => Expiration::class, 'iat' => IssuedAt::class, 'iss' => Issuer::class, 'jti' => JwtId::class, 'nbf' => NotBefore::class, 'sub' => Subject::class, ]; /** * Constructor. * * @param \Illuminate\Http\Request $request * @return void */ public function __construct(Request $request) { $this->request = $request; } /** * Get the instance of the claim when passing the name and value. * * @param string $name * @param mixed $value * @return \Tymon\JWTAuth\Claims\Claim */ public function get($name, $value) { if ($this->has($name)) { $claim = new $this->classMap[$name]($value); return method_exists($claim, 'setLeeway') ? $claim->setLeeway($this->leeway) : $claim; } return new Custom($name, $value); } /** * Check whether the claim exists. * * @param string $name * @return bool */ public function has($name) { return array_key_exists($name, $this->classMap); } /** * Generate the initial value and return the Claim instance. * * @param string $name * @return \Tymon\JWTAuth\Claims\Claim */ public function make($name) { return $this->get($name, $this->$name()); } /** * Get the Issuer (iss) claim. * * @return string */ public function iss() { return $this->request->url(); } /** * Get the Issued At (iat) claim. * * @return int */ public function iat() { return Utils::now()->getTimestamp(); } /** * Get the Expiration (exp) claim. * * @return int */ public function exp() { return Utils::now()->addMinutes($this->ttl)->getTimestamp(); } /** * Get the Not Before (nbf) claim. * * @return int */ public function nbf() { return Utils::now()->getTimestamp(); } /** * Get the JWT Id (jti) claim. * * @return string */ public function jti() { return Str::random(); } /** * Add a new claim mapping. * * @param string $name * @param string $classPath * @return $this */ public function extend($name, $classPath) { $this->classMap[$name] = $classPath; return $this; } /** * Set the request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } /** * Set the token ttl (in minutes). * * @param int $ttl * @return $this */ public function setTTL($ttl) { $this->ttl = $ttl; return $this; } /** * Get the token ttl. * * @return int */ public function getTTL() { return $this->ttl; } /** * Set the leeway in seconds. * * @param int $leeway * @return $this */ public function setLeeway($leeway) { $this->leeway = $leeway; return $this; } } src/Claims/Audience.php 0000644 00000000541 15105647724 0011004 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; class Audience extends Claim { /** * {@inheritdoc} */ protected $name = 'aud'; } src/Claims/Issuer.php 0000644 00000000537 15105647724 0010546 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; class Issuer extends Claim { /** * {@inheritdoc} */ protected $name = 'iss'; } src/Claims/Claim.php 0000644 00000006443 15105647724 0010323 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Contracts\Support\Jsonable; use JsonSerializable; use Tymon\JWTAuth\Contracts\Claim as ClaimContract; abstract class Claim implements Arrayable, ClaimContract, Jsonable, JsonSerializable { /** * The claim name. * * @var string */ protected $name; /** * The claim value. * * @var mixed */ private $value; /** * @param mixed $value * @return void */ public function __construct($value) { $this->setValue($value); } /** * Set the claim value, and call a validate method. * * @param mixed $value * @return $this * * @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException */ public function setValue($value) { $this->value = $this->validateCreate($value); return $this; } /** * Get the claim value. * * @return mixed */ public function getValue() { return $this->value; } /** * Set the claim name. * * @param string $name * @return $this */ public function setName($name) { $this->name = $name; return $this; } /** * Get the claim name. * * @return string */ public function getName() { return $this->name; } /** * Validate the claim in a standalone Claim context. * * @param mixed $value * @return bool */ public function validateCreate($value) { return $value; } /** * Validate the Claim within a Payload context. * * @return bool */ public function validatePayload() { return $this->getValue(); } /** * Validate the Claim within a refresh context. * * @param int $refreshTTL * @return bool */ public function validateRefresh($refreshTTL) { return $this->getValue(); } /** * Checks if the value matches the claim. * * @param mixed $value * @param bool $strict * @return bool */ public function matches($value, $strict = true) { return $strict ? $this->value === $value : $this->value == $value; } /** * Convert the object into something JSON serializable. * * @return array */ #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->toArray(); } /** * Build a key value array comprising of the claim name and value. * * @return array */ public function toArray() { return [$this->getName() => $this->getValue()]; } /** * Get the claim as JSON. * * @param int $options * @return string */ public function toJson($options = JSON_UNESCAPED_SLASHES) { return json_encode($this->toArray(), $options); } /** * Get the payload as a string. * * @return string */ public function __toString() { return $this->toJson(); } } src/Claims/IssuedAt.php 0000644 00000002534 15105647724 0011014 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Tymon\JWTAuth\Exceptions\InvalidClaimException; use Tymon\JWTAuth\Exceptions\TokenExpiredException; use Tymon\JWTAuth\Exceptions\TokenInvalidException; class IssuedAt extends Claim { use DatetimeTrait { validateCreate as commonValidateCreate; } /** * {@inheritdoc} */ protected $name = 'iat'; /** * {@inheritdoc} */ public function validateCreate($value) { $this->commonValidateCreate($value); if ($this->isFuture($value)) { throw new InvalidClaimException($this); } return $value; } /** * {@inheritdoc} */ public function validatePayload() { if ($this->isFuture($this->getValue())) { throw new TokenInvalidException('Issued At (iat) timestamp cannot be in the future'); } } /** * {@inheritdoc} */ public function validateRefresh($refreshTTL) { if ($this->isPast($this->getValue() + $refreshTTL * 60)) { throw new TokenExpiredException('Token has expired and can no longer be refreshed'); } } } src/Claims/NotBefore.php 0000644 00000001246 15105647725 0011156 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use Tymon\JWTAuth\Exceptions\TokenInvalidException; class NotBefore extends Claim { use DatetimeTrait; /** * {@inheritdoc} */ protected $name = 'nbf'; /** * {@inheritdoc} */ public function validatePayload() { if ($this->isFuture($this->getValue())) { throw new TokenInvalidException('Not Before (nbf) timestamp cannot be in the future'); } } } src/Claims/DatetimeTrait.php 0000644 00000003545 15105647725 0012037 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; use DateInterval; use DateTimeInterface; use Tymon\JWTAuth\Exceptions\InvalidClaimException; use Tymon\JWTAuth\Support\Utils; trait DatetimeTrait { /** * Time leeway in seconds. * * @var int */ protected $leeway = 0; /** * Set the claim value, and call a validate method. * * @param mixed $value * @return $this * * @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException */ public function setValue($value) { if ($value instanceof DateInterval) { $value = Utils::now()->add($value); } if ($value instanceof DateTimeInterface) { $value = $value->getTimestamp(); } return parent::setValue($value); } /** * {@inheritdoc} */ public function validateCreate($value) { if (! is_numeric($value)) { throw new InvalidClaimException($this); } return $value; } /** * Determine whether the value is in the future. * * @param mixed $value * @return bool */ protected function isFuture($value) { return Utils::isFuture($value, $this->leeway); } /** * Determine whether the value is in the past. * * @param mixed $value * @return bool */ protected function isPast($value) { return Utils::isPast($value, $this->leeway); } /** * Set the leeway in seconds. * * @param int $leeway * @return $this */ public function setLeeway($leeway) { $this->leeway = $leeway; return $this; } } src/Claims/JwtId.php 0000644 00000000536 15105647725 0010315 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Claims; class JwtId extends Claim { /** * {@inheritdoc} */ protected $name = 'jti'; } src/Blacklist.php 0000644 00000012230 15105647725 0007766 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use Tymon\JWTAuth\Contracts\Providers\Storage; use Tymon\JWTAuth\Support\Utils; class Blacklist { /** * The storage. * * @var \Tymon\JWTAuth\Contracts\Providers\Storage */ protected $storage; /** * The grace period when a token is blacklisted. In seconds. * * @var int */ protected $gracePeriod = 0; /** * Number of minutes from issue date in which a JWT can be refreshed. * * @var int */ protected $refreshTTL = 20160; /** * The unique key held within the blacklist. * * @var string */ protected $key = 'jti'; /** * Constructor. * * @param \Tymon\JWTAuth\Contracts\Providers\Storage $storage * @return void */ public function __construct(Storage $storage) { $this->storage = $storage; } /** * Add the token (jti claim) to the blacklist. * * @param \Tymon\JWTAuth\Payload $payload * @return bool */ public function add(Payload $payload) { // if there is no exp claim then add the jwt to // the blacklist indefinitely if (! $payload->hasKey('exp')) { return $this->addForever($payload); } // if we have already added this token to the blacklist if (! empty($this->storage->get($this->getKey($payload)))) { return true; } $this->storage->add( $this->getKey($payload), ['valid_until' => $this->getGraceTimestamp()], $this->getMinutesUntilExpired($payload) ); return true; } /** * Get the number of minutes until the token expiry. * * @param \Tymon\JWTAuth\Payload $payload * @return int */ protected function getMinutesUntilExpired(Payload $payload) { $exp = Utils::timestamp($payload['exp']); $iat = Utils::timestamp($payload['iat']); // get the latter of the two expiration dates and find // the number of minutes until the expiration date, // plus 1 minute to avoid overlap return $exp->max($iat->addMinutes($this->refreshTTL))->addMinute()->diffInRealMinutes(); } /** * Add the token (jti claim) to the blacklist indefinitely. * * @param \Tymon\JWTAuth\Payload $payload * @return bool */ public function addForever(Payload $payload) { $this->storage->forever($this->getKey($payload), 'forever'); return true; } /** * Determine whether the token has been blacklisted. * * @param \Tymon\JWTAuth\Payload $payload * @return bool */ public function has(Payload $payload) { $val = $this->storage->get($this->getKey($payload)); // exit early if the token was blacklisted forever, if ($val === 'forever') { return true; } // check whether the expiry + grace has past return ! empty($val) && ! Utils::isFuture($val['valid_until']); } /** * Remove the token (jti claim) from the blacklist. * * @param \Tymon\JWTAuth\Payload $payload * @return bool */ public function remove(Payload $payload) { return $this->storage->destroy($this->getKey($payload)); } /** * Remove all tokens from the blacklist. * * @return bool */ public function clear() { $this->storage->flush(); return true; } /** * Get the timestamp when the blacklist comes into effect * This defaults to immediate (0 seconds). * * @return int */ protected function getGraceTimestamp() { return Utils::now()->addSeconds($this->gracePeriod)->getTimestamp(); } /** * Set the grace period. * * @param int $gracePeriod * @return $this */ public function setGracePeriod($gracePeriod) { $this->gracePeriod = (int) $gracePeriod; return $this; } /** * Get the grace period. * * @return int */ public function getGracePeriod() { return $this->gracePeriod; } /** * Get the unique key held within the blacklist. * * @param \Tymon\JWTAuth\Payload $payload * @return mixed */ public function getKey(Payload $payload) { return $payload($this->key); } /** * Set the unique key held within the blacklist. * * @param string $key * @return $this */ public function setKey($key) { $this->key = value($key); return $this; } /** * Set the refresh time limit. * * @param int $ttl * @return $this */ public function setRefreshTTL($ttl) { $this->refreshTTL = (int) $ttl; return $this; } /** * Get the refresh time limit. * * @return int */ public function getRefreshTTL() { return $this->refreshTTL; } } src/Support/RefreshFlow.php 0000644 00000001166 15105647725 0011766 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Support; trait RefreshFlow { /** * The refresh flow flag. * * @var bool */ protected $refreshFlow = false; /** * Set the refresh flow flag. * * @param bool $refreshFlow * @return $this */ public function setRefreshFlow($refreshFlow = true) { $this->refreshFlow = $refreshFlow; return $this; } } src/Support/CustomClaims.php 0000644 00000001764 15105647725 0012147 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Support; trait CustomClaims { /** * Custom claims. * * @var array */ protected $customClaims = []; /** * Set the custom claims. * * @param array $customClaims * @return $this */ public function customClaims(array $customClaims) { $this->customClaims = $customClaims; return $this; } /** * Alias to set the custom claims. * * @param array $customClaims * @return $this */ public function claims(array $customClaims) { return $this->customClaims($customClaims); } /** * Get the custom claims. * * @return array */ public function getCustomClaims() { return $this->customClaims; } } src/Support/Utils.php 0000644 00000003003 15105647725 0010630 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Support; use Carbon\Carbon; class Utils { /** * Get the Carbon instance for the current time. * * @return \Carbon\Carbon */ public static function now() { return Carbon::now('UTC'); } /** * Get the Carbon instance for the timestamp. * * @param int $timestamp * @return \Carbon\Carbon */ public static function timestamp($timestamp) { return Carbon::createFromTimestampUTC($timestamp)->timezone('UTC'); } /** * Checks if a timestamp is in the past. * * @param int $timestamp * @param int $leeway * @return bool */ public static function isPast($timestamp, $leeway = 0) { $timestamp = static::timestamp($timestamp); return $leeway > 0 ? $timestamp->addSeconds($leeway)->isPast() : $timestamp->isPast(); } /** * Checks if a timestamp is in the future. * * @param int $timestamp * @param int $leeway * @return bool */ public static function isFuture($timestamp, $leeway = 0) { $timestamp = static::timestamp($timestamp); return $leeway > 0 ? $timestamp->subSeconds($leeway)->isFuture() : $timestamp->isFuture(); } } src/Factory.php 0000644 00000012425 15105647725 0007473 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use Tymon\JWTAuth\Claims\Claim; use Tymon\JWTAuth\Claims\Collection; use Tymon\JWTAuth\Claims\Factory as ClaimFactory; use Tymon\JWTAuth\Support\CustomClaims; use Tymon\JWTAuth\Support\RefreshFlow; use Tymon\JWTAuth\Validators\PayloadValidator; class Factory { use CustomClaims, RefreshFlow; /** * The claim factory. * * @var \Tymon\JWTAuth\Claims\Factory */ protected $claimFactory; /** * The validator. * * @var \Tymon\JWTAuth\Validators\PayloadValidator */ protected $validator; /** * The default claims. * * @var array */ protected $defaultClaims = [ 'iss', 'iat', 'exp', 'nbf', 'jti', ]; /** * The claims collection. * * @var \Tymon\JWTAuth\Claims\Collection */ protected $claims; /** * Constructor. * * @param \Tymon\JWTAuth\Claims\Factory $claimFactory * @param \Tymon\JWTAuth\Validators\PayloadValidator $validator * @return void */ public function __construct(ClaimFactory $claimFactory, PayloadValidator $validator) { $this->claimFactory = $claimFactory; $this->validator = $validator; $this->claims = new Collection; } /** * Create the Payload instance. * * @param bool $resetClaims * @return \Tymon\JWTAuth\Payload */ public function make($resetClaims = false) { if ($resetClaims) { $this->emptyClaims(); } return $this->withClaims($this->buildClaimsCollection()); } /** * Empty the claims collection. * * @return $this */ public function emptyClaims() { $this->claims = new Collection; return $this; } /** * Add an array of claims to the Payload. * * @param array $claims * @return $this */ protected function addClaims(array $claims) { foreach ($claims as $name => $value) { $this->addClaim($name, $value); } return $this; } /** * Add a claim to the Payload. * * @param string $name * @param mixed $value * @return $this */ protected function addClaim($name, $value) { $this->claims->put($name, $value); return $this; } /** * Build the default claims. * * @return $this */ protected function buildClaims() { // remove the exp claim if it exists and the ttl is null if ($this->claimFactory->getTTL() === null && $key = array_search('exp', $this->defaultClaims)) { unset($this->defaultClaims[$key]); } // add the default claims foreach ($this->defaultClaims as $claim) { $this->addClaim($claim, $this->claimFactory->make($claim)); } // add custom claims on top, allowing them to overwrite defaults return $this->addClaims($this->getCustomClaims()); } /** * Build out the Claim DTO's. * * @return \Tymon\JWTAuth\Claims\Collection */ protected function resolveClaims() { return $this->claims->map(function ($value, $name) { return $value instanceof Claim ? $value : $this->claimFactory->get($name, $value); }); } /** * Build and get the Claims Collection. * * @return \Tymon\JWTAuth\Claims\Collection */ public function buildClaimsCollection() { return $this->buildClaims()->resolveClaims(); } /** * Get a Payload instance with a claims collection. * * @param \Tymon\JWTAuth\Claims\Collection $claims * @return \Tymon\JWTAuth\Payload */ public function withClaims(Collection $claims) { return new Payload($claims, $this->validator, $this->refreshFlow); } /** * Set the default claims to be added to the Payload. * * @param array $claims * @return $this */ public function setDefaultClaims(array $claims) { $this->defaultClaims = $claims; return $this; } /** * Helper to set the ttl. * * @param int $ttl * @return $this */ public function setTTL($ttl) { $this->claimFactory->setTTL($ttl); return $this; } /** * Helper to get the ttl. * * @return int */ public function getTTL() { return $this->claimFactory->getTTL(); } /** * Get the default claims. * * @return array */ public function getDefaultClaims() { return $this->defaultClaims; } /** * Get the PayloadValidator instance. * * @return \Tymon\JWTAuth\Validators\PayloadValidator */ public function validator() { return $this->validator; } /** * Magically add a claim. * * @param string $method * @param array $parameters * @return $this */ public function __call($method, $parameters) { $this->addClaim($method, $parameters[0]); return $this; } } src/JWT.php 0000644 00000021261 15105647725 0006526 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use BadMethodCallException; use Illuminate\Http\Request; use Tymon\JWTAuth\Contracts\JWTSubject; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Http\Parser\Parser; use Tymon\JWTAuth\Support\CustomClaims; class JWT { use CustomClaims; /** * The authentication manager. * * @var \Tymon\JWTAuth\Manager */ protected $manager; /** * The HTTP parser. * * @var \Tymon\JWTAuth\Http\Parser\Parser */ protected $parser; /** * The token. * * @var \Tymon\JWTAuth\Token|null */ protected $token; /** * Lock the subject. * * @var bool */ protected $lockSubject = true; /** * JWT constructor. * * @param \Tymon\JWTAuth\Manager $manager * @param \Tymon\JWTAuth\Http\Parser\Parser $parser * @return void */ public function __construct(Manager $manager, Parser $parser) { $this->manager = $manager; $this->parser = $parser; } /** * Generate a token for a given subject. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject * @return string */ public function fromSubject(JWTSubject $subject) { $payload = $this->makePayload($subject); return $this->manager->encode($payload)->get(); } /** * Alias to generate a token for a given user. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $user * @return string */ public function fromUser(JWTSubject $user) { return $this->fromSubject($user); } /** * Refresh an expired token. * * @param bool $forceForever * @param bool $resetClaims * @return string */ public function refresh($forceForever = false, $resetClaims = false) { $this->requireToken(); return $this->manager->customClaims($this->getCustomClaims()) ->refresh($this->token, $forceForever, $resetClaims) ->get(); } /** * Invalidate a token (add it to the blacklist). * * @param bool $forceForever * @return $this */ public function invalidate($forceForever = false) { $this->requireToken(); $this->manager->invalidate($this->token, $forceForever); return $this; } /** * Alias to get the payload, and as a result checks that * the token is valid i.e. not expired or blacklisted. * * @return \Tymon\JWTAuth\Payload * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function checkOrFail() { return $this->getPayload(); } /** * Check that the token is valid. * * @param bool $getPayload * @return \Tymon\JWTAuth\Payload|bool */ public function check($getPayload = false) { try { $payload = $this->checkOrFail(); } catch (JWTException $e) { return false; } return $getPayload ? $payload : true; } /** * Get the token. * * @return \Tymon\JWTAuth\Token|null */ public function getToken() { if ($this->token === null) { try { $this->parseToken(); } catch (JWTException $e) { $this->token = null; } } return $this->token; } /** * Parse the token from the request. * * @return $this * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function parseToken() { if (! $token = $this->parser->parseToken()) { throw new JWTException('The token could not be parsed from the request'); } return $this->setToken($token); } /** * Get the raw Payload instance. * * @return \Tymon\JWTAuth\Payload */ public function getPayload() { $this->requireToken(); return $this->manager->decode($this->token); } /** * Alias for getPayload(). * * @return \Tymon\JWTAuth\Payload */ public function payload() { return $this->getPayload(); } /** * Convenience method to get a claim value. * * @param string $claim * @return mixed */ public function getClaim($claim) { return $this->payload()->get($claim); } /** * Create a Payload instance. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject * @return \Tymon\JWTAuth\Payload */ public function makePayload(JWTSubject $subject) { return $this->factory()->customClaims($this->getClaimsArray($subject))->make(); } /** * Build the claims array and return it. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject * @return array */ protected function getClaimsArray(JWTSubject $subject) { return array_merge( $this->getClaimsForSubject($subject), $subject->getJWTCustomClaims(), // custom claims from JWTSubject method $this->customClaims // custom claims from inline setter ); } /** * Get the claims associated with a given subject. * * @param \Tymon\JWTAuth\Contracts\JWTSubject $subject * @return array */ protected function getClaimsForSubject(JWTSubject $subject) { return array_merge([ 'sub' => $subject->getJWTIdentifier(), ], $this->lockSubject ? ['prv' => $this->hashSubjectModel($subject)] : []); } /** * Hash the subject model and return it. * * @param string|object $model * @return string */ protected function hashSubjectModel($model) { return sha1(is_object($model) ? get_class($model) : $model); } /** * Check if the subject model matches the one saved in the token. * * @param string|object $model * @return bool */ public function checkSubjectModel($model) { if (($prv = $this->payload()->get('prv')) === null) { return true; } return $this->hashSubjectModel($model) === $prv; } /** * Set the token. * * @param \Tymon\JWTAuth\Token|string $token * @return $this */ public function setToken($token) { $this->token = $token instanceof Token ? $token : new Token($token); return $this; } /** * Unset the current token. * * @return $this */ public function unsetToken() { $this->token = null; return $this; } /** * Ensure that a token is available. * * @return void * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ protected function requireToken() { if (! $this->token) { throw new JWTException('A token is required'); } } /** * Set the request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->parser->setRequest($request); return $this; } /** * Set whether the subject should be "locked". * * @param bool $lock * @return $this */ public function lockSubject($lock) { $this->lockSubject = $lock; return $this; } /** * Get the Manager instance. * * @return \Tymon\JWTAuth\Manager */ public function manager() { return $this->manager; } /** * Get the Parser instance. * * @return \Tymon\JWTAuth\Http\Parser\Parser */ public function parser() { return $this->parser; } /** * Get the Payload Factory. * * @return \Tymon\JWTAuth\Factory */ public function factory() { return $this->manager->getPayloadFactory(); } /** * Get the Blacklist. * * @return \Tymon\JWTAuth\Blacklist */ public function blacklist() { return $this->manager->getBlacklist(); } /** * Magically call the JWT Manager. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { if (method_exists($this->manager, $method)) { return call_user_func_array([$this->manager, $method], $parameters); } throw new BadMethodCallException("Method [$method] does not exist."); } } src/Token.php 0000644 00000001577 15105647725 0007152 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use Tymon\JWTAuth\Validators\TokenValidator; class Token { /** * @var string */ private $value; /** * Create a new JSON Web Token. * * @param string $value * @return void */ public function __construct($value) { $this->value = (string) (new TokenValidator)->check($value); } /** * Get the token. * * @return string */ public function get() { return $this->value; } /** * Get the token when casting to string. * * @return string */ public function __toString() { return $this->get(); } } src/Http/Parser/InputSource.php 0000644 00000001244 15105647725 0012514 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Tymon\JWTAuth\Contracts\Http\Parser as ParserContract; class InputSource implements ParserContract { use KeyTrait; /** * Try to parse the token from the request input source. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { return $request->input($this->key); } } src/Http/Parser/AuthHeaders.php 0000644 00000004111 15105647725 0012425 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Tymon\JWTAuth\Contracts\Http\Parser as ParserContract; class AuthHeaders implements ParserContract { /** * The header name. * * @var string */ protected $header = 'authorization'; /** * The header prefix. * * @var string */ protected $prefix = 'bearer'; /** * Attempt to parse the token from some other possible headers. * * @param \Illuminate\Http\Request $request * @return null|string */ protected function fromAltHeaders(Request $request) { return $request->server->get('HTTP_AUTHORIZATION') ?: $request->server->get('REDIRECT_HTTP_AUTHORIZATION'); } /** * Try to parse the token from the request header. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { $header = $request->headers->get($this->header) ?: $this->fromAltHeaders($request); if ($header !== null) { $position = strripos($header, $this->prefix); if ($position !== false) { $header = substr($header, $position + strlen($this->prefix)); return trim( strpos($header, ',') !== false ? strstr($header, ',', true) : $header ); } } return null; } /** * Set the header name. * * @param string $headerName * @return $this */ public function setHeaderName($headerName) { $this->header = $headerName; return $this; } /** * Set the header prefix. * * @param string $headerPrefix * @return $this */ public function setHeaderPrefix($headerPrefix) { $this->prefix = $headerPrefix; return $this; } } src/Http/Parser/Cookies.php 0000644 00000002037 15105647725 0011631 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Illuminate\Support\Facades\Crypt; use Tymon\JWTAuth\Contracts\Http\Parser as ParserContract; class Cookies implements ParserContract { use KeyTrait; /** * Decrypt or not the cookie while parsing. * * @var bool */ private $decrypt; public function __construct($decrypt = true) { $this->decrypt = $decrypt; } /** * Try to parse the token from the request cookies. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { if ($this->decrypt && $request->hasCookie($this->key)) { return Crypt::decrypt($request->cookie($this->key)); } return $request->cookie($this->key); } } src/Http/Parser/KeyTrait.php 0000644 00000001260 15105647725 0011766 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; trait KeyTrait { /** * The key. * * @var string */ protected $key = 'token'; /** * Set the key. * * @param string $key * @return $this */ public function setKey($key) { $this->key = $key; return $this; } /** * Get the key. * * @return string */ public function getKey() { return $this->key; } } src/Http/Parser/RouteParams.php 0000644 00000001667 15105647726 0012510 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Tymon\JWTAuth\Contracts\Http\Parser as ParserContract; class RouteParams implements ParserContract { use KeyTrait; /** * Try to get the token from the route parameters. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { $route = $request->route(); // Route may not be an instance of Illuminate\Routing\Route // (it's an array in Lumen <5.2) or not exist at all // (if the request was never dispatched) if (is_callable([$route, 'parameter'])) { return $route->parameter($this->key); } } } src/Http/Parser/Parser.php 0000644 00000004661 15105647726 0011477 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; class Parser { /** * The chain. * * @var array */ private $chain; /** * The request. * * @var \Illuminate\Http\Request */ protected $request; /** * Constructor. * * @param \Illuminate\Http\Request $request * @param array $chain * @return void */ public function __construct(Request $request, array $chain = []) { $this->request = $request; $this->chain = $chain; } /** * Get the parser chain. * * @return array */ public function getChain() { return $this->chain; } /** * Add a new parser to the chain. * * @param array|\Tymon\JWTAuth\Contracts\Http\Parser $parsers * @return $this */ public function addParser($parsers) { $this->chain = array_merge($this->chain, is_array($parsers) ? $parsers : [$parsers]); return $this; } /** * Set the order of the parser chain. * * @param array $chain * @return $this */ public function setChain(array $chain) { $this->chain = $chain; return $this; } /** * Alias for setting the order of the chain. * * @param array $chain * @return $this */ public function setChainOrder(array $chain) { return $this->setChain($chain); } /** * Iterate through the parsers and attempt to retrieve * a value, otherwise return null. * * @return string|null */ public function parseToken() { foreach ($this->chain as $parser) { if ($response = $parser->parse($this->request)) { return $response; } } } /** * Check whether a token exists in the chain. * * @return bool */ public function hasToken() { return $this->parseToken() !== null; } /** * Set the request instance. * * @param \Illuminate\Http\Request $request * @return $this */ public function setRequest(Request $request) { $this->request = $request; return $this; } } src/Http/Parser/LumenRouteParams.php 0000644 00000001564 15105647726 0013505 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Illuminate\Support\Arr; class LumenRouteParams extends RouteParams { /** * Try to get the token from the route parameters. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { // WARNING: Only use this parser if you know what you're doing! // It will only work with poorly-specified aspects of certain Lumen releases. // Route is the expected kind of array, and has a parameter with the key we want. return Arr::get($request->route(), '2.'.$this->key); } } src/Http/Parser/QueryString.php 0000644 00000001244 15105647726 0012531 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Parser; use Illuminate\Http\Request; use Tymon\JWTAuth\Contracts\Http\Parser as ParserContract; class QueryString implements ParserContract { use KeyTrait; /** * Try to parse the token from the request query string. * * @param \Illuminate\Http\Request $request * @return null|string */ public function parse(Request $request) { return $request->query($this->key); } } src/Http/Middleware/Authenticate.php 0000644 00000001326 15105647726 0013475 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Middleware; use Closure; /** @deprecated */ class Authenticate extends BaseMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function handle($request, Closure $next) { $this->authenticate($request); return $next($request); } } src/Http/Middleware/Check.php 0000644 00000001503 15105647726 0012071 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Middleware; use Closure; use Exception; /** @deprecated */ class Check extends BaseMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($this->auth->parser()->setRequest($request)->hasToken()) { try { $this->auth->parseToken()->authenticate(); } catch (Exception $e) { // } } return $next($request); } } src/Http/Middleware/RefreshToken.php 0000644 00000002242 15105647726 0013454 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Middleware; use Closure; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; use Tymon\JWTAuth\Exceptions\JWTException; /** @deprecated */ class RefreshToken extends BaseMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function handle($request, Closure $next) { $this->checkForToken($request); try { $token = $this->auth->parseToken()->refresh(); } catch (JWTException $e) { throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), $e, $e->getCode()); } $response = $next($request); // Send the refreshed token back to the client. return $this->setAuthenticationHeader($response, $token); } } src/Http/Middleware/BaseMiddleware.php 0000644 00000004602 15105647726 0013727 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Middleware; use Illuminate\Http\Request; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\JWTAuth; /** @deprecated */ abstract class BaseMiddleware { /** * The JWT Authenticator. * * @var \Tymon\JWTAuth\JWTAuth */ protected $auth; /** * Create a new BaseMiddleware instance. * * @param \Tymon\JWTAuth\JWTAuth $auth * @return void */ public function __construct(JWTAuth $auth) { $this->auth = $auth; } /** * Check the request for the presence of a token. * * @param \Illuminate\Http\Request $request * @return void * * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException */ public function checkForToken(Request $request) { if (! $this->auth->parser()->setRequest($request)->hasToken()) { throw new UnauthorizedHttpException('jwt-auth', 'Token not provided'); } } /** * Attempt to authenticate a user via the token in the request. * * @param \Illuminate\Http\Request $request * @return void * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function authenticate(Request $request) { $this->checkForToken($request); try { if (! $this->auth->parseToken()->authenticate()) { throw new UnauthorizedHttpException('jwt-auth', 'User not found'); } } catch (JWTException $e) { throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), $e, $e->getCode()); } } /** * Set the authentication header. * * @param \Illuminate\Http\Response|\Illuminate\Http\JsonResponse $response * @param string|null $token * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ protected function setAuthenticationHeader($response, $token = null) { $token = $token ?: $this->auth->refresh(); $response->headers->set('Authorization', 'Bearer '.$token); return $response; } } src/Http/Middleware/AuthenticateAndRenew.php 0000644 00000001526 15105647727 0015124 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth\Http\Middleware; use Closure; /** @deprecated */ class AuthenticateAndRenew extends BaseMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException */ public function handle($request, Closure $next) { $this->authenticate($request); $response = $next($request); // Send the refreshed token back to the client. return $this->setAuthenticationHeader($response); } } src/JWTAuth.php 0000644 00000003652 15105647727 0007356 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use Tymon\JWTAuth\Contracts\Providers\Auth; use Tymon\JWTAuth\Http\Parser\Parser; /** @deprecated */ class JWTAuth extends JWT { /** * The authentication provider. * * @var \Tymon\JWTAuth\Contracts\Providers\Auth */ protected $auth; /** * Constructor. * * @param \Tymon\JWTAuth\Manager $manager * @param \Tymon\JWTAuth\Contracts\Providers\Auth $auth * @param \Tymon\JWTAuth\Http\Parser\Parser $parser * @return void */ public function __construct(Manager $manager, Auth $auth, Parser $parser) { parent::__construct($manager, $parser); $this->auth = $auth; } /** * Attempt to authenticate the user and return the token. * * @param array $credentials * @return false|string */ public function attempt(array $credentials) { if (! $this->auth->byCredentials($credentials)) { return false; } return $this->fromUser($this->user()); } /** * Authenticate a user via a token. * * @return \Tymon\JWTAuth\Contracts\JWTSubject|false */ public function authenticate() { $id = $this->getPayload()->get('sub'); if (! $this->auth->byId($id)) { return false; } return $this->user(); } /** * Alias for authenticate(). * * @return \Tymon\JWTAuth\Contracts\JWTSubject|false */ public function toUser() { return $this->authenticate(); } /** * Get the authenticated user. * * @return \Tymon\JWTAuth\Contracts\JWTSubject */ public function user() { return $this->auth->user(); } } src/Manager.php 0000644 00000013220 15105647727 0007432 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Tymon\JWTAuth; use Tymon\JWTAuth\Contracts\Providers\JWT as JWTContract; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Exceptions\TokenBlacklistedException; use Tymon\JWTAuth\Support\CustomClaims; use Tymon\JWTAuth\Support\RefreshFlow; class Manager { use CustomClaims, RefreshFlow; /** * The provider. * * @var \Tymon\JWTAuth\Contracts\Providers\JWT */ protected $provider; /** * The blacklist. * * @var \Tymon\JWTAuth\Blacklist */ protected $blacklist; /** * the payload factory. * * @var \Tymon\JWTAuth\Factory */ protected $payloadFactory; /** * The blacklist flag. * * @var bool */ protected $blacklistEnabled = true; /** * the persistent claims. * * @var array */ protected $persistentClaims = []; /** * Constructor. * * @param \Tymon\JWTAuth\Contracts\Providers\JWT $provider * @param \Tymon\JWTAuth\Blacklist $blacklist * @param \Tymon\JWTAuth\Factory $payloadFactory * @return void */ public function __construct(JWTContract $provider, Blacklist $blacklist, Factory $payloadFactory) { $this->provider = $provider; $this->blacklist = $blacklist; $this->payloadFactory = $payloadFactory; } /** * Encode a Payload and return the Token. * * @param \Tymon\JWTAuth\Payload $payload * @return \Tymon\JWTAuth\Token */ public function encode(Payload $payload) { $token = $this->provider->encode($payload->get()); return new Token($token); } /** * Decode a Token and return the Payload. * * @param \Tymon\JWTAuth\Token $token * @param bool $checkBlacklist * @return \Tymon\JWTAuth\Payload * * @throws \Tymon\JWTAuth\Exceptions\TokenBlacklistedException */ public function decode(Token $token, $checkBlacklist = true) { $payloadArray = $this->provider->decode($token->get()); $payload = $this->payloadFactory ->setRefreshFlow($this->refreshFlow) ->customClaims($payloadArray) ->make(); if ($checkBlacklist && $this->blacklistEnabled && $this->blacklist->has($payload)) { throw new TokenBlacklistedException('The token has been blacklisted'); } return $payload; } /** * Refresh a Token and return a new Token. * * @param \Tymon\JWTAuth\Token $token * @param bool $forceForever * @param bool $resetClaims * @return \Tymon\JWTAuth\Token */ public function refresh(Token $token, $forceForever = false, $resetClaims = false) { $this->setRefreshFlow(); $claims = $this->buildRefreshClaims($this->decode($token)); if ($this->blacklistEnabled) { // Invalidate old token $this->invalidate($token, $forceForever); } // Return the new token return $this->encode( $this->payloadFactory->customClaims($claims)->make($resetClaims) ); } /** * Invalidate a Token by adding it to the blacklist. * * @param \Tymon\JWTAuth\Token $token * @param bool $forceForever * @return bool * * @throws \Tymon\JWTAuth\Exceptions\JWTException */ public function invalidate(Token $token, $forceForever = false) { if (! $this->blacklistEnabled) { throw new JWTException('You must have the blacklist enabled to invalidate a token.'); } return call_user_func( [$this->blacklist, $forceForever ? 'addForever' : 'add'], $this->decode($token, false) ); } /** * Build the claims to go into the refreshed token. * * @param \Tymon\JWTAuth\Payload $payload * @return array */ protected function buildRefreshClaims(Payload $payload) { // Get the claims to be persisted from the payload $persistentClaims = collect($payload->toArray()) ->only($this->persistentClaims) ->toArray(); // persist the relevant claims return array_merge( $this->customClaims, $persistentClaims, [ 'sub' => $payload['sub'], 'iat' => $payload['iat'], ] ); } /** * Get the Payload Factory instance. * * @return \Tymon\JWTAuth\Factory */ public function getPayloadFactory() { return $this->payloadFactory; } /** * Get the JWTProvider instance. * * @return \Tymon\JWTAuth\Contracts\Providers\JWT */ public function getJWTProvider() { return $this->provider; } /** * Get the Blacklist instance. * * @return \Tymon\JWTAuth\Blacklist */ public function getBlacklist() { return $this->blacklist; } /** * Set whether the blacklist is enabled. * * @param bool $enabled * @return $this */ public function setBlacklistEnabled($enabled) { $this->blacklistEnabled = $enabled; return $this; } /** * Set the claims to be persisted when refreshing a token. * * @param array $claims * @return $this */ public function setPersistentClaims(array $claims) { $this->persistentClaims = $claims; return $this; } } LICENSE 0000644 00000002060 15105647727 0005565 0 ustar 00 The MIT License (MIT) Copyright (c) Sean Tymon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. composer.json 0000644 00000004262 15105647727 0007310 0 ustar 00 { "name": "tymon/jwt-auth", "description": "JSON Web Token Authentication for Laravel and Lumen", "keywords": [ "auth", "authentication", "json web token", "jwt", "laravel" ], "homepage": "https://github.com/tymondesigns/jwt-auth", "support": { "issues": "https://github.com/tymondesigns/jwt-auth/issues", "source": "https://github.com/tymondesigns/jwt-auth" }, "license": "MIT", "authors": [ { "name": "Sean Tymon", "email": "tymon148@gmail.com", "homepage": "https://tymon.xyz", "role": "Developer" } ], "require": { "php": "^8.0", "illuminate/auth": "^9.0|^10.0", "illuminate/contracts": "^9.0|^10.0", "illuminate/http": "^9.0|^10.0", "illuminate/support": "^9.0|^10.0", "lcobucci/jwt": "^4.0", "nesbot/carbon": "^2.0" }, "require-dev": { "illuminate/console": "^9.0|^10.0", "illuminate/database": "^9.0|^10.0", "illuminate/routing": "^9.0|^10.0", "mockery/mockery": ">=0.9.9", "phpunit/phpunit": "^9.4" }, "autoload": { "psr-4": { "Tymon\\JWTAuth\\": "src/" } }, "autoload-dev": { "psr-4": { "Tymon\\JWTAuth\\Test\\": "tests/" } }, "extra": { "branch-alias": { "dev-develop": "1.0-dev", "dev-2.x": "2.0-dev" }, "laravel": { "aliases": { "JWTAuth": "Tymon\\JWTAuth\\Facades\\JWTAuth", "JWTFactory": "Tymon\\JWTAuth\\Facades\\JWTFactory" }, "providers": [ "Tymon\\JWTAuth\\Providers\\LaravelServiceProvider" ] } }, "funding": [ { "type": "patreon", "url": "https://www.patreon.com/seantymon" } ], "config": { "sort-packages": true }, "prefer-stable": true, "minimum-stability": "dev", "scripts": { "test": "phpunit --colors=always", "test:ci": "composer test -- --verbose --coverage-text --coverage-clover=coverage.xml" } } config/config.php 0000644 00000023303 15105647727 0010006 0 ustar 00 <?php /* * This file is part of jwt-auth. * * (c) Sean Tymon <tymon148@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ return [ /* |-------------------------------------------------------------------------- | JWT Authentication Secret |-------------------------------------------------------------------------- | | Don't forget to set this in your .env file, as it will be used to sign | your tokens. A helper command is provided for this: | `php artisan jwt:secret` | | Note: This will be used for Symmetric algorithms only (HMAC), | since RSA and ECDSA use a private/public key combo (See below). | */ 'secret' => env('JWT_SECRET'), /* |-------------------------------------------------------------------------- | JWT Authentication Keys |-------------------------------------------------------------------------- | | The algorithm you are using, will determine whether your tokens are | signed with a random string (defined in `JWT_SECRET`) or using the | following public & private keys. | | Symmetric Algorithms: | HS256, HS384 & HS512 will use `JWT_SECRET`. | | Asymmetric Algorithms: | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below. | */ 'keys' => [ /* |-------------------------------------------------------------------------- | Public Key |-------------------------------------------------------------------------- | | A path or resource to your public key. | | E.g. 'file://path/to/public/key' | */ 'public' => env('JWT_PUBLIC_KEY'), /* |-------------------------------------------------------------------------- | Private Key |-------------------------------------------------------------------------- | | A path or resource to your private key. | | E.g. 'file://path/to/private/key' | */ 'private' => env('JWT_PRIVATE_KEY'), /* |-------------------------------------------------------------------------- | Passphrase |-------------------------------------------------------------------------- | | The passphrase for your private key. Can be null if none set. | */ 'passphrase' => env('JWT_PASSPHRASE'), ], /* |-------------------------------------------------------------------------- | JWT time to live |-------------------------------------------------------------------------- | | Specify the length of time (in minutes) that the token will be valid for. | Defaults to 1 hour. | | You can also set this to null, to yield a never expiring token. | Some people may want this behaviour for e.g. a mobile app. | This is not particularly recommended, so make sure you have appropriate | systems in place to revoke the token if necessary. | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list. | */ 'ttl' => env('JWT_TTL', 60), /* |-------------------------------------------------------------------------- | Refresh time to live |-------------------------------------------------------------------------- | | Specify the length of time (in minutes) that the token can be refreshed | within. I.E. The user can refresh their token within a 2 week window of | the original token being created until they must re-authenticate. | Defaults to 2 weeks. | | You can also set this to null, to yield an infinite refresh time. | Some may want this instead of never expiring tokens for e.g. a mobile app. | This is not particularly recommended, so make sure you have appropriate | systems in place to revoke the token if necessary. | */ 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), /* |-------------------------------------------------------------------------- | JWT hashing algorithm |-------------------------------------------------------------------------- | | Specify the hashing algorithm that will be used to sign the token. | */ 'algo' => env('JWT_ALGO', Tymon\JWTAuth\Providers\JWT\Provider::ALGO_HS256), /* |-------------------------------------------------------------------------- | Required Claims |-------------------------------------------------------------------------- | | Specify the required claims that must exist in any token. | A TokenInvalidException will be thrown if any of these claims are not | present in the payload. | */ 'required_claims' => [ 'iss', 'iat', 'exp', 'nbf', 'sub', 'jti', ], /* |-------------------------------------------------------------------------- | Persistent Claims |-------------------------------------------------------------------------- | | Specify the claim keys to be persisted when refreshing a token. | `sub` and `iat` will automatically be persisted, in | addition to the these claims. | | Note: If a claim does not exist then it will be ignored. | */ 'persistent_claims' => [ // 'foo', // 'bar', ], /* |-------------------------------------------------------------------------- | Lock Subject |-------------------------------------------------------------------------- | | This will determine whether a `prv` claim is automatically added to | the token. The purpose of this is to ensure that if you have multiple | authentication models e.g. `App\User` & `App\OtherPerson`, then we | should prevent one authentication request from impersonating another, | if 2 tokens happen to have the same id across the 2 different models. | | Under specific circumstances, you may want to disable this behaviour | e.g. if you only have one authentication model, then you would save | a little on token size. | */ 'lock_subject' => true, /* |-------------------------------------------------------------------------- | Leeway |-------------------------------------------------------------------------- | | This property gives the jwt timestamp claims some "leeway". | Meaning that if you have any unavoidable slight clock skew on | any of your servers then this will afford you some level of cushioning. | | This applies to the claims `iat`, `nbf` and `exp`. | | Specify in seconds - only if you know you need it. | */ 'leeway' => env('JWT_LEEWAY', 0), /* |-------------------------------------------------------------------------- | Blacklist Enabled |-------------------------------------------------------------------------- | | In order to invalidate tokens, you must have the blacklist enabled. | If you do not want or need this functionality, then set this to false. | */ 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), /* | ------------------------------------------------------------------------- | Blacklist Grace Period | ------------------------------------------------------------------------- | | When multiple concurrent requests are made with the same JWT, | it is possible that some of them fail, due to token regeneration | on every request. | | Set grace period in seconds to prevent parallel request failure. | */ 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), /* |-------------------------------------------------------------------------- | Cookies encryption |-------------------------------------------------------------------------- | | By default Laravel encrypt cookies for security reason. | If you decide to not decrypt cookies, you will have to configure Laravel | to not encrypt your cookie token by adding its name into the $except | array available in the middleware "EncryptCookies" provided by Laravel. | see https://laravel.com/docs/master/responses#cookies-and-encryption | for details. | | Set it to true if you want to decrypt cookies. | */ 'decrypt_cookies' => false, /* |-------------------------------------------------------------------------- | Providers |-------------------------------------------------------------------------- | | Specify the various providers used throughout the package. | */ 'providers' => [ /* |-------------------------------------------------------------------------- | JWT Provider |-------------------------------------------------------------------------- | | Specify the provider that is used to create and decode the tokens. | */ 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, /* |-------------------------------------------------------------------------- | Authentication Provider |-------------------------------------------------------------------------- | | Specify the provider that is used to authenticate users. | */ 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, /* |-------------------------------------------------------------------------- | Storage Provider |-------------------------------------------------------------------------- | | Specify the provider that is used to store tokens in the blacklist. | */ 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, ], ];
Simpan