JWT::getToken() doesn't get the proper token - laravel

I'm using JWT-Auth for authentication. I have created a middleware that checks if token is expired and then it refreshes the token and update the header. But in my controller getToken() does not get the new token but returns the expired one. I have checked the value of header in my controller and it has the new token.
This is how I do it in my middleware:
$new_token = JWTAuth::refresh($token);
$request->headers->set('Authorization', 'Bearer '.$new_token);
$response = $next($request);
and this is in my controller:
$token = JWTAuth::getToken();

After looking at their code. I found a setToken() function which solved my issue. I modified my code like this:
$new_token = JWTAuth::refresh($token);
JWTAuth::setToken($new_token);
$response = $next($request);
$response->header('Authorization','Bearer '.$new_token);
return $response;

Change version of JWT package 5.12 to 5.11 in composer.json file then its work properly.
I was also stuck in same issue before few days
https://github.com/tymondesigns/jwt-auth/issues/1198

Related

How can write test for laravel api route with auth.basic middleware

My laravel project has an API route by auth.basic middleware which is used id of the authenticated user in the controller. when I call it in postman it works well and I get 401 when the username or password is incorrect, but in laravel APITest which extends from DuskTestCase, authentication does not take place so I get 500 instead of 401 when the user's informations were incorrect. However, by correct information, I have the same error because auth() is null.
it is written like below, which is wrong?
api.php route:
Route::get('/xxxxxx/xxxxxx/xxxxxxx', 'xxxxx#xxxx')->middleware('auth.basic');
APITest:
$response = $this->withHeaders(['Authorization' => 'Basic '. base64_encode("{$username}:{$password}")])->get("/xxxxxx/xxxxxx/xxxxxxx");
You can use actingAs() method for authentication in tests.
An example from docs:
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
Another example that you can use for an API:
$user = User::factory()->create();
$response = $this->actingAs($user)->json('GET', $this->uri);
$response->assertOk();
For more information: https://laravel.com/docs/5.1/testing#sessions-and-authentication

Unable to retrieve cookies set by Laravel

According to the official docs on cookies:
By default, all cookies generated by Laravel are encrypted and signed so that they can't be modified or read by the client. If you would like to disable encryption for a subset of cookies generated by your application, you may use the $except property of the App\Http\Middleware\EncryptCookies middleware, which is located in the app/Http/Middleware directory
In my controller that sends a response with cookies, I set a cookie with return response("Success", 200)->cookie('api_token', $api_token, 2, '/');, where $api_token is a string generated by Str::random(80). I have a route in web.php that is protected by middleware that checks if the cookie is valid. However, using $request->cookie('api_token'); in the middleware returns nothing, but I have to make an exception in the EncryptCookies for api_token to make this work.
I'm not sure why my cookie isn't being encrypted, even if I use a laravel function to set it. Am I misunderstanding which cookies are "generated" by Laravel?
Set Cookies :
public function setCookie(Request $request){
$minutes = 60;
$response = new Response('Set Cookie');
$response->withCookie(cookie('name', 'MyValue', $minutes));
return $response;
}
Get Cookies :
public function getCookie(Request $request){
$value = $request->cookie('name');
echo $value;
}

JWT laravel: check auth. Cannot check if user is authenticated even i have set the token

I'm trying make a mobile application with vue and i'm using jwt in laravel.
On first login, I can access the auth()->check() then I get false after the app is cancelled. I'm saving the token. I'm saving the token in local storage. How can I get the authenticated user.
controller:
public function JwtAuth(){
if($this->getAuthenticatedUser()){
return $this->JwtUser = $this->getAuthenticatedUser();
}
return [];
}
I want to acheive something like:
if(auth()->user()){
$user = "something";
}else{
$user = '';
}
return $user;
So sometime I will have token and sometime i dont .. how to check?

Tymon\JWTAuth::toUser error: A token is required

I have a Larvel API that uses Tymon\JWTAuth to authenticate the user.
It is working fine.
For some reasons I have also a non-guarded route in web.php:
Route::get('myroute', 'MyController#mymethod');
The code of MyController#mymethod is the following:
$user = JWTAuth::toUser($request->input('token'));
// I tried also this:
// JWTAuth::setToken($request->input('token'));
// $user = JWTAuth::authenticate();
And I call the route using this url in the browser: /myroute?token=eyJ0eXAiOiJKV1QiLCJhbGci....
The problem is that I have an exception in JWT.php:
Tymon \ JWTAuth \ Exceptions \ JWTException
A token is required
JWT.php
protected function requireToken()
{
if (! $this->token) {
throw new JWTException('A token is required');
}
}
How can I decode the token that is passed as URL parameter and not in the header of the request?
If you are using jwt-auth dev, the toUser method in old version will drop the error like above, try this:
// Get the currently authenticated user
$user = auth()->user();
If the user is not then authenticated, then null will be returned.
Instead of
$user = JWTAuth::toUser($request->input('token'));
Use
$user = $this->jwt->User();
I solved it using this code:
use Namshi\JOSE\SimpleJWS;
$secret = config('jwt.secret');
$jws = SimpleJWS::load($token);
if (!$jws->isValid($secret)) {
return response()->json([], 401); // unauthorized
}
$payload = $jws->getPayload();
$account = Account::find($payload["account"]["id"]);
However I would have preferred to use directly JWTAuth

Setting Cookie in Laravel Custom Middleware

I want to set a cookie in a custom Laravel middleware. The idea is to set the cookie value any time a user visits my website through any landing page.
So what I did was I created a middleware named UUIDMiddleware. I am using this middleware along with web middleware in my routes. Below is its code from the middleware.
if($request->hasCookie('uuid'))
{
return $next($request);
}
else
{
$uuid = Uuid::generate();
$response = new Response();
return $response->withCookie(cookie()->forever('uuid', $uuid));
}
As you can see I am checking if cookie exists. If not, I am passing control to next request.
The problem is when setting a cookie using return $response, I cannot pass control to next request. How do I resolve this?
What happens in this case is if a cookie is not set, it sets a cookie and a blank screen shows up. If I refresh, I see the website with a cookie set.
There has to be a way to set cookie using middleware in the right way. How do I do it?
The response object in middleware is returned by the $next closure, so you could do something like this:
if($request->hasCookie('uuid')) {
return $next($request);
}
$uuid = Uuid::generate();
return $next($request)
->withCookie(cookie()->forever('uuid', $uuid));
If you're using Laravel 5.8 and like me you want a solution that allows you set the expiration time of the cookie instead of setting it to forever, you could also do something like this in the middleware:
public function handle($request, Closure $next)
{
$time = time() + 60 * 60 * 24; //One day
$res = $next($request);
return $res->cookie('cookie_name', $cookieValue, $time, "/");
}
This would set the cookie when the controller is done with the request and is returning a response.

Resources