Commit 30c98fd9 authored by Viral Solani's avatar Viral Solani

Change JWT configuration (WIP)

parent b788def5
...@@ -16,6 +16,7 @@ Thumbs.db ...@@ -16,6 +16,7 @@ Thumbs.db
_ide_helper.php _ide_helper.php
composer.phar composer.phar
error.log error.log
access.log
Todo.rtf Todo.rtf
.vagrant .vagrant
/.vagrant /.vagrant
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api\V1; ...@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api\V1;
use App\Models\Access\User\User; use App\Models\Access\User\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use JWTAuth; use Illuminate\Support\Facades\Auth;
use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Exceptions\JWTException;
use Validator; use Validator;
...@@ -20,8 +20,8 @@ class AuthController extends APIController ...@@ -20,8 +20,8 @@ class AuthController extends APIController
public function login(Request $request) public function login(Request $request)
{ {
$validation = Validator::make($request->all(), [ $validation = Validator::make($request->all(), [
'email' => 'required|email', 'email' => 'required|email',
'password' => 'required|min:4', 'password' => 'required|min:4',
]); ]);
if ($validation->fails()) { if ($validation->fails()) {
...@@ -31,17 +31,24 @@ class AuthController extends APIController ...@@ -31,17 +31,24 @@ class AuthController extends APIController
$credentials = $request->only(['email', 'password']); $credentials = $request->only(['email', 'password']);
try { try {
if (!$token = JWTAuth::attempt($credentials)) { if (!$token = auth('api')->attempt($credentials)) {
return $this->throwValidation(trans('api.messages.login.failed')); return $this->throwValidation(trans('api.messages.login.failed'));
} }
} catch (JWTException $e) { } catch (JWTException $e) {
return $this->respondInternalError($e->getMessage()); return $this->respondInternalError($e->getMessage());
} }
return $this->respond([ return $this->respondWithToken($token);
'message' => trans('api.messages.login.success'), }
'token' => $token,
]); /**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json($this->guard()->user());
} }
/** /**
...@@ -51,19 +58,9 @@ class AuthController extends APIController ...@@ -51,19 +58,9 @@ class AuthController extends APIController
*/ */
public function logout() public function logout()
{ {
try { $this->guard()->logout();
$token = JWTAuth::getToken();
if ($token) { return response()->json(['message' => 'Successfully logged out']);
JWTAuth::invalidate($token);
}
} catch (JWTException $e) {
return $this->respondInternalError($e->getMessage());
}
return $this->respond([
'message' => trans('api.messages.logout.success'),
]);
} }
/** /**
...@@ -73,21 +70,79 @@ class AuthController extends APIController ...@@ -73,21 +70,79 @@ class AuthController extends APIController
*/ */
public function refresh() public function refresh()
{ {
$token = JWTAuth::getToken(); return $this->respondWithToken($this->guard()->refresh());
}
if (!$token) {
$this->respondUnauthorized(trans('api.messages.refresh.token.not_provided'));
}
try {
$refreshedToken = JWTAuth::refresh($token);
} catch (JWTException $e) {
return $this->respondInternalError($e->getMessage());
}
return $this->respond([ /**
'status' => trans('api.messages.refresh.status'), * Get the token array structure.
'token' => $refreshedToken, *
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
// 'token_type' => 'bearer',
// 'expires_in' => $this->guard()->factory()->getTTL() * 60
]); ]);
} }
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\Guard
*/
public function guard()
{
return Auth::guard('api');
}
/*
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
// public function logout()
// {
// try {
// $token = JWTAuth::getToken();
// if ($token) {
// JWTAuth::invalidate($token);
// }
// } catch (JWTException $e) {
// return $this->respondInternalError($e->getMessage());
// }
// return $this->respond([
// 'message' => trans('api.messages.logout.success'),
// ]);
// }
/*
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
// public function refresh()
// {
// $token = JWTAuth::getToken();
// if (!$token) {
// $this->respondUnauthorized(trans('api.messages.refresh.token.not_provided'));
// }
// try {
// $refreshedToken = JWTAuth::refresh($token);
// } catch (JWTException $e) {
// return $this->respondInternalError($e->getMessage());
// }
// return $this->respond([
// 'status' => trans('api.messages.refresh.status'),
// 'token' => $refreshedToken,
// ]);
// }
} }
...@@ -63,20 +63,20 @@ class Kernel extends HttpKernel ...@@ -63,20 +63,20 @@ class Kernel extends HttpKernel
* @var array * @var array
*/ */
protected $routeMiddleware = [ protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'timeout' => \App\Http\Middleware\SessionTimeout::class, 'timeout' => \App\Http\Middleware\SessionTimeout::class,
/* /*
* Access Middleware * Access Middleware
*/ */
'access.routeNeedsRole' => \App\Http\Middleware\RouteNeedsRole::class, 'access.routeNeedsRole' => \App\Http\Middleware\RouteNeedsRole::class,
'access.routeNeedsPermission' => \App\Http\Middleware\RouteNeedsPermission::class, 'access.routeNeedsPermission' => \App\Http\Middleware\RouteNeedsPermission::class,
'jwt.auth' => GetUserFromToken::class, // 'jwt.auth' => GetUserFromToken::class,
'jwt.refresh' => RefreshToken::class, // 'jwt.refresh' => RefreshToken::class,
]; ];
} }
...@@ -78,6 +78,18 @@ class User extends Authenticatable implements JWTSubject ...@@ -78,6 +78,18 @@ class User extends Authenticatable implements JWTSubject
return $this->getKey(); return $this->getKey();
} }
/**
* Set password attribute.
*
* @param [string] $password
*/
public function setPasswordAttribute($password)
{
if (!empty($password)) {
$this->attributes['password'] = bcrypt($password);
}
}
/** /**
* Return a key value array, containing any custom claims to be added to the JWT. * Return a key value array, containing any custom claims to be added to the JWT.
* *
...@@ -86,17 +98,17 @@ class User extends Authenticatable implements JWTSubject ...@@ -86,17 +98,17 @@ class User extends Authenticatable implements JWTSubject
public function getJWTCustomClaims() public function getJWTCustomClaims()
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
'first_name' => $this->first_name, 'first_name' => $this->first_name,
'last_name' => $this->last_name, 'last_name' => $this->last_name,
'email' => $this->email, 'email' => $this->email,
'picture' => $this->getPicture(), 'picture' => $this->getPicture(),
'confirmed' => $this->confirmed, 'confirmed' => $this->confirmed,
'role' => optional($this->roles()->first())->name, 'role' => optional($this->roles()->first())->name,
'permissions' => $this->permissions()->get(), 'permissions' => $this->permissions()->get(),
'status' => $this->status, 'status' => $this->status,
'created_at' => $this->created_at->toIso8601String(), 'created_at' => $this->created_at->toIso8601String(),
'updated_at' => $this->updated_at->toIso8601String(), 'updated_at' => $this->updated_at->toIso8601String(),
]; ];
} }
} }
...@@ -9,8 +9,9 @@ ...@@ -9,8 +9,9 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
return [ use Tymon\JWTAuth\Claims;
return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| JWT Authentication Secret | JWT Authentication Secret
...@@ -45,7 +46,6 @@ return [ ...@@ -45,7 +46,6 @@ return [
*/ */
'keys' => [ 'keys' => [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Public Key | Public Key
...@@ -82,7 +82,6 @@ return [ ...@@ -82,7 +82,6 @@ return [
*/ */
'passphrase' => env('JWT_PASSPHRASE'), 'passphrase' => env('JWT_PASSPHRASE'),
], ],
/* /*
...@@ -91,7 +90,7 @@ return [ ...@@ -91,7 +90,7 @@ return [
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Specify the length of time (in minutes) that the token will be valid for. | Specify the length of time (in minutes) that the token will be valid for.
| Defaults to 1 hour. | Defaults to 30 minutes.
| |
| You can also set this to null, to yield a never expiring token. | 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. | Some people may want this behaviour for e.g. a mobile app.
...@@ -100,26 +99,21 @@ return [ ...@@ -100,26 +99,21 @@ return [
| |
*/ */
'ttl' => env('JWT_TTL', 60), 'ttl' => env('JWT_TTL', 30),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Refresh time to live | Max refresh period
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Specify the length of time (in minutes) that the token can be refreshed | Specify the length of time (in minutes) that the token will be
| within. I.E. The user can refresh their token within a 2 week window of | refreshable for.
| 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. | Defaults to null, which will allow tokens to be refreshable forever.
| 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), 'max_refresh_period' => env('JWT_MAX_REFRESH_PERIOD'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -128,8 +122,11 @@ return [ ...@@ -128,8 +122,11 @@ return [
| |
| Specify the hashing algorithm that will be used to sign the token. | 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 | Possible values:
| for possible values. |
| 'HS256', 'HS384', 'HS512',
| 'RS256', 'RS384', 'RS512',
| 'ES256', 'ES384', 'ES512'
| |
*/ */
...@@ -147,31 +144,48 @@ return [ ...@@ -147,31 +144,48 @@ return [
*/ */
'required_claims' => [ 'required_claims' => [
'iss', Claims\Issuer::NAME,
'iat', Claims\IssuedAt::NAME,
'exp', Claims\Expiration::NAME,
'nbf', Claims\Subject::NAME,
'sub', Claims\JwtId::NAME,
'jti',
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Persistent Claims | Lock Subject
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Specify the claim keys to be persisted when refreshing a token. | This will determine whether a `prv` claim is automatically added to
| `sub` and `iat` will automatically be persisted, in | the token. The purpose of this is to ensure that if you have multiple
| addition to the these claims. | 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.
| |
| Note: If a claim does not exist then it will be ignored. | 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.
| |
*/ */
'persistent_claims' => [ 'lock_subject' => true,
// 'foo',
// 'bar', /*
], |--------------------------------------------------------------------------
| 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),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -212,11 +226,11 @@ return [ ...@@ -212,11 +226,11 @@ return [
| see https://laravel.com/docs/master/responses#cookies-and-encryption | see https://laravel.com/docs/master/responses#cookies-and-encryption
| for details. | for details.
| |
| Set it to false if you don't want to decrypt cookies. | Set it to true if you want to decrypt cookies.
| |
*/ */
'decrypt_cookies' => true, 'decrypt_cookies' => false,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -228,7 +242,6 @@ return [ ...@@ -228,7 +242,6 @@ return [
*/ */
'providers' => [ 'providers' => [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| JWT Provider | JWT Provider
...@@ -238,18 +251,7 @@ return [ ...@@ -238,18 +251,7 @@ return [
| |
*/ */
'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class, '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,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
...@@ -261,7 +263,5 @@ return [ ...@@ -261,7 +263,5 @@ return [
*/ */
'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
], ],
]; ];
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Tests\Feature\Api\V1; namespace Tests\Feature\Api\V1;
use Illuminate\Support\Facades\Auth;
use Tests\TestCase; use Tests\TestCase;
class LoginTest extends TestCase class LoginTest extends TestCase
...@@ -11,9 +10,9 @@ class LoginTest extends TestCase ...@@ -11,9 +10,9 @@ class LoginTest extends TestCase
public function users_can_login_through_api() public function users_can_login_through_api()
{ {
$res = $this->json('POST', '/api/v1/auth/login', [ $res = $this->json('POST', '/api/v1/auth/login', [
'email' => $this->user->email, 'email' => $this->user->email,
'password' => '1234', 'password' => '1234',
]) ])
->assertStatus(200) ->assertStatus(200)
->assertJsonStructure([ ->assertJsonStructure([
'message', 'message',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment