I want to have JWT authentication in Laravel >=5.2, using this (Tymon JWT-auth) library but I want to put JWT token into HttpOnly Cookies - to protect JWT token from steal from XSS attack.
- I set up Tymon library and... in project: app/Providers/RouteServiceProvider@mapWebRoutes i deactivate execution 'web' middelware group for all requests (which is default laravel behavior - you can see it by
php artisan route:list
) by remove'middleware' => 'web'
(If I don't do it, i will see CSRF problem with post request). - in routes.php i write:
Route::group(['middleware' =>'api', 'prefix' => '/api/v1', 'namespace' => 'Api\V1'], function () { Route::post('/login', 'Auth\AuthController@postLogin'); ... Route::get('/projects', 'ProjectsController@getProjects'); }
In may Api\V1\Auth\AuthController@postLogin i generate token and send it back as httpOnly cookie:
... try { $user = User::where('email','=',$credentials['email'])->first(); if ( !($user && Hash::check($credentials['password'], $user->password) )) { return response()->json(['error' => 'invalid_credentials'], 401); } $customClaims = ['sub' => $user->id, 'role'=> $user->role, 'csrf-token' => str_random(32) ]; $payload = JWTFactory::make($customClaims); $token = JWTAuth::encode($payload); } catch(...) {...} return response()->json($payload->toArray())->withCookie('token', $token, config('jwt.ttl'), "/", null, false, true);
And, yeah here question starts. I would like to do something (may be modifiy laravel
Auth
class) on each request:- get coookie from request
- decode it
- check is right (if not trhow 401)
- get user from DB
- and make that method Auth::user() works every where like in usual way in laravel (so i can use it in each Controller for example)
Any ideas how to do point 4 ?
UPDATE
I also add here protection for CSRF attack - csrf-token is in JWT, and it is also return in body of response for login request (so JS have acces to this csrf-token) (i return only public part of JWT token in login response, whole JWT is return only in cookie, so it is XSS safe) - then front JS must copy csrf-token into header of each request. Then the middelware JWTAuthentiacate (in my answer below) compare csrf-token header with csrf-token field in JWT payload - if they are similar then request pass csrf test.