Laravel version update

Laravel version update
This commit is contained in:
Manish Verma
2018-08-06 18:48:58 +05:30
parent d143048413
commit 126fbb0255
13678 changed files with 1031482 additions and 778530 deletions

View File

@@ -11,15 +11,25 @@
namespace Tymon\JWTAuth;
use Tymon\JWTAuth\Providers\Storage\StorageInterface;
use Tymon\JWTAuth\Support\Utils;
use Tymon\JWTAuth\Contracts\Providers\Storage;
class Blacklist
{
/**
* @var \Tymon\JWTAuth\Providers\Storage\StorageInterface
* 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.
*
@@ -28,9 +38,20 @@ class Blacklist
protected $refreshTTL = 20160;
/**
* @param \Tymon\JWTAuth\Providers\Storage\StorageInterface $storage
* The unique key held within the blacklist.
*
* @var string
*/
public function __construct(StorageInterface $storage)
protected $key = 'jti';
/**
* Constructor.
*
* @param \Tymon\JWTAuth\Contracts\Providers\Storage $storage
*
* @return void
*/
public function __construct(Storage $storage)
{
$this->storage = $storage;
}
@@ -39,26 +60,54 @@ class Blacklist
* Add the token (jti claim) to the blacklist.
*
* @param \Tymon\JWTAuth\Payload $payload
*
* @return bool
*/
public function add(Payload $payload)
{
$exp = Utils::timestamp($payload['exp']);
$refreshExp = Utils::timestamp($payload['iat'])->addMinutes($this->refreshTTL);
// there is no need to add the token to the blacklist
// if the token has already expired AND the refresh_ttl
// has gone by
if ($exp->isPast() && $refreshExp->isPast()) {
return false;
// if there is no exp claim then add the jwt to
// the blacklist indefinitely
if (! $payload->hasKey('exp')) {
return $this->addForever($payload);
}
// Set the cache entry's lifetime to be equal to the amount
// of refreshable time it has remaining (which is the larger
// of `exp` and `iat+refresh_ttl`), rounded up a minute
$cacheLifetime = $exp->max($refreshExp)->addMinute()->diffInMinutes();
$this->storage->add(
$this->getKey($payload),
['valid_until' => $this->getGraceTimestamp()],
$this->getMinutesUntilExpired($payload)
);
$this->storage->add($payload['jti'], [], $cacheLifetime);
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()->diffInMinutes();
}
/**
* 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;
}
@@ -67,22 +116,32 @@ class Blacklist
* Determine whether the token has been blacklisted.
*
* @param \Tymon\JWTAuth\Payload $payload
*
* @return bool
*/
public function has(Payload $payload)
{
return $this->storage->has($payload['jti']);
$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($payload['jti']);
return $this->storage->destroy($this->getKey($payload));
}
/**
@@ -97,10 +156,71 @@ class Blacklist
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
* @param int $ttl
*
* @return $this
*/
@@ -110,4 +230,14 @@ class Blacklist
return $this;
}
/**
* Get the refresh time limit.
*
* @return int
*/
public function getRefreshTTL()
{
return $this->refreshTTL;
}
}

View File

@@ -14,9 +14,7 @@ namespace Tymon\JWTAuth\Claims;
class Audience extends Claim
{
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'aud';
}

View File

@@ -11,9 +11,12 @@
namespace Tymon\JWTAuth\Claims;
use Tymon\JWTAuth\Exceptions\InvalidClaimException;
use JsonSerializable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Arrayable;
use Tymon\JWTAuth\Contracts\Claim as ClaimContract;
abstract class Claim implements ClaimInterface
abstract class Claim implements Arrayable, ClaimContract, Jsonable, JsonSerializable
{
/**
* The claim name.
@@ -30,7 +33,9 @@ abstract class Claim implements ClaimInterface
private $value;
/**
* @param mixed $value
* @param mixed $value
*
* @return void
*/
public function __construct($value)
{
@@ -38,19 +43,17 @@ abstract class Claim implements ClaimInterface
}
/**
* Set the claim value, and call a validate method if available.
* Set the claim value, and call a validate method.
*
* @param mixed $value
*
* @param $value
* @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException
*
* @return $this
*/
public function setValue($value)
{
if (! $this->validate($value)) {
throw new InvalidClaimException('Invalid value provided for claim "'.$this->getName().'": '.$value);
}
$this->value = $value;
$this->value = $this->validateCreate($value);
return $this;
}
@@ -68,7 +71,8 @@ abstract class Claim implements ClaimInterface
/**
* Set the claim name.
*
* @param string $name
* @param string $name
*
* @return $this
*/
public function setName($name)
@@ -89,14 +93,60 @@ abstract class Claim implements ClaimInterface
}
/**
* Validate the Claim value.
* Validate the claim in a standalone Claim context.
*
* @param mixed $value
*
* @param $value
* @return bool
*/
protected function validate($value)
public function validateCreate($value)
{
return true;
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
*/
public function jsonSerialize()
{
return $this->toArray();
}
/**
@@ -110,12 +160,24 @@ abstract class Claim implements ClaimInterface
}
/**
* Get the claim as a string.
* 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 json_encode($this->toArray(), JSON_UNESCAPED_SLASHES);
return $this->toJson();
}
}

View File

@@ -0,0 +1,121 @@
<?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\Str;
use Illuminate\Support\Collection as IlluminateCollection;
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;
}
}

View File

@@ -14,8 +14,10 @@ namespace Tymon\JWTAuth\Claims;
class Custom extends Claim
{
/**
* @param string $name
* @param mixed $value
* @param string $name
* @param mixed $value
*
* @return void
*/
public function __construct($name, $value)
{

View File

@@ -0,0 +1,99 @@
<?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\Support\Utils;
use Tymon\JWTAuth\Exceptions\InvalidClaimException;
trait DatetimeTrait
{
/**
* Time leeway in seconds.
*
* @var int
*/
protected $leeway = 0;
/**
* Set the claim value, and call a validate method.
*
* @param mixed $value
*
* @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException
*
* @return $this
*/
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;
}
}

View File

@@ -11,23 +11,24 @@
namespace Tymon\JWTAuth\Claims;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class Expiration extends Claim
{
use DatetimeTrait;
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'exp';
/**
* Validate the expiry claim.
*
* @param mixed $value
* @return bool
* {@inheritdoc}
*/
protected function validate($value)
public function validatePayload()
{
return is_numeric($value);
if ($this->isPast($this->getValue())) {
throw new TokenExpiredException('Token has expired');
}
}
}

View File

@@ -11,32 +11,76 @@
namespace Tymon\JWTAuth\Claims;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
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 static $classMap = [
'aud' => 'Tymon\JWTAuth\Claims\Audience',
'exp' => 'Tymon\JWTAuth\Claims\Expiration',
'iat' => 'Tymon\JWTAuth\Claims\IssuedAt',
'iss' => 'Tymon\JWTAuth\Claims\Issuer',
'jti' => 'Tymon\JWTAuth\Claims\JwtId',
'nbf' => 'Tymon\JWTAuth\Claims\NotBefore',
'sub' => 'Tymon\JWTAuth\Claims\Subject',
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
* @param mixed $value
*
* @return \Tymon\JWTAuth\Claims\Claim
*/
public function get($name, $value)
{
if ($this->has($name)) {
return new self::$classMap[$name]($value);
$claim = new $this->classMap[$name]($value);
return method_exists($claim, 'setLeeway') ?
$claim->setLeeway($this->leeway) :
$claim;
}
return new Custom($name, $value);
@@ -46,10 +90,140 @@ class Factory
* Check whether the claim exists.
*
* @param string $name
*
* @return bool
*/
public function has($name)
{
return array_key_exists($name, self::$classMap);
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;
}
}

View File

@@ -11,23 +11,52 @@
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;
}
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'iat';
/**
* Validate the issued at claim.
*
* @param mixed $value
* @return bool
* {@inheritdoc}
*/
protected function validate($value)
public function validateCreate($value)
{
return is_numeric($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');
}
}
}

View File

@@ -14,9 +14,7 @@ namespace Tymon\JWTAuth\Claims;
class Issuer extends Claim
{
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'iss';
}

View File

@@ -14,9 +14,7 @@ namespace Tymon\JWTAuth\Claims;
class JwtId extends Claim
{
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'jti';
}

View File

@@ -11,23 +11,41 @@
namespace Tymon\JWTAuth\Claims;
use Tymon\JWTAuth\Exceptions\InvalidClaimException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class NotBefore extends Claim
{
use DatetimeTrait {
validateCreate as commonValidateCreate;
}
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'nbf';
/**
* Validate the not before claim.
*
* @param mixed $value
* @return bool
* {@inheritdoc}
*/
protected function validate($value)
public function validateCreate($value)
{
return is_numeric($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('Not Before (nbf) timestamp cannot be in the future');
}
}
}

View File

@@ -14,9 +14,7 @@ namespace Tymon\JWTAuth\Claims;
class Subject extends Claim
{
/**
* The claim name.
*
* @var string
* {@inheritdoc}
*/
protected $name = 'sub';
}

View File

@@ -1,81 +0,0 @@
<?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\Commands;
use Illuminate\Support\Str;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
class JWTGenerateCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'jwt:generate';
/**
* 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 fire()
{
$key = $this->getRandomKey();
if ($this->option('show')) {
return $this->line('<comment>'.$key.'</comment>');
}
$path = config_path('jwt.php');
if (file_exists($path)) {
file_put_contents($path, str_replace(
$this->laravel['config']['jwt.secret'], $key, file_get_contents($path)
));
}
$this->laravel['config']['jwt.secret'] = $key;
$this->info("jwt-auth secret [$key] set successfully.");
}
/**
* Generate a random key for the JWT Auth secret.
*
* @return string
*/
protected function getRandomKey()
{
return Str::random(32);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['show', null, InputOption::VALUE_NONE, 'Simply display the key instead of modifying files.'],
];
}
}

View File

@@ -0,0 +1,118 @@
<?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\Support\Str;
use Illuminate\Console\Command;
class JWTGenerateSecretCommand extends Command
{
/**
* The console command signature.
*
* @var string
*/
protected $signature = 'jwt:secret
{--s|show : Display the key instead of modifying files.}
{--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(32);
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) {
// update existing entry
file_put_contents($path, PHP_EOL."JWT_SECRET=$key", FILE_APPEND);
} else {
if ($this->isConfirmed() === false) {
$this->comment('Phew... No changes were made to your secret key.');
return;
}
// create new 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');
}
}

View File

@@ -9,15 +9,18 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Claims;
namespace Tymon\JWTAuth\Contracts;
interface ClaimInterface
interface Claim
{
/**
* Set the claim value, and call a validate method if available.
* Set the claim value, and call a validate method.
*
* @param mixed
* @return Claim
* @param mixed $value
*
* @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException
*
* @return $this
*/
public function setValue($value);
@@ -31,8 +34,9 @@ interface ClaimInterface
/**
* Set the claim name.
*
* @param string $name
* @return Claim
* @param string $name
*
* @return $this
*/
public function setName($name);
@@ -42,4 +46,13 @@ interface ClaimInterface
* @return string
*/
public function getName();
/**
* Validate the Claim value.
*
* @param mixed $value
*
* @return bool
*/
public function validateCreate($value);
}

View File

@@ -0,0 +1,26 @@
<?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);
}

View File

@@ -0,0 +1,29 @@
<?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();
}

View File

@@ -9,23 +9,25 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Providers\Auth;
namespace Tymon\JWTAuth\Contracts\Providers;
interface AuthInterface
interface Auth
{
/**
* Check a user's credentials.
*
* @param array $credentials
* @return bool
*
* @return mixed
*/
public function byCredentials(array $credentials = []);
public function byCredentials(array $credentials);
/**
* Authenticate a user via the id.
*
* @param mixed $id
* @return bool
*
* @return mixed
*/
public function byId($id);

View File

@@ -9,18 +9,20 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Providers\JWT;
namespace Tymon\JWTAuth\Contracts\Providers;
interface JWTInterface
interface JWT
{
/**
* @param array $payload
*
* @return string
*/
public function encode(array $payload);
/**
* @param string $token
*
* @return array
*/
public function decode($token);

View File

@@ -9,25 +9,37 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Providers\Storage;
namespace Tymon\JWTAuth\Contracts\Providers;
interface StorageInterface
interface Storage
{
/**
* @param string $key
* @param int $minutes
* @param string $key
* @param mixed $value
* @param int $minutes
*
* @return void
*/
public function add($key, $value, $minutes);
/**
* @param string $key
* @return bool
* @param string $key
* @param mixed $value
*
* @return void
*/
public function has($key);
public function forever($key, $value);
/**
* @param string $key
* @param string $key
*
* @return mixed
*/
public function get($key);
/**
* @param string $key
*
* @return bool
*/
public function destroy($key);

View File

@@ -9,14 +9,15 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Validators;
namespace Tymon\JWTAuth\Contracts;
interface ValidatorInterface
interface Validator
{
/**
* Perform some checks on the value.
*
* @param mixed $value
*
* @return void
*/
public function check($value);
@@ -25,6 +26,7 @@ interface ValidatorInterface
* Helper function to return a boolean.
*
* @param array $value
*
* @return bool
*/
public function isValid($value);

View File

@@ -11,10 +11,22 @@
namespace Tymon\JWTAuth\Exceptions;
use Exception;
use Tymon\JWTAuth\Claims\Claim;
class InvalidClaimException extends JWTException
{
/**
* @var int
* Constructor.
*
* @param \Tymon\JWTAuth\Claims\Claim $claim
* @param int $code
* @param \Exception|null $previous
*
* @return void
*/
protected $statusCode = 400;
public function __construct(Claim $claim, $code = 0, Exception $previous = null)
{
parent::__construct('Invalid value provided for claim ['.$claim->getName().']', $code, $previous);
}
}

View File

@@ -11,39 +11,12 @@
namespace Tymon\JWTAuth\Exceptions;
class JWTException extends \Exception
use Exception;
class JWTException extends Exception
{
/**
* @var int
* {@inheritdoc}
*/
protected $statusCode = 500;
/**
* @param string $message
* @param int $statusCode
*/
public function __construct($message = 'An error occurred', $statusCode = null)
{
parent::__construct($message);
if (! is_null($statusCode)) {
$this->setStatusCode($statusCode);
}
}
/**
* @param int $statusCode
*/
public function setStatusCode($statusCode)
{
$this->statusCode = $statusCode;
}
/**
* @return int the status code
*/
public function getStatusCode()
{
return $this->statusCode;
}
protected $message = 'An error occurred';
}

View File

@@ -13,8 +13,5 @@ namespace Tymon\JWTAuth\Exceptions;
class PayloadException extends JWTException
{
/**
* @var int
*/
protected $statusCode = 500;
//
}

View File

@@ -13,8 +13,5 @@ namespace Tymon\JWTAuth\Exceptions;
class TokenBlacklistedException extends TokenInvalidException
{
/**
* @var int
*/
protected $statusCode = 401;
//
}

View File

@@ -13,8 +13,5 @@ namespace Tymon\JWTAuth\Exceptions;
class TokenExpiredException extends JWTException
{
/**
* @var int
*/
protected $statusCode = 401;
//
}

View File

@@ -13,8 +13,5 @@ namespace Tymon\JWTAuth\Exceptions;
class TokenInvalidException extends JWTException
{
/**
* @var int
*/
protected $statusCode = 400;
//
}

View File

@@ -0,0 +1,17 @@
<?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
{
//
}

View File

@@ -0,0 +1,27 @@
<?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';
}
}

262
vendor/tymon/jwt-auth/src/Factory.php vendored Normal file
View File

@@ -0,0 +1,262 @@
<?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\Support\RefreshFlow;
use Tymon\JWTAuth\Support\CustomClaims;
use Tymon\JWTAuth\Validators\PayloadValidator;
use Tymon\JWTAuth\Claims\Factory as ClaimFactory;
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();
}
$payload = $this->withClaims($this->buildClaimsCollection());
return $payload;
}
/**
* 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;
}
}

View File

@@ -0,0 +1,34 @@
<?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;
class Authenticate extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->authenticate($request);
return $next($request);
}
}

View File

@@ -0,0 +1,37 @@
<?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;
class AuthenticateAndRenew extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->authenticate($request);
$response = $next($request);
// Send the refreshed token back to the client.
return $this->setAuthenticationHeader($response);
}
}

View File

@@ -0,0 +1,93 @@
<?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 Tymon\JWTAuth\JWTAuth;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
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
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
*
* @return void
*/
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
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return void
*/
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;
}
}

View File

@@ -0,0 +1,39 @@
<?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;
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);
}
}

View File

@@ -0,0 +1,45 @@
<?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 Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class RefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @return mixed
*/
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);
}
}

View File

@@ -0,0 +1,88 @@
<?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 && preg_match('/'.$this->prefix.'\s*(\S+)\b/i', $header, $matches)) {
return $matches[1];
}
}
/**
* 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;
}
}

View File

@@ -0,0 +1,49 @@
<?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);
}
}

View File

@@ -0,0 +1,32 @@
<?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);
}
}

View File

@@ -0,0 +1,46 @@
<?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;
}
}

View File

@@ -0,0 +1,33 @@
<?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\Support\Arr;
use Illuminate\Http\Request;
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);
}
}

View File

@@ -0,0 +1,120 @@
<?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;
}
/**
* 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;
}
}

View File

@@ -0,0 +1,32 @@
<?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);
}
}

View File

@@ -0,0 +1,39 @@
<?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);
}
}
}

421
vendor/tymon/jwt-auth/src/JWT.php vendored Normal file
View File

@@ -0,0 +1,421 @@
<?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\Http\Parser\Parser;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Tymon\JWTAuth\Support\CustomClaims;
use Tymon\JWTAuth\Exceptions\JWTException;
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.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return \Tymon\JWTAuth\Payload
*/
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.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return $this
*/
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.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return void
*/
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
*
* @throws \BadMethodCallException
*
* @return mixed
*/
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.");
}
}

View File

@@ -11,331 +11,82 @@
namespace Tymon\JWTAuth;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Providers\Auth\AuthInterface;
use Tymon\JWTAuth\Providers\User\UserInterface;
use Tymon\JWTAuth\Http\Parser\Parser;
use Tymon\JWTAuth\Contracts\Providers\Auth;
class JWTAuth
class JWTAuth extends JWT
{
/**
* @var \Tymon\JWTAuth\JWTManager
*/
protected $manager;
/**
* @var \Tymon\JWTAuth\Providers\User\UserInterface
*/
protected $user;
/**
* @var \Tymon\JWTAuth\Providers\Auth\AuthInterface
* The authentication provider.
*
* @var \Tymon\JWTAuth\Contracts\Providers\Auth
*/
protected $auth;
/**
* @var \Illuminate\Http\Request
* Constructor.
*
* @param \Tymon\JWTAuth\Manager $manager
* @param \Tymon\JWTAuth\Contracts\Providers\Auth $auth
* @param \Tymon\JWTAuth\Http\Parser\Parser $parser
*
* @return void
*/
protected $request;
/**
* @var string
*/
protected $identifier = 'id';
/**
* @var \Tymon\JWTAuth\Token
*/
protected $token;
/**
* @param \Tymon\JWTAuth\JWTManager $manager
* @param \Tymon\JWTAuth\Providers\User\UserInterface $user
* @param \Tymon\JWTAuth\Providers\Auth\AuthInterface $auth
* @param \Illuminate\Http\Request $request
*/
public function __construct(JWTManager $manager, UserInterface $user, AuthInterface $auth, Request $request)
public function __construct(Manager $manager, Auth $auth, Parser $parser)
{
$this->manager = $manager;
$this->user = $user;
parent::__construct($manager, $parser);
$this->auth = $auth;
$this->request = $request;
}
/**
* Find a user using the user identifier in the subject claim.
*
* @param bool|string $token
*
* @return mixed
*/
public function toUser($token = false)
{
$payload = $this->getPayload($token);
if (! $user = $this->user->getBy($this->identifier, $payload['sub'])) {
return false;
}
return $user;
}
/**
* Generate a token using the user identifier as the subject claim.
*
* @param mixed $user
* @param array $customClaims
*
* @return string
*/
public function fromUser($user, array $customClaims = [])
{
$payload = $this->makePayload($user->{$this->identifier}, $customClaims);
return $this->manager->encode($payload)->get();
}
/**
* Attempt to authenticate the user and return the token.
*
* @param array $credentials
* @param array $customClaims
* @param array $credentials
*
* @return false|string
*/
public function attempt(array $credentials = [], array $customClaims = [])
public function attempt(array $credentials)
{
if (! $this->auth->byCredentials($credentials)) {
return false;
}
return $this->fromUser($this->auth->user(), $customClaims);
return $this->fromUser($this->user());
}
/**
* Authenticate a user via a token.
*
* @param mixed $token
*
* @return mixed
* @return \Tymon\JWTAuth\Contracts\JWTSubject|false
*/
public function authenticate($token = false)
public function authenticate()
{
$id = $this->getPayload($token)->get('sub');
$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();
}
/**
* Refresh an expired token.
*
* @param mixed $token
*
* @return string
*/
public function refresh($token = false)
{
$this->requireToken($token);
return $this->manager->refresh($this->token)->get();
}
/**
* Invalidate a token (add it to the blacklist).
*
* @param mixed $token
*
* @return bool
*/
public function invalidate($token = false)
{
$this->requireToken($token);
return $this->manager->invalidate($this->token);
}
/**
* Get the token.
*
* @return bool|string
*/
public function getToken()
{
if (! $this->token) {
try {
$this->parseToken();
} catch (JWTException $e) {
return false;
}
}
return $this->token;
}
/**
* Get the raw Payload instance.
*
* @param mixed $token
*
* @return \Tymon\JWTAuth\Payload
*/
public function getPayload($token = false)
{
$this->requireToken($token);
return $this->manager->decode($this->token);
}
/**
* Parse the token from the request.
*
* @param string $query
*
* @return JWTAuth
*/
public function parseToken($method = 'bearer', $header = 'authorization', $query = 'token')
{
if (! $token = $this->parseAuthHeader($header, $method)) {
if (! $token = $this->request->query($query, false)) {
throw new JWTException('The token could not be parsed from the request', 400);
}
}
return $this->setToken($token);
}
/**
* Parse token from the authorization header.
*
* @param string $header
* @param string $method
*
* @return false|string
*/
protected function parseAuthHeader($header = 'authorization', $method = 'bearer')
{
$header = $this->request->headers->get($header);
if (! starts_with(strtolower($header), $method)) {
return false;
}
return trim(str_ireplace($method, '', $header));
}
/**
* Create a Payload instance.
*
* @param mixed $subject
* @param array $customClaims
*
* @return \Tymon\JWTAuth\Payload
*/
protected function makePayload($subject, array $customClaims = [])
{
return $this->manager->getPayloadFactory()->make(
array_merge($customClaims, ['sub' => $subject])
);
}
/**
* Set the identifier.
*
* @param string $identifier
*
* @return $this
*/
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
return $this;
}
/**
* Get the identifier.
*
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Set the token.
*
* @param string $token
*
* @return $this
*/
public function setToken($token)
{
$this->token = new Token($token);
return $this;
}
/**
* Ensure that a token is available.
*
* @param mixed $token
*
* @return JWTAuth
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*/
protected function requireToken($token)
{
if (! $token = $token ?: $this->token) {
throw new JWTException('A token is required', 400);
}
return $this->setToken($token);
}
/**
* Set the request instance.
*
* @param Request $request
*/
public function setRequest(Request $request)
{
$this->request = $request;
return $this;
}
/**
* Get the JWTManager instance.
*
* @return \Tymon\JWTAuth\JWTManager
*/
public function manager()
{
return $this->manager;
}
/**
* 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.");
}
}

447
vendor/tymon/jwt-auth/src/JWTGuard.php vendored Normal file
View File

@@ -0,0 +1,447 @@
<?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 Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Support\Traits\Macroable;
use Tymon\JWTAuth\Exceptions\JWTException;
use Illuminate\Contracts\Auth\UserProvider;
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.
*
* @throws \Tymon\JWTAuth\Exceptions\UserNotDefinedException
*
* @return \Illuminate\Contracts\Auth\Authenticatable
*/
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.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return \Tymon\JWTAuth\JWT
*/
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
*
* @throws \BadMethodCallException
*
* @return mixed
*/
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.");
}
}

View File

@@ -1,183 +0,0 @@
<?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\Exceptions\JWTException;
use Tymon\JWTAuth\Providers\JWT\JWTInterface;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
class JWTManager
{
/**
* @var \Tymon\JWTAuth\Providers\JWT\JWTInterface
*/
protected $jwt;
/**
* @var \Tymon\JWTAuth\Blacklist
*/
protected $blacklist;
/**
* @var \Tymon\JWTAuth\PayloadFactory
*/
protected $payloadFactory;
/**
* @var bool
*/
protected $blacklistEnabled = true;
/**
* @var bool
*/
protected $refreshFlow = false;
/**
* @param \Tymon\JWTAuth\Providers\JWT\JWTInterface $jwt
* @param \Tymon\JWTAuth\Blacklist $blacklist
* @param \Tymon\JWTAuth\PayloadFactory $payloadFactory
*/
public function __construct(JWTInterface $jwt, Blacklist $blacklist, PayloadFactory $payloadFactory)
{
$this->jwt = $jwt;
$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->jwt->encode($payload->get());
return new Token($token);
}
/**
* Decode a Token and return the Payload.
*
* @param \Tymon\JWTAuth\Token $token
* @return Payload
* @throws TokenBlacklistedException
*/
public function decode(Token $token)
{
$payloadArray = $this->jwt->decode($token->get());
$payload = $this->payloadFactory->setRefreshFlow($this->refreshFlow)->make($payloadArray);
if ($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
* @return \Tymon\JWTAuth\Token
*/
public function refresh(Token $token)
{
$payload = $this->setRefreshFlow()->decode($token);
if ($this->blacklistEnabled) {
// invalidate old token
$this->blacklist->add($payload);
}
// return the new token
return $this->encode(
$this->payloadFactory->make([
'sub' => $payload['sub'],
'iat' => $payload['iat'],
])
);
}
/**
* Invalidate a Token by adding it to the blacklist.
*
* @param Token $token
* @return bool
*/
public function invalidate(Token $token)
{
if (! $this->blacklistEnabled) {
throw new JWTException('You must have the blacklist enabled to invalidate a token.');
}
return $this->blacklist->add($this->decode($token));
}
/**
* Get the PayloadFactory instance.
*
* @return \Tymon\JWTAuth\PayloadFactory
*/
public function getPayloadFactory()
{
return $this->payloadFactory;
}
/**
* Get the JWTProvider instance.
*
* @return \Tymon\JWTAuth\Providers\JWT\JWTInterface
*/
public function getJWTProvider()
{
return $this->jwt;
}
/**
* Get the Blacklist instance.
*
* @return \Tymon\JWTAuth\Blacklist
*/
public function getBlacklist()
{
return $this->blacklist;
}
/**
* Set whether the blacklist is enabled.
*
* @param bool $enabled
*/
public function setBlacklistEnabled($enabled)
{
$this->blacklistEnabled = $enabled;
return $this;
}
/**
* Set the refresh flow.
*
* @param bool $refreshFlow
* @return $this
*/
public function setRefreshFlow($refreshFlow = true)
{
$this->refreshFlow = $refreshFlow;
return $this;
}
}

239
vendor/tymon/jwt-auth/src/Manager.php vendored Normal file
View File

@@ -0,0 +1,239 @@
<?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\Support\RefreshFlow;
use Tymon\JWTAuth\Support\CustomClaims;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Contracts\Providers\JWT as JWTContract;
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
*
* @throws \Tymon\JWTAuth\Exceptions\TokenBlacklistedException
*
* @return \Tymon\JWTAuth\Payload
*/
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
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return bool
*/
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)
{
// assign the payload values as variables for use later
extract($payload->toArray());
// persist the relevant claims
return array_merge(
$this->customClaims,
compact($this->persistentClaims, 'sub', '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;
}
}

View File

@@ -1,64 +0,0 @@
<?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\Middleware;
use Tymon\JWTAuth\JWTAuth;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Routing\ResponseFactory;
abstract class BaseMiddleware
{
/**
* @var \Illuminate\Contracts\Routing\ResponseFactory
*/
protected $response;
/**
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected $events;
/**
* @var \Tymon\JWTAuth\JWTAuth
*/
protected $auth;
/**
* Create a new BaseMiddleware instance.
*
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @param \Tymon\JWTAuth\JWTAuth $auth
*/
public function __construct(ResponseFactory $response, Dispatcher $events, JWTAuth $auth)
{
$this->response = $response;
$this->events = $events;
$this->auth = $auth;
}
/**
* Fire event and return the response.
*
* @param string $event
* @param string $error
* @param int $status
* @param array $payload
* @return mixed
*/
protected function respond($event, $error, $status, $payload = [])
{
$response = $this->events->fire($event, $payload, true);
return $response ?: $this->response->json(['error' => $error], $status);
}
}

View File

@@ -1,48 +0,0 @@
<?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\Middleware;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class GetUserFromToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
if (! $token = $this->auth->setRequest($request)->getToken()) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
try {
$user = $this->auth->authenticate($token);
} catch (TokenExpiredException $e) {
return $this->respond('tymon.jwt.expired', 'token_expired', 200, [$e]);
} catch (JWTException $e) {
return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]);
}
if (! $user) {
return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404);
}
$this->events->fire('tymon.jwt.valid', $user);
return $next($request);
}
}

View File

@@ -1,43 +0,0 @@
<?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\Middleware;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class RefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
$response = $next($request);
try {
$newToken = $this->auth->setRequest($request)->parseToken()->refresh();
} catch (TokenExpiredException $e) {
return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]);
} catch (JWTException $e) {
return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]);
}
// send the refreshed token back to the client
$response->headers->set('Authorization', 'Bearer '.$newToken);
return $response;
}
}

View File

@@ -11,43 +11,146 @@
namespace Tymon\JWTAuth;
use Countable;
use ArrayAccess;
use JsonSerializable;
use BadMethodCallException;
use Illuminate\Support\Arr;
use Tymon\JWTAuth\Claims\Claim;
use Tymon\JWTAuth\Claims\Collection;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Arrayable;
use Tymon\JWTAuth\Exceptions\PayloadException;
use Tymon\JWTAuth\Validators\PayloadValidator;
class Payload implements \ArrayAccess
class Payload implements ArrayAccess, Arrayable, Countable, Jsonable, JsonSerializable
{
/**
* The array of claims.
* The collection of claims.
*
* @var \Tymon\JWTAuth\Claims\Claim[]
* @var \Tymon\JWTAuth\Claims\Collection
*/
private $claims = [];
private $claims;
/**
* Build the Payload.
*
* @param array $claims
* @param \Tymon\JWTAuth\Validators\PayloadValidator $validator
* @param bool $refreshFlow
* @param \Tymon\JWTAuth\Claims\Collection $claims
* @param \Tymon\JWTAuth\Validators\PayloadValidator $validator
* @param bool $refreshFlow
*
* @return void
*/
public function __construct(array $claims, PayloadValidator $validator, $refreshFlow = false)
public function __construct(Collection $claims, PayloadValidator $validator, $refreshFlow = false)
{
$this->claims = $claims;
$validator->setRefreshFlow($refreshFlow)->check($this->toArray());
$this->claims = $validator->setRefreshFlow($refreshFlow)->check($claims);
}
/**
* Get the array of claim instances.
*
* @return \Tymon\JWTAuth\Claims\Claim[]
* @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.
*
@@ -55,42 +158,29 @@ class Payload implements \ArrayAccess
*/
public function toArray()
{
$results = [];
foreach ($this->claims as $claim) {
$results[$claim->getName()] = $claim->getValue();
}
return $results;
return $this->claims->toPlainArray();
}
/**
* Get the payload.
* Convert the object into something JSON serializable.
*
* @param string $claim
* @return mixed
* @return array
*/
public function get($claim = null)
public function jsonSerialize()
{
if (! is_null($claim)) {
if (is_array($claim)) {
return array_map([$this, 'get'], $claim);
}
return array_get($this->toArray(), $claim, false);
}
return $this->toArray();
}
/**
* Determine whether the payload has the claim.
* Get the payload as JSON.
*
* @param \Tymon\JWTAuth\Claims\Claim $claim
* @return bool
* @param int $options
*
* @return string
*/
public function has(Claim $claim)
public function toJson($options = JSON_UNESCAPED_SLASHES)
{
return in_array($claim, $this->claims);
return json_encode($this->toArray(), $options);
}
/**
@@ -100,38 +190,40 @@ class Payload implements \ArrayAccess
*/
public function __toString()
{
return json_encode($this->toArray());
return $this->toJson();
}
/**
* Determine if an item exists at an offset.
*
* @param mixed $key
*
* @return bool
*/
public function offsetExists($key)
{
return array_key_exists($key, $this->toArray());
return Arr::has($this->toArray(), $key);
}
/**
* Get an item at a given offset.
*
* @param mixed $key
*
* @return mixed
*/
public function offsetGet($key)
{
return array_get($this->toArray(), $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 Exceptions\PayloadException
* @return void
* @param mixed $key
* @param mixed $value
*
* @throws \Tymon\JWTAuth\Exceptions\PayloadException
*/
public function offsetSet($key, $value)
{
@@ -141,8 +233,10 @@ class Payload implements \ArrayAccess
/**
* Don't allow changing the payload as it should be immutable.
*
* @param string $key
* @throws Exceptions\PayloadException
* @param string $key
*
* @throws \Tymon\JWTAuth\Exceptions\PayloadException
*
* @return void
*/
public function offsetUnset($key)
@@ -150,26 +244,48 @@ class Payload implements \ArrayAccess
throw new PayloadException('The payload is immutable');
}
/**
* Count the number of claims.
*
* @return int
*/
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
* @param array $parameters
*
* @throws \BadMethodCallException
*
* @return mixed
*/
public function __call($method, $parameters)
{
if (! method_exists($this, $method) && starts_with($method, 'get')) {
$class = sprintf('Tymon\\JWTAuth\\Claims\\%s', substr($method, 3));
if (preg_match('/get(.+)\b/i', $method, $matches)) {
foreach ($this->claims as $claim) {
if (get_class($claim) === $class) {
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.', $method));
throw new BadMethodCallException(sprintf('The claim [%s] does not exist on the payload.', $method));
}
}

View File

@@ -1,247 +0,0 @@
<?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 Illuminate\Http\Request;
use Tymon\JWTAuth\Claims\Factory;
use Tymon\JWTAuth\Validators\PayloadValidator;
class PayloadFactory
{
/**
* @var \Tymon\JWTAuth\Claims\Factory
*/
protected $claimFactory;
/**
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* @var \Tymon\JWTAuth\Validators\PayloadValidator
*/
protected $validator;
/**
* @var int
*/
protected $ttl = 60;
/**
* @var bool
*/
protected $refreshFlow = false;
/**
* @var array
*/
protected $defaultClaims = ['iss', 'iat', 'exp', 'nbf', 'jti'];
/**
* @var array
*/
protected $claims = [];
/**
* @param \Tymon\JWTAuth\Claims\Factory $claimFactory
* @param \Illuminate\Http\Request $request
* @param \Tymon\JWTAuth\Validators\PayloadValidator $validator
*/
public function __construct(Factory $claimFactory, Request $request, PayloadValidator $validator)
{
$this->claimFactory = $claimFactory;
$this->request = $request;
$this->validator = $validator;
}
/**
* Create the Payload instance.
*
* @param array $customClaims
* @return \Tymon\JWTAuth\Payload
*/
public function make(array $customClaims = [])
{
$claims = $this->buildClaims($customClaims)->resolveClaims();
return new Payload($claims, $this->validator, $this->refreshFlow);
}
/**
* Add an array of claims to the Payload.
*
* @param array $claims
* @return $this
*/
public 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
*/
public function addClaim($name, $value)
{
$this->claims[$name] = $value;
return $this;
}
/**
* Build the default claims.
*
* @param array $customClaims
* @return $this
*/
protected function buildClaims(array $customClaims)
{
// add any custom claims first
$this->addClaims(array_diff_key($customClaims, $this->defaultClaims));
foreach ($this->defaultClaims as $claim) {
if (! array_key_exists($claim, $customClaims)) {
$this->addClaim($claim, $this->$claim());
}
}
return $this;
}
/**
* Build out the Claim DTO's.
*
* @return array
*/
public function resolveClaims()
{
$resolved = [];
foreach ($this->claims as $name => $value) {
$resolved[] = $this->claimFactory->get($name, $value);
}
return $resolved;
}
/**
* Set the Issuer (iss) claim.
*
* @return string
*/
public function iss()
{
return $this->request->url();
}
/**
* Set the Issued At (iat) claim.
*
* @return int
*/
public function iat()
{
return Utils::now()->timestamp;
}
/**
* Set the Expiration (exp) claim.
*
* @return int
*/
public function exp()
{
return Utils::now()->addMinutes($this->ttl)->timestamp;
}
/**
* Set the Not Before (nbf) claim.
*
* @return int
*/
public function nbf()
{
return Utils::now()->timestamp;
}
/**
* Set a unique id (jti) for the token.
*
* @return string
*/
protected function jti()
{
$sub = array_get($this->claims, 'sub', '');
$nbf = array_get($this->claims, 'nbf', '');
return md5(sprintf('jti.%s.%s', $sub, $nbf));
}
/**
* 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 refresh flow.
*
* @param bool $refreshFlow
* @return $this
*/
public function setRefreshFlow($refreshFlow = true)
{
$this->refreshFlow = $refreshFlow;
return $this;
}
/**
* Magically add a claim.
*
* @param string $method
* @param array $parameters
* @return PayloadFactory
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
$this->addClaim($method, $parameters[0]);
return $this;
}
}

View File

@@ -0,0 +1,382 @@
<?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 Namshi\JOSE\JWS;
use Tymon\JWTAuth\JWT;
use Tymon\JWTAuth\Factory;
use Tymon\JWTAuth\JWTAuth;
use Tymon\JWTAuth\Manager;
use Tymon\JWTAuth\JWTGuard;
use Tymon\JWTAuth\Blacklist;
use Lcobucci\JWT\Parser as JWTParser;
use Tymon\JWTAuth\Http\Parser\Parser;
use Tymon\JWTAuth\Http\Parser\Cookies;
use Illuminate\Support\ServiceProvider;
use Lcobucci\JWT\Builder as JWTBuilder;
use Tymon\JWTAuth\Providers\JWT\Namshi;
use Tymon\JWTAuth\Http\Middleware\Check;
use Tymon\JWTAuth\Providers\JWT\Lcobucci;
use Tymon\JWTAuth\Http\Parser\AuthHeaders;
use Tymon\JWTAuth\Http\Parser\InputSource;
use Tymon\JWTAuth\Http\Parser\QueryString;
use Tymon\JWTAuth\Http\Parser\RouteParams;
use Tymon\JWTAuth\Contracts\Providers\Auth;
use Tymon\JWTAuth\Contracts\Providers\Storage;
use Tymon\JWTAuth\Validators\PayloadValidator;
use Tymon\JWTAuth\Http\Middleware\Authenticate;
use Tymon\JWTAuth\Http\Middleware\RefreshToken;
use Tymon\JWTAuth\Claims\Factory as ClaimFactory;
use Tymon\JWTAuth\Console\JWTGenerateSecretCommand;
use Tymon\JWTAuth\Http\Middleware\AuthenticateAndRenew;
use Tymon\JWTAuth\Contracts\Providers\JWT as JWTContract;
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(
new JWTBuilder(),
new JWTParser(),
$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,
new RouteParams,
new Cookies($this->config('decrypt_cookies')),
]
);
$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;
}
}

View File

@@ -11,19 +11,26 @@
namespace Tymon\JWTAuth\Providers\Auth;
use Illuminate\Auth\AuthManager;
use Tymon\JWTAuth\Contracts\Providers\Auth;
use Illuminate\Contracts\Auth\Guard as GuardContract;
class IlluminateAuthAdapter implements AuthInterface
class Illuminate implements Auth
{
/**
* @var \Illuminate\Auth\AuthManager
* The authentication guard.
*
* @var \Illuminate\Contracts\Auth\Guard
*/
protected $auth;
/**
* @param \Illuminate\Auth\AuthManager $auth
* Constructor.
*
* @param \Illuminate\Contracts\Auth\Guard $auth
*
* @return void
*/
public function __construct(AuthManager $auth)
public function __construct(GuardContract $auth)
{
$this->auth = $auth;
}
@@ -32,9 +39,10 @@ class IlluminateAuthAdapter implements AuthInterface
* Check a user's credentials.
*
* @param array $credentials
*
* @return bool
*/
public function byCredentials(array $credentials = [])
public function byCredentials(array $credentials)
{
return $this->auth->once($credentials);
}
@@ -43,6 +51,7 @@ class IlluminateAuthAdapter implements AuthInterface
* Authenticate a user via the id.
*
* @param mixed $id
*
* @return bool
*/
public function byId($id)

View File

@@ -0,0 +1,77 @@
<?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 Tymon\JWTAuth\Contracts\Providers\Auth;
use Cartalyst\Sentinel\Sentinel as SentinelAuth;
class Sentinel implements Auth
{
/**
* The sentinel authentication.
*
* @var \Cartalyst\Sentinel\Sentinel
*/
protected $sentinel;
/**
* Constructor.
*
* @param \Cartalyst\Sentinel\Sentinel $sentinel
*
* @return void
*/
public function __construct(SentinelAuth $sentinel)
{
$this->sentinel = $sentinel;
}
/**
* Check a user's credentials.
*
* @param array $credentials
*
* @return mixed
*/
public function byCredentials(array $credentials)
{
return $this->sentinel->stateless($credentials);
}
/**
* Authenticate a user via the id.
*
* @param mixed $id
*
* @return bool
*/
public function byId($id)
{
if ($user = $this->sentinel->getUserRepository()->findById($id)) {
$this->sentinel->setUser($user);
return true;
}
return false;
}
/**
* Get the currently authenticated user.
*
* @return \Cartalyst\Sentinel\Users\UserInterface
*/
public function user()
{
return $this->sentinel->getUser();
}
}

View File

@@ -1,58 +0,0 @@
<?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;
abstract class JWTProvider
{
/**
* @var string
*/
protected $secret;
/**
* @var string
*/
protected $algo;
/**
* @param string $secret
* @param string $algo
*/
public function __construct($secret, $algo = 'HS256')
{
$this->secret = $secret;
$this->algo = $algo;
}
/**
* Set the algorithm used to sign the token.
*
* @param string $algo
* @return self
*/
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;
}
}

View File

@@ -0,0 +1,190 @@
<?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 Exception;
use ReflectionClass;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Rsa;
use Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Keychain;
use Illuminate\Support\Collection;
use Tymon\JWTAuth\Contracts\Providers\JWT;
use Tymon\JWTAuth\Exceptions\JWTException;
use Lcobucci\JWT\Signer\Rsa\Sha256 as RS256;
use Lcobucci\JWT\Signer\Rsa\Sha384 as RS384;
use Lcobucci\JWT\Signer\Rsa\Sha512 as RS512;
use Lcobucci\JWT\Signer\Hmac\Sha256 as HS256;
use Lcobucci\JWT\Signer\Hmac\Sha384 as HS384;
use Lcobucci\JWT\Signer\Hmac\Sha512 as HS512;
use Lcobucci\JWT\Signer\Ecdsa\Sha256 as ES256;
use Lcobucci\JWT\Signer\Ecdsa\Sha384 as ES384;
use Lcobucci\JWT\Signer\Ecdsa\Sha512 as ES512;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class Lcobucci extends Provider implements JWT
{
/**
* The Builder instance.
*
* @var \Lcobucci\JWT\Builder
*/
protected $builder;
/**
* The Parser instance.
*
* @var \Lcobucci\JWT\Parser
*/
protected $parser;
/**
* Create the Lcobucci provider.
*
* @param \Lcobucci\JWT\Builder $builder
* @param \Lcobucci\JWT\Parser $parser
* @param string $secret
* @param string $algo
* @param array $keys
*
* @return void
*/
public function __construct(
Builder $builder,
Parser $parser,
$secret,
$algo,
array $keys
) {
parent::__construct($secret, $algo, $keys);
$this->builder = $builder;
$this->parser = $parser;
$this->signer = $this->getSigner();
}
/**
* Signers that this provider supports.
*
* @var array
*/
protected $signers = [
'HS256' => HS256::class,
'HS384' => HS384::class,
'HS512' => HS512::class,
'RS256' => RS256::class,
'RS384' => RS384::class,
'RS512' => RS512::class,
'ES256' => ES256::class,
'ES384' => ES384::class,
'ES512' => ES512::class,
];
/**
* Create a JSON Web Token.
*
* @param array $payload
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return string
*/
public function encode(array $payload)
{
// Remove the signature on the builder instance first.
$this->builder->unsign();
try {
foreach ($payload as $key => $value) {
$this->builder->set($key, $value);
}
$this->builder->sign($this->signer, $this->getSigningKey());
} catch (Exception $e) {
throw new JWTException('Could not create token: '.$e->getMessage(), $e->getCode(), $e);
}
return (string) $this->builder->getToken();
}
/**
* Decode a JSON Web Token.
*
* @param string $token
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return array
*/
public function decode($token)
{
try {
$jwt = $this->parser->parse($token);
} catch (Exception $e) {
throw new TokenInvalidException('Could not decode token: '.$e->getMessage(), $e->getCode(), $e);
}
if (! $jwt->verify($this->signer, $this->getVerificationKey())) {
throw new TokenInvalidException('Token Signature could not be verified.');
}
return (new Collection($jwt->getClaims()))->map(function ($claim) {
return is_object($claim) ? $claim->getValue() : $claim;
})->toArray();
}
/**
* Get the signer instance.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return \Lcobucci\JWT\Signer
*/
protected function getSigner()
{
if (! array_key_exists($this->algo, $this->signers)) {
throw new JWTException('The given algorithm could not be found');
}
return new $this->signers[$this->algo];
}
/**
* {@inheritdoc}
*/
protected function isAsymmetric()
{
$reflect = new ReflectionClass($this->signer);
return $reflect->isSubclassOf(Rsa::class) || $reflect->isSubclassOf(Ecdsa::class);
}
/**
* {@inheritdoc}
*/
protected function getSigningKey()
{
return $this->isAsymmetric() ?
(new Keychain())->getPrivateKey($this->getPrivateKey(), $this->getPassphrase()) :
$this->getSecret();
}
/**
* {@inheritdoc}
*/
protected function getVerificationKey()
{
return $this->isAsymmetric() ?
(new Keychain())->getPublicKey($this->getPublicKey()) :
$this->getSecret();
}
}

View File

@@ -0,0 +1,106 @@
<?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 Exception;
use Namshi\JOSE\JWS;
use ReflectionClass;
use ReflectionException;
use InvalidArgumentException;
use Namshi\JOSE\Signer\OpenSSL\PublicKey;
use Tymon\JWTAuth\Contracts\Providers\JWT;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class Namshi extends Provider implements JWT
{
/**
* The JWS.
*
* @var \Namshi\JOSE\JWS
*/
protected $jws;
/**
* Constructor.
*
* @param \Namshi\JOSE\JWS $jws
* @param string $secret
* @param string $algo
* @param array $keys
*
* @return void
*/
public function __construct(JWS $jws, $secret, $algo, array $keys)
{
parent::__construct($secret, $algo, $keys);
$this->jws = $jws;
}
/**
* Create a JSON Web Token.
*
* @param array $payload
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return string
*/
public function encode(array $payload)
{
try {
$this->jws->setPayload($payload)->sign($this->getSigningKey(), $this->getPassphrase());
return (string) $this->jws->getTokenString();
} catch (Exception $e) {
throw new JWTException('Could not create token: '.$e->getMessage(), $e->getCode(), $e);
}
}
/**
* Decode a JSON Web Token.
*
* @param string $token
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return array
*/
public function decode($token)
{
try {
// Let's never allow insecure tokens
$jws = $this->jws->load($token, false);
} catch (InvalidArgumentException $e) {
throw new TokenInvalidException('Could not decode token: '.$e->getMessage(), $e->getCode(), $e);
}
if (! $jws->verify($this->getVerificationKey(), $this->getAlgo())) {
throw new TokenInvalidException('Token Signature could not be verified.');
}
return (array) $jws->getPayload();
}
/**
* {@inheritdoc}
*/
protected function isAsymmetric()
{
try {
return (new ReflectionClass(sprintf('Namshi\\JOSE\\Signer\\OpenSSL\\%s', $this->getAlgo())))->isSubclassOf(PublicKey::class);
} catch (ReflectionException $e) {
throw new JWTException('The given algorithm could not be found', $e->getCode(), $e);
}
}
}

View File

@@ -1,76 +0,0 @@
<?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 Exception;
use Namshi\JOSE\JWS;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class NamshiAdapter extends JWTProvider implements JWTInterface
{
/**
* @var \Namshi\JOSE\JWS
*/
protected $jws;
/**
* @param string $secret
* @param string $algo
* @param null $driver
*/
public function __construct($secret, $algo, $driver = null)
{
parent::__construct($secret, $algo);
$this->jws = $driver ?: new JWS(['typ' => 'JWT', 'alg' => $algo]);
}
/**
* Create a JSON Web Token.
*
* @return string
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*/
public function encode(array $payload)
{
try {
$this->jws->setPayload($payload)->sign($this->secret);
return $this->jws->getTokenString();
} catch (Exception $e) {
throw new JWTException('Could not create token: '.$e->getMessage());
}
}
/**
* Decode a JSON Web Token.
*
* @param string $token
* @return array
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*/
public function decode($token)
{
try {
$jws = JWS::load($token);
} catch (Exception $e) {
throw new TokenInvalidException('Could not decode token: '.$e->getMessage());
}
if (! $jws->verify($this->secret, $this->algo)) {
throw new TokenInvalidException('Token Signature could not be verified.');
}
return $jws->getPayload();
}
}

View File

@@ -0,0 +1,190 @@
<?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
{
/**
* 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 resource|string
*/
public function getPublicKey()
{
return Arr::get($this->keys, 'public');
}
/**
* Get the private key used to sign tokens
* with an asymmetric algorithm.
*
* @return resource|string
*/
public function getPrivateKey()
{
return Arr::get($this->keys, 'private');
}
/**
* Get the passphrase used to sign tokens
* with an asymmetric algorithm.
*
* @return string
*/
public function getPassphrase()
{
return Arr::get($this->keys, 'passphrase');
}
/**
* Get the key used to sign the tokens.
*
* @return resource|string
*/
protected function getSigningKey()
{
return $this->isAsymmetric() ? $this->getPrivateKey() : $this->getSecret();
}
/**
* Get the key used to verify the tokens.
*
* @return resource|string
*/
protected function getVerificationKey()
{
return $this->isAsymmetric() ? $this->getPublicKey() : $this->getSecret();
}
/**
* Determine if the algorithm is asymmetric, and thus
* requires a public/private key combo.
*
* @throws \Tymon\JWTAuth\Exceptions\JWTException
*
* @return bool
*/
abstract protected function isAsymmetric();
}

View File

@@ -1,278 +0,0 @@
<?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\JWTAuth;
use Tymon\JWTAuth\Blacklist;
use Tymon\JWTAuth\JWTManager;
use Tymon\JWTAuth\PayloadFactory;
use Tymon\JWTAuth\Claims\Factory;
use Illuminate\Support\ServiceProvider;
use Tymon\JWTAuth\Commands\JWTGenerateCommand;
use Tymon\JWTAuth\Validators\PayloadValidator;
class JWTAuthServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Boot the service provider.
*/
public function boot()
{
$this->publishes([
__DIR__.'/../config/config.php' => config_path('jwt.php'),
], 'config');
$this->bootBindings();
$this->commands('tymon.jwt.generate');
}
/**
* Bind some Interfaces and implementations.
*/
protected function bootBindings()
{
$this->app['Tymon\JWTAuth\JWTAuth'] = function ($app) {
return $app['tymon.jwt.auth'];
};
$this->app['Tymon\JWTAuth\Providers\User\UserInterface'] = function ($app) {
return $app['tymon.jwt.provider.user'];
};
$this->app['Tymon\JWTAuth\Providers\JWT\JWTInterface'] = function ($app) {
return $app['tymon.jwt.provider.jwt'];
};
$this->app['Tymon\JWTAuth\Providers\Auth\AuthInterface'] = function ($app) {
return $app['tymon.jwt.provider.auth'];
};
$this->app['Tymon\JWTAuth\Providers\Storage\StorageInterface'] = function ($app) {
return $app['tymon.jwt.provider.storage'];
};
$this->app['Tymon\JWTAuth\JWTManager'] = function ($app) {
return $app['tymon.jwt.manager'];
};
$this->app['Tymon\JWTAuth\Blacklist'] = function ($app) {
return $app['tymon.jwt.blacklist'];
};
$this->app['Tymon\JWTAuth\PayloadFactory'] = function ($app) {
return $app['tymon.jwt.payload.factory'];
};
$this->app['Tymon\JWTAuth\Claims\Factory'] = function ($app) {
return $app['tymon.jwt.claim.factory'];
};
$this->app['Tymon\JWTAuth\Validators\PayloadValidator'] = function ($app) {
return $app['tymon.jwt.validators.payload'];
};
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
// register providers
$this->registerUserProvider();
$this->registerJWTProvider();
$this->registerAuthProvider();
$this->registerStorageProvider();
$this->registerJWTBlacklist();
$this->registerClaimFactory();
$this->registerJWTManager();
$this->registerJWTAuth();
$this->registerPayloadValidator();
$this->registerPayloadFactory();
$this->registerJWTCommand();
$this->mergeConfigFrom(__DIR__.'/../config/config.php', 'jwt');
}
/**
* Register the bindings for the User provider.
*/
protected function registerUserProvider()
{
$this->app['tymon.jwt.provider.user'] = $this->app->share(function ($app) {
return $app->make($this->config('providers.user'), [$app->make($this->config('user'))]);
});
}
/**
* Register the bindings for the JSON Web Token provider.
*/
protected function registerJWTProvider()
{
$this->app['tymon.jwt.provider.jwt'] = $this->app->share(function ($app) {
$secret = $this->config('secret');
$algo = $this->config('algo');
$provider = $this->config('providers.jwt');
return $app->make($provider, [$secret, $algo]);
});
}
/**
* Register the bindings for the Auth provider.
*/
protected function registerAuthProvider()
{
$this->app['tymon.jwt.provider.auth'] = $this->app->share(function ($app) {
return $this->getConfigInstance($this->config('providers.auth'));
});
}
/**
* Register the bindings for the Storage provider.
*/
protected function registerStorageProvider()
{
$this->app['tymon.jwt.provider.storage'] = $this->app->share(function ($app) {
return $this->getConfigInstance($this->config('providers.storage'));
});
}
/**
* Register the bindings for the Payload Factory.
*/
protected function registerClaimFactory()
{
$this->app->singleton('tymon.jwt.claim.factory', function () {
return new Factory();
});
}
/**
* Register the bindings for the JWT Manager.
*/
protected function registerJWTManager()
{
$this->app['tymon.jwt.manager'] = $this->app->share(function ($app) {
$instance = new JWTManager(
$app['tymon.jwt.provider.jwt'],
$app['tymon.jwt.blacklist'],
$app['tymon.jwt.payload.factory']
);
return $instance->setBlacklistEnabled((bool) $this->config('blacklist_enabled'));
});
}
/**
* Register the bindings for the main JWTAuth class.
*/
protected function registerJWTAuth()
{
$this->app['tymon.jwt.auth'] = $this->app->share(function ($app) {
$auth = new JWTAuth(
$app['tymon.jwt.manager'],
$app['tymon.jwt.provider.user'],
$app['tymon.jwt.provider.auth'],
$app['request']
);
return $auth->setIdentifier($this->config('identifier'));
});
}
/**
* Register the bindings for the main JWTAuth class.
*/
protected function registerJWTBlacklist()
{
$this->app['tymon.jwt.blacklist'] = $this->app->share(function ($app) {
$instance = new Blacklist($app['tymon.jwt.provider.storage']);
return $instance->setRefreshTTL($this->config('refresh_ttl'));
});
}
/**
* Register the bindings for the payload validator.
*/
protected function registerPayloadValidator()
{
$this->app['tymon.jwt.validators.payload'] = $this->app->share(function () {
return with(new PayloadValidator())->setRefreshTTL($this->config('refresh_ttl'))->setRequiredClaims($this->config('required_claims'));
});
}
/**
* Register the bindings for the Payload Factory.
*/
protected function registerPayloadFactory()
{
$this->app['tymon.jwt.payload.factory'] = $this->app->share(function ($app) {
$factory = new PayloadFactory($app['tymon.jwt.claim.factory'], $app['request'], $app['tymon.jwt.validators.payload']);
return $factory->setTTL($this->config('ttl'));
});
}
/**
* Register the Artisan command.
*/
protected function registerJWTCommand()
{
$this->app['tymon.jwt.generate'] = $this->app->share(function () {
return new JWTGenerateCommand();
});
}
/**
* Helper to get the config values.
*
* @param string $key
* @return string
*/
protected function config($key, $default = null)
{
return config("jwt.$key", $default);
}
/**
* Get an instantiable configuration instance. Pinched from dingo/api :).
*
* @param mixed $instance
* @return object
*/
protected function getConfigInstance($instance)
{
if (is_callable($instance)) {
return call_user_func($instance, $this->app);
} elseif (is_string($instance)) {
return $this->app->make($instance);
}
return $instance;
}
}

View File

@@ -0,0 +1,46 @@
<?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;
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();
}
/**
* 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);
}
}
}

View File

@@ -0,0 +1,42 @@
<?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\AuthHeaders;
use Tymon\JWTAuth\Http\Parser\InputSource;
use Tymon\JWTAuth\Http\Parser\QueryString;
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']->setChain([
new AuthHeaders,
new QueryString,
new InputSource,
new LumenRouteParams,
]);
}
}

View File

@@ -0,0 +1,160 @@
<?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 Tymon\JWTAuth\Contracts\Providers\Storage;
use Psr\SimpleCache\CacheInterface as PsrCacheInterface;
use Illuminate\Contracts\Cache\Repository as CacheContract;
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;
/**
* 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)
{
$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;
}
/**
* 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;
}
}
}
}

View File

@@ -1,94 +0,0 @@
<?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 Illuminate\Cache\CacheManager;
class IlluminateCacheAdapter implements StorageInterface
{
/**
* @var \Illuminate\Cache\CacheManager
*/
protected $cache;
/**
* @var string
*/
protected $tag = 'tymon.jwt';
/**
* @param \Illuminate\Cache\CacheManager $cache
*/
public function __construct(CacheManager $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)
{
$this->cache()->put($key, $value, $minutes);
}
/**
* Check whether a key exists in storage.
*
* @param string $key
* @return bool
*/
public function has($key)
{
return $this->cache()->has($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\Cache\CacheManager
*/
protected function cache()
{
if (! method_exists($this->cache, 'tags')) {
return $this->cache;
}
return $this->cache->tags($this->tag);
}
}

View File

@@ -1,44 +0,0 @@
<?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\User;
use Illuminate\Database\Eloquent\Model;
class EloquentUserAdapter implements UserInterface
{
/**
* @var \Illuminate\Database\Eloquent\Model
*/
protected $user;
/**
* Create a new User instance.
*
* @param \Illuminate\Database\Eloquent\Model $user
*/
public function __construct(Model $user)
{
$this->user = $user;
}
/**
* Get the user by the given key, value.
*
* @param mixed $key
* @param mixed $value
* @return Illuminate\Database\Eloquent\Model
*/
public function getBy($key, $value)
{
return $this->user->where($key, $value)->first();
}
}

View File

@@ -1,24 +0,0 @@
<?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\User;
interface UserInterface
{
/**
* Get the user by the given key, value.
*
* @param string $key
* @param mixed $value
* @return Illuminate\Database\Eloquent\Model|null
*/
public function getBy($key, $value);
}

View File

@@ -0,0 +1,58 @@
<?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;
}
}

View File

@@ -0,0 +1,36 @@
<?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;
}
}

View File

@@ -0,0 +1,73 @@
<?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();
}
}

View File

@@ -23,13 +23,13 @@ class Token
/**
* Create a new JSON Web Token.
*
* @param string $value
* @param string $value
*
* @return void
*/
public function __construct($value)
{
with(new TokenValidator)->check($value);
$this->value = $value;
$this->value = (string) (new TokenValidator)->check($value);
}
/**
@@ -49,6 +49,6 @@ class Token
*/
public function __toString()
{
return (string) $this->value;
return $this->get();
}
}

View File

@@ -1,38 +0,0 @@
<?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 Carbon\Carbon;
class Utils
{
/**
* Get the Carbon instance for the current time.
*
* @return \Carbon\Carbon
*/
public static function now()
{
return Carbon::now();
}
/**
* Get the Carbon instance for the timestamp.
*
* @param int $timestamp
* @return \Carbon\Carbon
*/
public static function timestamp($timestamp)
{
return Carbon::createFromTimeStampUTC($timestamp);
}
}

View File

@@ -11,18 +11,28 @@
namespace Tymon\JWTAuth\Validators;
use Tymon\JWTAuth\Utils;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Claims\Collection;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class PayloadValidator extends AbstractValidator
class PayloadValidator extends Validator
{
/**
* The required claims.
*
* @var array
*/
protected $requiredClaims = ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'];
protected $requiredClaims = [
'iss',
'iat',
'exp',
'nbf',
'sub',
'jti',
];
/**
* The refresh TTL.
*
* @var int
*/
protected $refreshTTL = 20160;
@@ -30,81 +40,69 @@ class PayloadValidator extends AbstractValidator
/**
* Run the validations on the payload array.
*
* @param array $value
* @return void
* @param \Tymon\JWTAuth\Claims\Collection $value
*
* @return \Tymon\JWTAuth\Claims\Collection
*/
public function check($value)
{
$this->validateStructure($value);
if (! $this->refreshFlow) {
$this->validateTimestamps($value);
} else {
$this->validateRefresh($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 array $payload
* @param \Tymon\JWTAuth\Claims\Collection $claims
*
* @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException
* @return bool
*
* @return void
*/
protected function validateStructure(array $payload)
protected function validateStructure(Collection $claims)
{
if (count(array_diff_key($this->requiredClaims, array_keys($payload))) !== 0) {
if ($this->requiredClaims && ! $claims->hasAllClaims($this->requiredClaims)) {
throw new TokenInvalidException('JWT payload does not contain the required claims');
}
return true;
}
/**
* Validate the payload timestamps.
*
* @param array $payload
* @param \Tymon\JWTAuth\Claims\Collection $claims
*
* @throws \Tymon\JWTAuth\Exceptions\TokenExpiredException
* @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException
* @return bool
*
* @return \Tymon\JWTAuth\Claims\Collection
*/
protected function validateTimestamps(array $payload)
protected function validatePayload(Collection $claims)
{
if (isset($payload['nbf']) && Utils::timestamp($payload['nbf'])->isFuture()) {
throw new TokenInvalidException('Not Before (nbf) timestamp cannot be in the future', 400);
}
if (isset($payload['iat']) && Utils::timestamp($payload['iat'])->isFuture()) {
throw new TokenInvalidException('Issued At (iat) timestamp cannot be in the future', 400);
}
if (Utils::timestamp($payload['exp'])->isPast()) {
throw new TokenExpiredException('Token has expired');
}
return true;
return $claims->validate('payload');
}
/**
* Check the token in the refresh flow context.
*
* @param $payload
* @return bool
* @param \Tymon\JWTAuth\Claims\Collection $claims
*
* @throws \Tymon\JWTAuth\Exceptions\TokenExpiredException
*
* @return \Tymon\JWTAuth\Claims\Collection
*/
protected function validateRefresh(array $payload)
protected function validateRefresh(Collection $claims)
{
if (isset($payload['iat']) && Utils::timestamp($payload['iat'])->addMinutes($this->refreshTTL)->isPast()) {
throw new TokenExpiredException('Token has expired and can no longer be refreshed', 400);
}
return true;
return $this->refreshTTL === null ? $claims : $claims->validate('refresh', $this->refreshTTL);
}
/**
* Set the required claims.
*
* @param array $claims
* @param array $claims
*
* @return $this
*/
public function setRequiredClaims(array $claims)
{
@@ -116,7 +114,9 @@ class PayloadValidator extends AbstractValidator
/**
* Set the refresh ttl.
*
* @param int $ttl
* @param int $ttl
*
* @return $this
*/
public function setRefreshTTL($ttl)
{

View File

@@ -13,30 +13,41 @@ namespace Tymon\JWTAuth\Validators;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class TokenValidator extends AbstractValidator
class TokenValidator extends Validator
{
/**
* Check the structure of the token.
*
* @param string $value
* @return void
* @param string $value
*
* @return string
*/
public function check($value)
{
$this->validateStructure($value);
return $this->validateStructure($value);
}
/**
* @param string $token
*
* @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException
* @return bool
*
* @return string
*/
protected function validateStructure($token)
{
if (count(explode('.', $token)) !== 3) {
$parts = explode('.', $token);
if (count($parts) !== 3) {
throw new TokenInvalidException('Wrong number of segments');
}
return true;
$parts = array_filter(array_map('trim', $parts));
if (count($parts) !== 3 || implode('.', $parts) !== $token) {
throw new TokenInvalidException('Malformed token');
}
return $token;
}
}

View File

@@ -11,19 +11,19 @@
namespace Tymon\JWTAuth\Validators;
use Tymon\JWTAuth\Support\RefreshFlow;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Contracts\Validator as ValidatorContract;
abstract class AbstractValidator implements ValidatorInterface
abstract class Validator implements ValidatorContract
{
/**
* @var bool
*/
protected $refreshFlow = false;
use RefreshFlow;
/**
* Helper function to return a boolean.
*
* @param array $value
*
* @return bool
*/
public function isValid($value)
@@ -38,15 +38,11 @@ abstract class AbstractValidator implements ValidatorInterface
}
/**
* Set the refresh flow flag.
* Run the validation.
*
* @param bool $refreshFlow
* @return $this
* @param array $value
*
* @return void
*/
public function setRefreshFlow($refreshFlow = true)
{
$this->refreshFlow = $refreshFlow;
return $this;
}
abstract public function check($value);
}

View File

@@ -1,173 +0,0 @@
<?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, as it will be used to sign your tokens.
| A helper command is provided for this: `php artisan jwt:generate`
|
*/
'secret' => env('JWT_SECRET', 'changeme'),
/*
|--------------------------------------------------------------------------
| JWT time to live
|--------------------------------------------------------------------------
|
| Specify the length of time (in minutes) that the token will be valid for.
| Defaults to 1 hour
|
*/
'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
|
*/
'refresh_ttl' => 20160,
/*
|--------------------------------------------------------------------------
| JWT hashing algorithm
|--------------------------------------------------------------------------
|
| Specify the hashing algorithm that will be used to sign the token.
|
| See here: https://github.com/namshi/jose/tree/2.2.0/src/Namshi/JOSE/Signer
| for possible values
|
*/
'algo' => 'HS256',
/*
|--------------------------------------------------------------------------
| User Model namespace
|--------------------------------------------------------------------------
|
| Specify the full namespace to your User model.
| e.g. 'Acme\Entities\User'
|
*/
'user' => 'App\User',
/*
|--------------------------------------------------------------------------
| User identifier
|--------------------------------------------------------------------------
|
| Specify a unique property of the user that will be added as the 'sub'
| claim of the token payload.
|
*/
'identifier' => 'id',
/*
|--------------------------------------------------------------------------
| 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'],
/*
|--------------------------------------------------------------------------
| Blacklist Enabled
|--------------------------------------------------------------------------
|
| In order to invalidate tokens, you must have the the blacklist enabled.
| If you do not want or need this functionality, then set this to false.
|
*/
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
/*
|--------------------------------------------------------------------------
| Providers
|--------------------------------------------------------------------------
|
| Specify the various providers used throughout the package.
|
*/
'providers' => [
/*
|--------------------------------------------------------------------------
| User Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to find the user based
| on the subject claim
|
*/
'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',
/*
|--------------------------------------------------------------------------
| JWT Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to create and decode the tokens.
|
*/
'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter',
/*
|--------------------------------------------------------------------------
| Authentication Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to authenticate users.
|
*/
'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter',
/*
|--------------------------------------------------------------------------
| Storage Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to store tokens in the blacklist
|
*/
'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter',
],
];