diff --git a/app/User.php b/app/User.php index 1b387d0..b25a9f0 100755 --- a/app/User.php +++ b/app/User.php @@ -6,6 +6,7 @@ use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; +use Tymon\JWTAuth\Contracts\JWTSubject; /** * App\User @@ -26,7 +27,7 @@ * @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Permission\Models\Role[] $roles * @property-read \Illuminate\Database\Eloquent\Collection|\App\Post[] $posts */ -class User extends Authenticatable +class User extends Authenticatable implements JWTSubject { use Notifiable, HasRoles; @@ -59,6 +60,26 @@ class User extends Authenticatable */ protected $appends = ['name']; + /** + * Get the identifier that will be stored in the subject claim of the JWT. + * + * @return mixed + */ + public function getJWTIdentifier() + { + return $this->getKey(); + } + + /** + * Return a key value array, containing any custom claims to be added to the JWT. + * + * @return array + */ + public function getJWTCustomClaims() + { + return []; + } + /** * Get the profile associated with the user. * diff --git a/composer.json b/composer.json index 53b5952..db2d637 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "laravel/tinker": "^1.0", "mews/purifier": "^2.0", "spatie/laravel-permission": "^2.7", - "tymon/jwt-auth": "^0.5.12" + "tymon/jwt-auth": "^1.0.0-rc.2" }, "require-dev": { "filp/whoops": "^2.0", diff --git a/config/app.php b/config/app.php index 0d60cb4..4180bbf 100755 --- a/config/app.php +++ b/config/app.php @@ -150,7 +150,7 @@ /* * Package Service Providers... */ - Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, + Tymon\JWTAuth\Providers\LaravelServiceProvider::class, /* * Application Service Providers... @@ -207,10 +207,7 @@ 'Storage' => Illuminate\Support\Facades\Storage::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, - 'View' => Illuminate\Support\Facades\View::class, - 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, - 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class, - + 'View' => Illuminate\Support\Facades\View::class ], ]; diff --git a/config/jwt.php b/config/jwt.php old mode 100755 new mode 100644 index b23e985..c4ea92d --- a/config/jwt.php +++ b/config/jwt.php @@ -16,24 +16,91 @@ | 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` + | 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 + | 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. | */ - 'ttl' => 600, + 'ttl' => env('JWT_TTL', 60), /* |-------------------------------------------------------------------------- @@ -43,11 +110,16 @@ | 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 + | 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' => 20160, + 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), /* |-------------------------------------------------------------------------- @@ -56,49 +128,86 @@ | | 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 + | See here: https://github.com/namshi/jose/tree/master/src/Namshi/JOSE/Signer/OpenSSL + | for possible values. | */ - 'algo' => 'HS256', + 'algo' => env('JWT_ALGO', 'HS256'), /* |-------------------------------------------------------------------------- - | User Model namespace + | Required Claims |-------------------------------------------------------------------------- | - | Specify the full namespace to your User model. - | e.g. 'Acme\Entities\User' + | 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. | */ - 'user' => 'App\User', + 'required_claims' => [ + 'iss', + 'iat', + 'exp', + 'nbf', + 'sub', + 'jti', + ], /* |-------------------------------------------------------------------------- - | User identifier + | Persistent Claims |-------------------------------------------------------------------------- | - | Specify a unique property of the user that will be added as the 'sub' - | claim of the token payload. + | 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. | */ - 'identifier' => 'id', + 'persistent_claims' => [ + // 'foo', + // 'bar', + ], /* |-------------------------------------------------------------------------- - | Required Claims + | Lock Subject |-------------------------------------------------------------------------- | - | 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. + | 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. | */ - 'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'], + 'leeway' => env('JWT_LEEWAY', 0), /* |-------------------------------------------------------------------------- @@ -112,6 +221,39 @@ '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 @@ -123,18 +265,6 @@ '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 @@ -144,7 +274,7 @@ | */ - 'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter', + 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, /* |-------------------------------------------------------------------------- @@ -155,18 +285,18 @@ | */ - 'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter', + 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, /* |-------------------------------------------------------------------------- | Storage Provider |-------------------------------------------------------------------------- | - | Specify the provider that is used to store tokens in the blacklist + | Specify the provider that is used to store tokens in the blacklist. | */ - 'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter', + 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, ],