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

@@ -1,3 +0,0 @@
/vendor
composer.lock
build

View File

@@ -1,6 +0,0 @@
preset: laravel
enabled:
- unalign_double_arrow
linting: true

View File

@@ -1,20 +0,0 @@
sudo: false
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
allow_failures:
- php: 7.0
before_script:
- travis_retry composer self-update
- travis_retry composer install --no-interaction --prefer-source
script:
- phpunit --coverage-text --coverage-clover=coverage.clover

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014 Sean Tymon
Copyright (c) 2018 Sean Tymon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,40 +0,0 @@
# jwt-auth
> JSON Web Token Authentication for Laravel
[![Build Status](http://img.shields.io/travis/tymondesigns/jwt-auth/master.svg?style=flat-square)](https://travis-ci.org/tymondesigns/jwt-auth)
[![Scrutinizer Code Quality](http://img.shields.io/scrutinizer/g/tymondesigns/jwt-auth.svg?style=flat-square)](https://scrutinizer-ci.com/g/tymondesigns/jwt-auth/)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/tymondesigns/jwt-auth.svg?style=flat-square)](https://scrutinizer-ci.com/g/tymondesigns/jwt-auth/code-structure)
[![StyleCI](https://styleci.io/repos/23680678/shield?style=flat-square)](https://styleci.io/repos/23680678)
[![HHVM](https://img.shields.io/hhvm/tymon/jwt-auth.svg?style=flat-square)](http://hhvm.h4cc.de/package/tymon/jwt-auth)
[![Latest Version](http://img.shields.io/packagist/v/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth)
[![Latest Dev Version](https://img.shields.io/packagist/vpre/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth#dev-develop)
[![Monthly Downloads](https://img.shields.io/packagist/dm/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth)
See the [WIKI](https://github.com/tymondesigns/jwt-auth/wiki) for documentation
## License
The MIT License (MIT)
Copyright (c) 2014 Sean Tymon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[![Gratipay](https://img.shields.io/gratipay/tymondesigns.svg?style=flat-square)](https://gratipay.com/~tymondesigns)

View File

@@ -1,51 +1,76 @@
{
"name": "tymon/jwt-auth",
"description": "JSON Web Token Authentication for Laravel 4 and 5",
"description": "JSON Web Token Authentication for Laravel and Lumen",
"keywords": [
"jwt",
"auth",
"authentication",
"tymon",
"laravel",
"json web token"
"json web token",
"jwt",
"laravel"
],
"homepage": "https://github.com/tymondesigns/jwt-auth",
"support": {
"issues": "https://github.com/tymondesigns/jwt-auth/issues",
"source": "https://github.com/tymondesigns/jwt-auth"
},
"license": "MIT",
"authors": [
{
"name": "Sean Tymon",
"email": "tymon148@gmail.com",
"homepage": "http://tymondesigns.com",
"homepage": "https://tymon.xyz",
"role": "Developer"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "~5.0",
"illuminate/http": "~5.0",
"namshi/jose": "5.0.*",
"nesbot/carbon": "~1.0"
"php": "^5.5.9 || ^7.0",
"illuminate/auth": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"illuminate/contracts": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"illuminate/http": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"illuminate/support": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"lcobucci/jwt": "^3.2",
"namshi/jose": "^7.0",
"nesbot/carbon": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"mockery/mockery": "0.9.*",
"illuminate/auth": "~5.0",
"illuminate/database": "~5.0",
"illuminate/console" : "~5.0"
"cartalyst/sentinel": "2.0.*",
"illuminate/console": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"illuminate/database": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"illuminate/routing": "5.1.* || 5.2.* || 5.3.* || 5.4.* || 5.5.* || 5.6.*",
"mockery/mockery": ">=0.9.9",
"phpunit/phpunit": "~4.8 || ~6.0"
},
"autoload": {
"psr-4": {
"Tymon\\JWTAuth\\": "src"
"Tymon\\JWTAuth\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tymon\\JWTAuth\\Test\\": "tests"
"Tymon\\JWTAuth\\Test\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "0.5-dev"
"dev-develop": "1.0-dev"
},
"laravel": {
"aliases": {
"JWTAuth": "Tymon\\JWTAuth\\Facades\\JWTAuth",
"JWTFactory": "Tymon\\JWTAuth\\Facades\\JWTFactory"
},
"providers": [
"Tymon\\JWTAuth\\Providers\\LaravelServiceProvider"
]
}
},
"config": {
"sort-packages": true
},
"prefer-stable": true,
"minimum-stability": "dev",
"scripts": {
"test": "phpunit --colors=always",
"test:ci": "composer test -- --verbose --coverage-text --coverage-clover=coverage.xml"
}
}

304
vendor/tymon/jwt-auth/config/config.php vendored Normal file
View File

@@ -0,0 +1,304 @@
<?php
/*
* This file is part of jwt-auth.
*
* (c) Sean Tymon <tymon148@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return [
/*
|--------------------------------------------------------------------------
| JWT Authentication Secret
|--------------------------------------------------------------------------
|
| Don't forget to set this in your .env file, as it will be used to sign
| your tokens. A helper command is provided for this:
| `php artisan jwt:secret`
|
| Note: This will be used for Symmetric algorithms only (HMAC),
| since RSA and ECDSA use a private/public key combo (See below).
|
*/
'secret' => env('JWT_SECRET'),
/*
|--------------------------------------------------------------------------
| JWT Authentication Keys
|--------------------------------------------------------------------------
|
| The algorithm you are using, will determine whether your tokens are
| signed with a random string (defined in `JWT_SECRET`) or using the
| following public & private keys.
|
| Symmetric Algorithms:
| HS256, HS384 & HS512 will use `JWT_SECRET`.
|
| Asymmetric Algorithms:
| RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below.
|
*/
'keys' => [
/*
|--------------------------------------------------------------------------
| Public Key
|--------------------------------------------------------------------------
|
| A path or resource to your public key.
|
| E.g. 'file://path/to/public/key'
|
*/
'public' => env('JWT_PUBLIC_KEY'),
/*
|--------------------------------------------------------------------------
| Private Key
|--------------------------------------------------------------------------
|
| A path or resource to your private key.
|
| E.g. 'file://path/to/private/key'
|
*/
'private' => env('JWT_PRIVATE_KEY'),
/*
|--------------------------------------------------------------------------
| Passphrase
|--------------------------------------------------------------------------
|
| The passphrase for your private key. Can be null if none set.
|
*/
'passphrase' => env('JWT_PASSPHRASE'),
],
/*
|--------------------------------------------------------------------------
| JWT time to live
|--------------------------------------------------------------------------
|
| Specify the length of time (in minutes) that the token will be valid for.
| Defaults to 1 hour.
|
| You can also set this to null, to yield a never expiring token.
| Some people may want this behaviour for e.g. a mobile app.
| This is not particularly recommended, so make sure you have appropriate
| systems in place to revoke the token if necessary.
| Notice: If you set this to null you should remove 'exp' element from 'required_claims' list.
|
*/
'ttl' => env('JWT_TTL', 60),
/*
|--------------------------------------------------------------------------
| Refresh time to live
|--------------------------------------------------------------------------
|
| Specify the length of time (in minutes) that the token can be refreshed
| within. I.E. The user can refresh their token within a 2 week window of
| the original token being created until they must re-authenticate.
| Defaults to 2 weeks.
|
| You can also set this to null, to yield an infinite refresh time.
| Some may want this instead of never expiring tokens for e.g. a mobile app.
| This is not particularly recommended, so make sure you have appropriate
| systems in place to revoke the token if necessary.
|
*/
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),
/*
|--------------------------------------------------------------------------
| JWT hashing algorithm
|--------------------------------------------------------------------------
|
| Specify the hashing algorithm that will be used to sign the token.
|
| See here: https://github.com/namshi/jose/tree/master/src/Namshi/JOSE/Signer/OpenSSL
| for possible values.
|
*/
'algo' => env('JWT_ALGO', 'HS256'),
/*
|--------------------------------------------------------------------------
| Required Claims
|--------------------------------------------------------------------------
|
| Specify the required claims that must exist in any token.
| A TokenInvalidException will be thrown if any of these claims are not
| present in the payload.
|
*/
'required_claims' => [
'iss',
'iat',
'exp',
'nbf',
'sub',
'jti',
],
/*
|--------------------------------------------------------------------------
| Persistent Claims
|--------------------------------------------------------------------------
|
| Specify the claim keys to be persisted when refreshing a token.
| `sub` and `iat` will automatically be persisted, in
| addition to the these claims.
|
| Note: If a claim does not exist then it will be ignored.
|
*/
'persistent_claims' => [
// 'foo',
// 'bar',
],
/*
|--------------------------------------------------------------------------
| Lock Subject
|--------------------------------------------------------------------------
|
| This will determine whether a `prv` claim is automatically added to
| the token. The purpose of this is to ensure that if you have multiple
| authentication models e.g. `App\User` & `App\OtherPerson`, then we
| should prevent one authentication request from impersonating another,
| if 2 tokens happen to have the same id across the 2 different models.
|
| Under specific circumstances, you may want to disable this behaviour
| e.g. if you only have one authentication model, then you would save
| a little on token size.
|
*/
'lock_subject' => true,
/*
|--------------------------------------------------------------------------
| Leeway
|--------------------------------------------------------------------------
|
| This property gives the jwt timestamp claims some "leeway".
| Meaning that if you have any unavoidable slight clock skew on
| any of your servers then this will afford you some level of cushioning.
|
| This applies to the claims `iat`, `nbf` and `exp`.
|
| Specify in seconds - only if you know you need it.
|
*/
'leeway' => env('JWT_LEEWAY', 0),
/*
|--------------------------------------------------------------------------
| Blacklist Enabled
|--------------------------------------------------------------------------
|
| In order to invalidate tokens, you must have the blacklist enabled.
| If you do not want or need this functionality, then set this to false.
|
*/
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
/*
| -------------------------------------------------------------------------
| Blacklist Grace Period
| -------------------------------------------------------------------------
|
| When multiple concurrent requests are made with the same JWT,
| it is possible that some of them fail, due to token regeneration
| on every request.
|
| Set grace period in seconds to prevent parallel request failure.
|
*/
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
/*
|--------------------------------------------------------------------------
| Cookies encryption
|--------------------------------------------------------------------------
|
| By default Laravel encrypt cookies for security reason.
| If you decide to not decrypt cookies, you will have to configure Laravel
| to not encrypt your cookie token by adding its name into the $except
| array available in the middleware "EncryptCookies" provided by Laravel.
| see https://laravel.com/docs/master/responses#cookies-and-encryption
| for details.
|
| Set it to true if you want to decrypt cookies.
|
*/
'decrypt_cookies' => false,
/*
|--------------------------------------------------------------------------
| Providers
|--------------------------------------------------------------------------
|
| Specify the various providers used throughout the package.
|
*/
'providers' => [
/*
|--------------------------------------------------------------------------
| JWT Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to create and decode the tokens.
|
*/
'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class,
/*
|--------------------------------------------------------------------------
| Authentication Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to authenticate users.
|
*/
'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
/*
|--------------------------------------------------------------------------
| Storage Provider
|--------------------------------------------------------------------------
|
| Specify the provider that is used to store tokens in the blacklist.
|
*/
'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
],
];

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="League Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
<exclude>
<file>src/Providers/JWTAuthServiceProvider.php</file>
<directory suffix=".php">src/config/</directory>
<directory suffix=".php">src/Facades/</directory>
</exclude>
</whitelist>
</filter>
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>

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

@@ -9,10 +9,9 @@
* file that was distributed with this source code.
*/
namespace Tymon\JWTAuth\Test\Stubs;
namespace Tymon\JWTAuth\Exceptions;
use Tymon\JWTAuth\Providers\JWT\JWTProvider;
class JWTProviderStub extends JWTProvider
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',
],
];

View File

@@ -1,153 +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\Test\Providers\JWT;
use Carbon\Carbon;
use Mockery;
use Tymon\JWTAuth\Blacklist;
use Tymon\JWTAuth\Payload;
use Tymon\JWTAuth\Claims\Issuer;
use Tymon\JWTAuth\Claims\IssuedAt;
use Tymon\JWTAuth\Claims\Expiration;
use Tymon\JWTAuth\Claims\NotBefore;
use Tymon\JWTAuth\Claims\Subject;
use Tymon\JWTAuth\Claims\JwtId;
class BlacklistTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Carbon::setTestNow(Carbon::createFromTimeStampUTC(123));
$this->storage = Mockery::mock('Tymon\JWTAuth\Providers\Storage\StorageInterface');
$this->blacklist = new Blacklist($this->storage);
$this->blacklist->setRefreshTTL(20160);
$this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator');
$this->validator->shouldReceive('setRefreshFlow->check');
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_add_a_valid_token_to_the_blacklist()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(100 + 3600),
new NotBefore(100),
new IssuedAt(100),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator);
$this->storage->shouldReceive('add')->once()->with('foo', [], 20160);
$this->assertTrue($this->blacklist->add($payload));
}
/** @test */
public function it_should_return_true_when_adding_a_refreshable_expired_token_to_the_blacklist()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(101),
new NotBefore(100),
new IssuedAt(100),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator, true);
$this->storage->shouldReceive('add')->once()->with('foo', [], 20160);
$this->assertTrue($this->blacklist->add($payload));
}
/** @test */
public function it_should_return_false_when_adding_an_unrefreshable_token_to_the_blacklist()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(100), // default refresh_ttl
new NotBefore(100),
new IssuedAt(100 - 20160 * 60),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator, true);
$this->storage->shouldReceive('add')->never();
$this->assertFalse($this->blacklist->add($payload));
}
/** @test */
public function it_should_return_false_when_adding_a_unrefreshable_token_after_modifying_refresh_ttl()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(101),
new NotBefore(100),
new IssuedAt(100),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator, true);
$this->storage->shouldReceive('add')->never();
$this->blacklist->setRefreshTTL(0);
$this->assertFalse($this->blacklist->add($payload));
}
/** @test */
public function it_should_check_whether_a_token_has_been_blacklisted()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foobar'),
];
$payload = new Payload($claims, $this->validator);
$this->storage->shouldReceive('has')->once()->with('foobar')->andReturn(true);
$this->assertTrue($this->blacklist->has($payload));
}
/** @test */
public function it_should_remove_a_token_from_the_blacklist()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foobar'),
];
$payload = new Payload($claims, $this->validator);
$this->storage->shouldReceive('destroy')->once()->with('foobar')->andReturn(true);
$this->assertTrue($this->blacklist->remove($payload));
}
/** @test */
public function it_should_empty_the_blacklist()
{
$this->storage->shouldReceive('flush')->once();
$this->assertTrue($this->blacklist->clear());
}
}

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\Test;
use Symfony\Component\Console\Tester\CommandTester;
use Tymon\JWTAuth\Commands\JWTGenerateCommand;
use Illuminate\Foundation\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
class JWTGenerateCommandTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->command = new JWTGenerateCommand();
$this->tester = new CommandTester($this->command);
}
/** @test */
public function it_shoud_generate_random_key()
{
// $app = new Application();
// $app['path.base'] = '';
// $this->command->setLaravel($app);
// $this->runCommand($this->command);
}
protected function runCommand($command, $input = [])
{
return $command->run(new ArrayInput($input), new NullOutput);
}
}

View File

@@ -1,235 +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\Test;
use Mockery;
use Tymon\JWTAuth\JWTAuth;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Token;
class JWTAuthTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->user = Mockery::mock('Tymon\JWTAuth\Providers\User\UserInterface');
$this->manager = Mockery::mock('Tymon\JWTAuth\JWTManager');
$this->auth = Mockery::mock('Tymon\JWTAuth\Providers\Auth\AuthInterface');
$this->jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, Request::create('/foo', 'GET'));
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_return_a_user_when_passing_a_token_containing_a_valid_subject_claim()
{
$payload = Mockery::mock('Tymon\JWTAuth\Payload');
$payload->shouldReceive('offsetGet')->once()->andReturn(1);
$this->manager->shouldReceive('decode')->once()->andReturn($payload);
$this->user->shouldReceive('getBy')->once()->andReturn((object) ['id' => 1]);
$user = $this->jwtAuth->toUser('foo.bar.baz');
$this->assertEquals(1, $user->id);
}
/** @test */
public function it_should_return_false_when_passing_a_token_containing_an_invalid_subject_claim()
{
$payload = Mockery::mock('Tymon\JWTAuth\Payload');
$payload->shouldReceive('offsetGet')->once()->andReturn(1);
$this->manager->shouldReceive('decode')->once()->andReturn($payload);
$this->user->shouldReceive('getBy')->once()->andReturn(false);
$user = $this->jwtAuth->toUser('foo.bar.baz');
$this->assertFalse($user);
}
/** @test */
public function it_should_return_a_token_when_passing_a_user()
{
$this->manager->shouldReceive('getPayloadFactory->make')->once()->andReturn(Mockery::mock('Tymon\JWTAuth\Payload'));
$this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz');
$token = $this->jwtAuth->fromUser((object) ['id' => 1]);
$this->assertEquals($token, 'foo.bar.baz');
}
/** @test */
public function it_should_return_a_token_when_passing_valid_credentials_to_attempt_method()
{
$this->manager->shouldReceive('getPayloadFactory->make')->once()->andReturn(Mockery::mock('Tymon\JWTAuth\Payload'));
$this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz');
$this->auth->shouldReceive('byCredentials')->once()->andReturn(true);
$this->auth->shouldReceive('user')->once()->andReturn((object) ['id' => 1]);
$token = $this->jwtAuth->attempt();
$this->assertEquals($token, 'foo.bar.baz');
}
/** @test */
public function it_should_return_false_when_passing_invalid_credentials_to_attempt_method()
{
$this->manager->shouldReceive('encode->get')->never();
$this->auth->shouldReceive('byCredentials')->once()->andReturn(false);
$this->auth->shouldReceive('user')->never();
$token = $this->jwtAuth->attempt();
$this->assertFalse($token);
}
/** @test */
public function it_should_throw_an_exception_when_not_providing_a_token()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException');
$this->jwtAuth->toUser();
}
/** @test */
public function it_should_return_the_owning_user_from_a_token_containing_an_existing_user()
{
$payload = Mockery::mock('Tymon\JWTAuth\Payload');
$payload->shouldReceive('get')->once()->with('sub')->andReturn(1);
$this->manager->shouldReceive('decode')->once()->andReturn($payload);
$this->auth->shouldReceive('byId')->once()->with(1)->andReturn(true);
$this->auth->shouldReceive('user')->once()->andReturn((object) ['id' => 1]);
$user = $this->jwtAuth->authenticate('foo.bar.baz');
$this->assertEquals($user->id, 1);
}
/** @test */
public function it_should_return_false_when_passing_a_token_not_containing_an_existing_user()
{
$payload = Mockery::mock('Tymon\JWTAuth\Payload');
$payload->shouldReceive('get')->once()->with('sub')->andReturn(1);
$this->manager->shouldReceive('decode')->once()->andReturn($payload);
$this->auth->shouldReceive('byId')->once()->with(1)->andReturn(false);
$this->auth->shouldReceive('user')->never();
$user = $this->jwtAuth->authenticate('foo.bar.baz');
$this->assertFalse($user);
}
/** @test */
public function it_should_refresh_a_token()
{
$newToken = Mockery::mock('Tymon\JWTAuth\Token');
$newToken->shouldReceive('get')->once()->andReturn('baz.bar.foo');
$this->manager->shouldReceive('refresh')->once()->andReturn($newToken);
$result = $this->jwtAuth->setToken('foo.bar.baz')->refresh();
$this->assertEquals($result, 'baz.bar.foo');
}
/** @test */
public function it_should_invalidate_a_token()
{
$this->manager->shouldReceive('invalidate')->once()->andReturn(true);
$result = $this->jwtAuth->invalidate('foo.bar.baz');
$this->assertTrue($result);
}
/** @test */
public function it_should_retrieve_the_token_from_the_auth_header()
{
$request = Request::create('/foo', 'GET');
$request->headers->set('authorization', 'Bearer foo.bar.baz');
$jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request);
$this->assertInstanceOf('Tymon\JWTAuth\Token', $jwtAuth->parseToken()->getToken());
$this->assertEquals($jwtAuth->getToken(), 'foo.bar.baz');
}
/** @test */
public function it_should_retrieve_the_token_from_the_query_string()
{
$request = Request::create('/foo', 'GET', ['token' => 'foo.bar.baz']);
$jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request);
$this->assertInstanceOf('Tymon\JWTAuth\Token', $jwtAuth->parseToken()->getToken());
$this->assertEquals($jwtAuth->getToken(), 'foo.bar.baz');
}
/** @test */
public function it_should_throw_an_exception_when_token_not_present_in_request()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException');
$request = Request::create('/foo', 'GET');
$jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request);
$jwtAuth->parseToken();
}
/** @test */
public function it_should_return_false_when_no_token_is_set()
{
$this->assertFalse($this->jwtAuth->getToken());
}
/** @test */
public function it_should_set_the_identifier()
{
$this->jwtAuth->setIdentifier('foo');
$this->assertEquals($this->jwtAuth->getIdentifier(), 'foo');
}
/** @test */
public function it_should_magically_call_the_manager()
{
$this->manager->shouldReceive('getBlacklist')->andReturn(new \StdClass);
$blacklist = $this->jwtAuth->getBlacklist();
$this->assertInstanceOf('StdClass', $blacklist);
}
/** @test */
public function it_should_set_the_request()
{
$request = Request::create('/foo', 'GET', ['token' => 'some.random.token']);
$token = $this->jwtAuth->setRequest($request)->getToken();
$this->assertEquals('some.random.token', $token);
}
/** @test */
public function it_should_get_the_manager_instance()
{
$manager = $this->jwtAuth->manager();
$this->assertInstanceOf('Tymon\JWTAuth\JWTManager', $manager);
}
}

View File

@@ -1,188 +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\Test\Providers\JWT;
use Mockery;
use Tymon\JWTAuth\JWTManager;
use Tymon\JWTAuth\Payload;
use Tymon\JWTAuth\Token;
use Tymon\JWTAuth\Claims\Issuer;
use Tymon\JWTAuth\Claims\IssuedAt;
use Tymon\JWTAuth\Claims\Expiration;
use Tymon\JWTAuth\Claims\NotBefore;
use Tymon\JWTAuth\Claims\Subject;
use Tymon\JWTAuth\Claims\JwtId;
class JWTManagerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->jwt = Mockery::mock('Tymon\JWTAuth\Providers\JWT\JWTInterface');
$this->blacklist = Mockery::mock('Tymon\JWTAuth\Blacklist');
$this->factory = Mockery::mock('Tymon\JWTAuth\PayloadFactory');
$this->manager = new JWTManager($this->jwt, $this->blacklist, $this->factory);
$this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator');
$this->validator->shouldReceive('setRefreshFlow->check');
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_encode_a_payload()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator);
$this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('foo.bar.baz');
$token = $this->manager->encode($payload);
$this->assertEquals($token, 'foo.bar.baz');
}
/** @test */
public function it_should_decode_a_token()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator);
$token = new Token('foo.bar.baz');
$this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());
$this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload);
$this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);
$payload = $this->manager->decode($token);
$this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload);
}
/** @test */
public function it_should_throw_exception_when_token_is_blacklisted()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenBlacklistedException');
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator);
$token = new Token('foo.bar.baz');
$this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());
$this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload);
$this->blacklist->shouldReceive('has')->with($payload)->andReturn(true);
$this->manager->decode($token);
}
/** @test */
public function it_should_refresh_a_token()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 - 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator, true);
$token = new Token('foo.bar.baz');
$this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());
$this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('baz.bar.foo');
$this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory);
$this->factory->shouldReceive('make')->andReturn($payload);
$this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);
$this->blacklist->shouldReceive('add')->once()->with($payload);
$token = $this->manager->refresh($token);
$this->assertInstanceOf('Tymon\JWTAuth\Token', $token);
$this->assertEquals('baz.bar.foo', $token);
}
/** @test */
public function it_should_invalidate_a_token()
{
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$payload = new Payload($claims, $this->validator);
$token = new Token('foo.bar.baz');
$this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray());
$this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload);
$this->blacklist->shouldReceive('has')->with($payload)->andReturn(false);
$this->blacklist->shouldReceive('add')->with($payload)->andReturn(true);
$this->manager->invalidate($token);
}
/** @test */
public function it_should_throw_an_exception_when_enable_blacklist_is_set_to_false()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException');
$token = new Token('foo.bar.baz');
$this->manager->setBlacklistEnabled(false)->invalidate($token);
}
/** @test */
public function it_should_get_the_payload_factory()
{
$this->assertInstanceOf('Tymon\JWTAuth\PayloadFactory', $this->manager->getPayloadFactory());
}
/** @test */
public function it_should_get_the_jwt_provider()
{
$this->assertInstanceOf('Tymon\JWTAuth\Providers\JWT\JWTInterface', $this->manager->getJWTProvider());
}
/** @test */
public function it_should_get_the_blacklist()
{
$this->assertInstanceOf('Tymon\JWTAuth\Blacklist', $this->manager->getBlacklist());
}
}

View File

@@ -1,103 +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\Test;
use Mockery;
use Tymon\JWTAuth\Middleware\GetUserFromToken;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class GetUserFromTokenTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
$this->auth = Mockery::mock('Tymon\JWTAuth\JWTAuth');
$this->request = Mockery::mock('Illuminate\Http\Request');
$this->response = Mockery::mock('Illuminate\Contracts\Routing\ResponseFactory');
$this->middleware = new GetUserFromToken($this->response, $this->events, $this->auth);
$this->auth->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_fire_an_event_when_no_token_is_available()
{
$this->auth->shouldReceive('getToken')->once()->andReturn(false);
$this->events->shouldReceive('fire')->once()->with('tymon.jwt.absent', [], true);
$this->response->shouldReceive('json')->with(['error' => 'token_not_provided'], 400);
$this->middleware->handle($this->request, function () {});
}
/** @test */
public function it_should_fire_an_event_when_the_token_has_expired()
{
$exception = new TokenExpiredException;
$this->auth->shouldReceive('getToken')->once()->andReturn('foo');
$this->auth->shouldReceive('authenticate')->once()->with('foo')->andThrow($exception);
$this->events->shouldReceive('fire')->once()->with('tymon.jwt.expired', [$exception], true);
$this->response->shouldReceive('json')->with(['error' => 'token_expired'], 401);
$this->middleware->handle($this->request, function () {});
}
/** @test */
public function it_should_fire_an_event_when_the_token_is_invalid()
{
$exception = new TokenInvalidException;
$this->auth->shouldReceive('getToken')->once()->andReturn('foo');
$this->auth->shouldReceive('authenticate')->once()->with('foo')->andThrow($exception);
$this->events->shouldReceive('fire')->once()->with('tymon.jwt.invalid', [$exception], true);
$this->response->shouldReceive('json')->with(['error' => 'token_invalid'], 400);
$this->middleware->handle($this->request, function () {});
}
/** @test */
public function it_should_fire_an_event_when_no_user_is_found()
{
$this->auth->shouldReceive('getToken')->once()->andReturn('foo');
$this->auth->shouldReceive('authenticate')->once()->with('foo')->andReturn(false);
$this->events->shouldReceive('fire')->once()->with('tymon.jwt.user_not_found', [], true);
$this->response->shouldReceive('json')->with(['error' => 'user_not_found'], 404);
$this->middleware->handle($this->request, function () {});
}
/** @test */
public function it_should_fire_an_event_when_the_token_has_been_decoded_and_user_is_found()
{
$user = (object) ['id' => 1];
$this->auth->shouldReceive('getToken')->once()->andReturn('foo');
$this->auth->shouldReceive('authenticate')->once()->with('foo')->andReturn($user);
$this->events->shouldReceive('fire')->once()->with('tymon.jwt.valid', $user);
$this->response->shouldReceive('json')->never();
$this->middleware->handle($this->request, function () {});
}
}

View File

@@ -1,115 +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\Test\Providers\JWT;
use Carbon\Carbon;
use Mockery;
use Tymon\JWTAuth\PayloadFactory;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Claims\Issuer;
use Tymon\JWTAuth\Claims\IssuedAt;
use Tymon\JWTAuth\Claims\Expiration;
use Tymon\JWTAuth\Claims\NotBefore;
use Tymon\JWTAuth\Claims\Subject;
use Tymon\JWTAuth\Claims\JwtId;
use Tymon\JWTAuth\Claims\Custom;
class PayloadFactoryTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Carbon::setTestNow(Carbon::createFromTimeStampUTC(123));
$this->claimFactory = Mockery::mock('Tymon\JWTAuth\Claims\Factory');
$this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator');
$this->factory = new PayloadFactory($this->claimFactory, Request::create('/foo', 'GET'), $this->validator);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_return_a_payload_when_passing_an_array_of_claims_to_make_method()
{
$this->validator->shouldReceive('setRefreshFlow->check');
$expTime = 123 + 3600;
$this->claimFactory->shouldReceive('get')->once()->with('sub', 1)->andReturn(new Subject(1));
$this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo'));
$this->claimFactory->shouldReceive('get')->once()->with('iat', 123)->andReturn(new IssuedAt(123));
$this->claimFactory->shouldReceive('get')->once()->with('jti', 'foo')->andReturn(new JwtId('foo'));
$this->claimFactory->shouldReceive('get')->once()->with('nbf', 123)->andReturn(new NotBefore(123));
$this->claimFactory->shouldReceive('get')->once()->with('exp', $expTime)->andReturn(new Expiration($expTime));
$payload = $this->factory->make(['sub' => 1, 'jti' => 'foo', 'iat' => 123]);
$this->assertEquals($payload->get('sub'), 1);
$this->assertEquals($payload->get('iat'), 123);
$this->assertEquals($payload['exp'], $expTime);
$this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload);
}
/** @test */
public function it_should_return_a_payload_when_chaining_claim_methods()
{
$this->validator->shouldReceive('setRefreshFlow->check');
$this->claimFactory->shouldReceive('get')->once()->with('sub', 1)->andReturn(new Subject(1));
$this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo'));
$this->claimFactory->shouldReceive('get')->once()->with('exp', 123 + 3600)->andReturn(new Expiration(123 + 3600));
$this->claimFactory->shouldReceive('get')->once()->with('iat', 123)->andReturn(new IssuedAt(123));
$this->claimFactory->shouldReceive('get')->once()->with('jti', Mockery::any())->andReturn(new JwtId('foo'));
$this->claimFactory->shouldReceive('get')->once()->with('nbf', 123)->andReturn(new NotBefore(123));
$this->claimFactory->shouldReceive('get')->once()->with('foo', 'baz')->andReturn(new Custom('foo', 'baz'));
$payload = $this->factory->sub(1)->foo('baz')->make();
$this->assertEquals($payload['sub'], 1);
$this->assertEquals($payload->get('jti'), 'foo');
$this->assertEquals($payload->get('foo'), 'baz');
$this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload);
}
/** @test */
public function it_should_return_a_payload_when_passing_miltidimensional_array_as_custom_claim_to_make_method()
{
$this->validator->shouldReceive('setRefreshFlow->check');
$this->claimFactory->shouldReceive('get')->once()->with('sub', 1)->andReturn(new Subject(1));
$this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo'));
$this->claimFactory->shouldReceive('get')->once()->with('exp', Mockery::any())->andReturn(new Expiration(123 + 3600));
$this->claimFactory->shouldReceive('get')->once()->with('iat', Mockery::any())->andReturn(new IssuedAt(123));
$this->claimFactory->shouldReceive('get')->once()->with('jti', Mockery::any())->andReturn(new JwtId('foo'));
$this->claimFactory->shouldReceive('get')->once()->with('nbf', Mockery::any())->andReturn(new NotBefore(123));
$this->claimFactory->shouldReceive('get')->once()->with('foo', ['bar' => [0, 0, 0]])->andReturn(new Custom('foo', ['bar' => [0, 0, 0]]));
$payload = $this->factory->sub(1)->foo(['bar' => [0, 0, 0]])->make();
$this->assertEquals($payload->get('sub'), 1);
$this->assertEquals($payload->get('foo'), ['bar' => [0, 0, 0]]);
$this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload);
}
/** @test */
public function it_should_set_the_ttl()
{
$this->factory->setTTL(12345);
$this->assertEquals($this->factory->getTTL(), 12345);
}
}

View File

@@ -1,136 +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\Test\Providers\JWT;
use Carbon\Carbon;
use Tymon\JWTAuth\Payload;
use Mockery;
use Tymon\JWTAuth\Claims\Issuer;
use Tymon\JWTAuth\Claims\IssuedAt;
use Tymon\JWTAuth\Claims\Expiration;
use Tymon\JWTAuth\Claims\NotBefore;
use Tymon\JWTAuth\Claims\Audience;
use Tymon\JWTAuth\Claims\Subject;
use Tymon\JWTAuth\Claims\JwtId;
class PayloadTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Carbon::setTestNow(Carbon::createFromTimeStampUTC(123));
$claims = [
new Subject(1),
new Issuer('http://example.com'),
new Expiration(123 + 3600),
new NotBefore(123),
new IssuedAt(123),
new JwtId('foo'),
];
$this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator');
$this->validator->shouldReceive('setRefreshFlow->check');
$this->payload = new Payload($claims, $this->validator);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_throws_an_exception_when_trying_to_add_to_the_payload()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\PayloadException');
$this->payload['foo'] = 'bar';
}
/** @test */
public function it_throws_an_exception_when_trying_to_remove_a_key_from_the_payload()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\PayloadException');
unset($this->payload['foo']);
}
/** @test */
public function it_should_cast_the_payload_to_a_string_as_json()
{
$this->assertEquals((string) $this->payload, json_encode($this->payload->get()));
$this->assertJsonStringEqualsJsonString((string) $this->payload, json_encode($this->payload->get()));
}
/** @test */
public function it_should_allow_array_access_on_the_payload()
{
$this->assertTrue(isset($this->payload['iat']));
$this->assertEquals($this->payload['sub'], 1);
$this->assertArrayHasKey('exp', $this->payload);
}
/** @test */
public function it_should_get_properties_of_payload_via_get_method()
{
$this->assertInternalType('array', $this->payload->get());
$this->assertEquals($this->payload->get('sub'), 1);
}
/** @test */
public function it_should_get_multiple_properties_when_passing_an_array_to_the_get_method()
{
$values = $this->payload->get(['sub', 'jti']);
list($sub, $jti) = $values;
$this->assertInternalType('array', $values);
$this->assertEquals($sub, 1);
$this->assertEquals($jti, 'foo');
}
/** @test */
public function it_should_determine_whether_the_payload_has_a_claim()
{
$this->assertTrue($this->payload->has(new Subject(1)));
$this->assertFalse($this->payload->has(new Audience(1)));
}
/** @test */
public function it_should_magically_get_a_property()
{
$sub = $this->payload->getSubject();
$jti = $this->payload->getJwtId();
$iss = $this->payload->getIssuer();
$this->assertEquals($sub, 1);
$this->assertEquals($jti, 'foo');
$this->assertEquals($iss, 'http://example.com');
}
/** @test */
public function it_should_throw_an_exception_when_magically_getting_a_property_that_does_not_exist()
{
$this->setExpectedException('\BadMethodCallException');
$this->payload->getFoo();
}
/** @test */
public function it_should_get_the_claims()
{
$claims = $this->payload->getClaims();
$this->assertInstanceOf('Tymon\JWTAuth\Claims\Expiration', $claims[2]);
$this->assertInstanceOf('Tymon\JWTAuth\Claims\JwtId', $claims[5]);
}
}

View File

@@ -1,65 +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\Test\Providers\Auth;
use Mockery;
use Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter;
class IlluminateAuthAdapterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->authManager = Mockery::mock('Illuminate\Auth\AuthManager');
$this->auth = new IlluminateAuthAdapter($this->authManager);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_return_true_if_credentials_are_valid()
{
$this->authManager->shouldReceive('once')->once()->with(['email' => 'foo@bar.com', 'password' => 'foobar'])->andReturn(true);
$this->assertTrue($this->auth->byCredentials(['email' => 'foo@bar.com', 'password' => 'foobar']));
}
/** @test */
public function it_should_return_true_if_user_is_found()
{
$this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(true);
$this->assertTrue($this->auth->byId(123));
}
/** @test */
public function it_should_return_false_if_user_is_not_found()
{
$this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(false);
$this->assertFalse($this->auth->byId(123));
}
/** @test */
public function it_should_bubble_exceptions_from_auth()
{
$this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andThrow(new \Exception('Some auth failure'));
$this->setExpectedException('Exception', 'Some auth failure');
$this->auth->byId(123);
}
/** @test */
public function it_should_return_the_currently_authenticated_user()
{
$this->authManager->shouldReceive('user')->once()->andReturn((object) ['id' => 1]);
$this->assertEquals($this->auth->user()->id, 1);
}
}

View File

@@ -1,36 +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\Test\Providers\JWT;
use Mockery;
use Tymon\JWTAuth\Test\Stubs\JWTProviderStub;
class JWTProviderTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->provider = new JWTProviderStub('secret', 'HS256');
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_set_the_algo()
{
$this->provider->setAlgo('HS512');
$this->assertEquals('HS512', $this->provider->getAlgo());
}
}

View File

@@ -1,77 +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\Test\Providers\JWT;
use Carbon\Carbon;
use Mockery;
use Tymon\JWTAuth\Providers\JWT\NamshiAdapter;
class NamshiAdapterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Carbon::setTestNow(Carbon::createFromTimeStampUTC(123));
$this->jws = Mockery::mock('Namshi\JOSE\JWS');
$this->provider = new NamshiAdapter('secret', 'HS256', $this->jws);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_return_the_token_when_passing_a_valid_subject_to_encode()
{
$payload = ['sub' => 1, 'exp' => 123, 'iat' => 123, 'iss' => '/foo'];
$this->jws->shouldReceive('setPayload')->once()->with($payload)->andReturn(Mockery::self());
$this->jws->shouldReceive('sign')->once()->with('secret')->andReturn(Mockery::self());
$this->jws->shouldReceive('getTokenString')->once()->andReturn('foo.bar.baz');
$token = $this->provider->encode($payload);
$this->assertEquals('foo.bar.baz', $token);
}
/** @test */
public function it_should_throw_an_invalid_exception_when_the_payload_could_not_be_encoded()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException');
$this->jws->shouldReceive('sign')->andThrow(new \Exception);
$payload = ['sub' => 1, 'exp' => 123, 'iat' => 123, 'iss' => '/foo'];
$this->provider->encode($payload);
}
/** @test */
// public function it_should_return_the_payload_when_passing_a_valid_token_to_decode()
// {
// $this->jws->shouldReceive('load')->once()->with('foo.bar.baz')->andReturn(true);
// $this->jws->shouldReceive('verify')->andReturn(true);
// $payload = $this->provider->decode('foo.bar.baz');
// }
/** @test */
public function it_should_throw_a_token_invalid_exception_when_the_token_could_not_be_decoded()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException');
$this->jws->shouldReceive('verify')->andReturn(false);
$token = $this->provider->decode('foo');
}
}

View File

@@ -1,63 +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\Test\Providers\Storage;
use Mockery;
use Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter;
class IlluminateCacheAdapterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->cache = Mockery::mock('Illuminate\Cache\CacheManager');
$this->storage = new IlluminateCacheAdapter($this->cache);
$this->cache->shouldReceive('tags')->andReturn(Mockery::self());
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_add_the_item_to_storage()
{
$this->cache->shouldReceive('tags->put')->with('foo', 'bar', 10);
$this->storage->add('foo', 'bar', 10);
}
/** @test */
public function it_should_check_if_the_item_exists_in_storage()
{
$this->cache->shouldReceive('tags->has')->with('foo')->andReturn(true);
$this->assertTrue($this->storage->has('foo'));
}
/** @test */
public function it_should_remove_the_item_from_storage()
{
$this->cache->shouldReceive('tags->forget')->with('foo')->andReturn(true);
$this->assertTrue($this->storage->destroy('foo'));
}
/** @test */
public function it_should_remove_all_items_from_storage()
{
$this->cache->shouldReceive('tags->flush')->withNoArgs();
$this->storage->flush();
}
}

View File

@@ -1,41 +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\Test\Providers\User;
use Mockery;
use Tymon\JWTAuth\Providers\User\EloquentUserAdapter;
class EloquentUserAdapterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->builder = Mockery::mock('Illuminate\Database\Query\Builder');
$this->model = Mockery::mock('Illuminate\Database\Eloquent\Model');
$this->user = new EloquentUserAdapter($this->model);
}
public function tearDown()
{
Mockery::close();
}
/** @test */
public function it_should_return_the_user_if_found()
{
$this->builder->shouldReceive('first')->once()->withNoArgs()->andReturn((object) ['id' => 1]);
$this->model->shouldReceive('where')->once()->with('foo', 'bar')->andReturn($this->builder);
$user = $this->user->getBy('foo', 'bar');
$this->assertEquals(1, $user->id);
}
}

View File

@@ -1,34 +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\Test\Providers\JWT;
use Tymon\JWTAuth\Token;
class TokenTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->token = new Token('foo.bar.baz');
}
/** @test */
public function it_should_return_the_token_when_casting_to_a_string()
{
$this->assertEquals((string) $this->token, $this->token);
}
/** @test */
public function it_should_return_the_token_when_calling_get_method()
{
$this->assertInternalType('string', $this->token->get());
}
}

View File

@@ -1,119 +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\Test;
use Carbon\Carbon;
use Tymon\JWTAuth\Validators\PayloadValidator;
class PayloadValidatorTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
Carbon::setTestNow(Carbon::createFromTimeStampUTC(123));
$this->validator = new PayloadValidator();
}
/** @test */
public function it_should_return_true_when_providing_a_valid_payload()
{
$payload = [
'iss' => 'http://example.com',
'iat' => 100,
'nbf' => 100,
'exp' => 100 + 3600,
'sub' => 1,
'jti' => 'foo',
];
$this->assertTrue($this->validator->isValid($payload));
}
/** @test */
public function it_should_throw_an_exception_when_providing_an_expired_payload()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenExpiredException');
$payload = [
'iss' => 'http://example.com',
'iat' => 20,
'nbf' => 20,
'exp' => 120,
'sub' => 1,
'jti' => 'foo',
];
$this->validator->check($payload);
}
/** @test */
public function it_should_throw_an_exception_when_providing_an_invalid_nbf_claim()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException');
$payload = [
'iss' => 'http://example.com',
'iat' => 100,
'nbf' => 150,
'exp' => 150 + 3600,
'sub' => 1,
'jti' => 'foo',
];
$this->validator->check($payload);
}
/** @test */
public function it_should_throw_an_exception_when_providing_an_invalid_iat_claim()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException');
$payload = [
'iss' => 'http://example.com',
'iat' => 150,
'nbf' => 100,
'exp' => 150 + 3600,
'sub' => 1,
'jti' => 'foo',
];
$this->validator->check($payload);
}
/** @test */
public function it_should_throw_an_exception_when_providing_an_invalid_payload()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException');
$payload = [
'iss' => 'http://example.com',
'sub' => 1,
];
$this->validator->check($payload);
}
/** @test */
public function it_should_throw_an_exception_when_providing_an_invalid_expiry()
{
$this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException');
$payload = [
'iss' => 'http://example.com',
'iat' => 100,
'exp' => 'foo',
'sub' => 1,
'jti' => 'foo',
];
$this->validator->check($payload);
}
}

Some files were not shown because too many files have changed in this diff Show More