I'm trying to invalidate (or remove) a token from JWT but I can't achieve that. First I did something like this answer says Logout issue with Laravel JWT-auth authentication:
JWTAuth::invalidate(JWTAuth::getToken())):
But I get this error:
Non-static method Tymon\JWTAuth\JWT::invalidate() should not be called statically, assuming $this from incompatible context
Then I did something like this:
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWTAuth;
class AuthController extends Controller
{
protected $jwt;
public function __construct(JWTAuth $jwt)
{
$this->jwt = $jwt;
}
public function invalidateToken(Request $request)
{
$this->jwt->parseToken()->invalidate();
return response()->json(array('message' => 'log out'));
}
...
}
But I can still use the token for another request and I can't remove or invalidate it.
What am I doing wrong to invalidate the token?
Edit:
I read another questions from here and issues post from the repo of JWT on github (this is the library I'm using) and I followed all the examples to invalidate or remove the token and I can't still remove or invalidate it .
The blacklist feature works if cache_driver in your .env file is set to something other than array.
Changing it to file worked for me. However, in my particular case, I was using Entrust too, which causes issues when cache_driver is set to file or database. So, had to drop the blacklist/invalidate functionality.
Hope this helps someone.
This is how i think it should look like: $this->jwt->setToken($old_token)->invalidate(true);
JWTAuth::invalidate(old token);
Related
I'm trying to invalidate (or remove) a token from JWT but I can't achieve that. First I did something like this answer says Logout issue with Laravel JWT-auth authentication:
JWTAuth::invalidate(JWTAuth::getToken())):
But I get this error:
Non-static method Tymon\JWTAuth\JWT::invalidate() should not be called statically, assuming $this from incompatible context
Then I did something like this:
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWTAuth;
class AuthController extends Controller
{
protected $jwt;
public function __construct(JWTAuth $jwt)
{
$this->jwt = $jwt;
}
public function invalidateToken(Request $request)
{
$this->jwt->parseToken()->invalidate();
return response()->json(array('message' => 'log out'));
}
...
}
But I can still use the token for another request and I can't remove or invalidate it.
What am I doing wrong to invalidate the token?
Edit:
I read another questions from here and issues post from the repo of JWT on github (this is the library I'm using) and I followed all the examples to invalidate or remove the token and I can't still remove or invalidate it .
The blacklist feature works if cache_driver in your .env file is set to something other than array.
Changing it to file worked for me. However, in my particular case, I was using Entrust too, which causes issues when cache_driver is set to file or database. So, had to drop the blacklist/invalidate functionality.
Hope this helps someone.
This is how i think it should look like: $this->jwt->setToken($old_token)->invalidate(true);
JWTAuth::invalidate(old token);
In my controller constructor I have middleware auth. How do I assert that somebody is not authenticated in tests? Right now I'm getting Illuminate\Auth\AuthenticationException and the only way to make test positive is to add
$this->expectException('Illuminate\Auth\AuthenticationException')
in the beginning. I saw solutions like using withoutExceptionHandling() in the beginning of test or using assertUnauthorized() but that doesn't change anything.
Is there a better way?
I'm using Laravel 7.2.2 and PHPUnit 8.5.
$this->get('/routeThatRequiresAuthentication');
$this->assertGuest();
/** #test */
public function unauthenticated_user_cannot_access_protected_routes()
{
$this->withoutExceptionHandling();
$this->expectException('Illuminate\Auth\AuthenticationException');
$this->getJson('/api/user'); //This route is protected with auth:api
}
Try $this->deleteJson('replies/' . $reply->id);. It will return json response instead of throwing an exception. You can then call ->assertStatus(401); on it
In Laravel, you can use the auth() helper method to get the currently authenticated user as below. If no authenticated user is found, it will return null. And this is what you can assert to check for unauthenticated.
$this->assertNull(auth()->user());
I believe this will also work:
$this->assertFalse(auth()->check());
I am building a REST user-microservice using Laravel 5.5 + Passport.
I am using the standard Passport::routes(), but I have had to modify the Auth::routes in order to make them return JSON responses, and to make them work with Passport.
I have added the following lines to my routes/web.php file:
Route::group(['middleware' => 'auth:api'], function () {
$this->post('logout', 'Auth\LoginController#logout')->name('logout');
});
This allows me to POST https://myapi/logout
If I make the call with the header "Authorization => Bearer TOKEN", I get a successful logout response.
If I provide no header at all, I get a "not authenticated" message (which is good)
However, if I provide the header with a revoked token, I get a recursive deadloop of the function: Illuminate\Auth\RequestGuard->user() (it keeps calling itself recursively until stack-overflow)
This is all done in the auth:api middleware, my logout code is not reached, but my LoginController constructor is called. Constructor code:
public function __construct(Application $app)
{
$this->apiConsumer = $app->make('apiconsumer');
$this->middleware('guest')
->except('logout');
}
I'm struggling to understand if it's my code causing this issue, or some combination of Laravel + passport + auth.
My first thought was that the auth:api middleware fails to authenticate the user, and as a result redirects the user to /home, where for some reason it's triggered again, recursively. But if that was the case, why would it work correctly with no header?
My current thinking is that the token in question does exist in the database, but Laravel is failing to figure out that it's revoked.
Any suggestions appreciated,
I found an answer (if not the answer) after a lot of research. It appears this is a Laravel bug (https://github.com/laravel/passport/issues/440). The solution is to add OAuthServerException to the $dontReport array in app/Exceptions/Handler.php:
class Handler extends ExceptionHandler
{
protected $dontReport = [
...
\League\OAuth2\Server\Exception\OAuthServerException::class,
];
}
This will avoid trying to log user information, thereby avoid the deadloop.
I have faced this in localhost. in my case, I have used xampp server and facing this issue
after creating a virtual host like "testlarave.test" then solve the error
I want to be able to retrieve the token from the http_request_body as for annoying reasons where I need to send the data from, the token is too long to send as part of the query string, and they don't accept sending headers.
Anyway, I've managed to edit the jwt.auth GetUserFromToken middleware to the following:
if (! $token = $this->auth->setRequest($request)->getToken()) {
if(! $token = $request->get('token') ) {
return $this->respond('tymon.jwt.absent', 'token_not_provided', 400);
}
}
This works, but I am wondering if there is a better way that would be more permanent?
Obviously when I deploy or the package is updated this will be over-ridden.
Is there a way to extend to extend or over-ride this class from within my app, rather than directly in the vendor Middleware?
Thanks!
With the help of #Moeen Basra #apokryfos and this How to override vendor class file?
Managed to extend the Middleware so that it overrides the existing Class and won't be impacted when the app is deployed or the package updated.
Added MyGetUserFromToken.php
namespace App\Overrides\Tymon;
use Tymon\JWTAuth\Middleware\GetUserFromToken;
class MyGetUserFromToken extends GetUserFromToken {
And then in the Kernel
//use Tymon\JWTAuth\Middleware\GetUserFromToken;
use App\Overrides\Tymon\MyGetUserFromToken;
...
'jwt.auth' => MyGetUserFromToken::class,
Hopefully this will then help others also.
I am developing web application using Laravel 5 and angularJs with RESTFUL apis.
Using middleware to authentication purpose. My problem is after sending few request simultaneously,system automatically logged out and sending 401 exception from laravel side.
API base controller:
class ApiController extends BaseController {
use DispatchesCommands, ValidatesRequests;
function __construct() {
$this->middleware('api.auth');
}
}
Middleware:
class APIMiddleware {
/**
* Handle an incoming request.
*
* #param Request $request
* #param Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
if (!Auth::check()) {
abort(401, "Unauthorized");
}
return $next($request);
}
}
Log in controller
public function login(LoginRequest $request) {
if (Auth::check()) {
Auth::logout();
}
if (Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')], $request->input('is_remember'))) {
return array(true);
} else {
abort(401, "Invalid email & password");
}
}
After few request gone, Server log out and sends 401 exception. I am stuck with this issue.
Now I'm not 100% sure (and depending on your set-up I can't even say I'm 90% sure) But after changing my session_driver from file to database I seem to have fixed this issue - that is if it's the same issue.
I think do the samething as you with my app - that is on a start up of a page, I'm making 6 request (this is development and I will be changing it to one so please don't cry). If I load this page, it works with about 3 or 4 request, then the other 2-3 come back with a unauthorised response. It also only happens on request that require middleware => auth.
So here's my theory to why this is happening: Because, by default, sessions are saved in a file - making multiple requests at once means that file is being opened 6 times at once - probably messing it up (depending on your machine). Therefore changing the session to a database, which is designed to have thousands of requests at once, works!
SOLUTION:
Go to your .env file and change SESSION_DRIVER=file to SESSION_DRIVER=database.
Next you will need to create a session migration: php artisan session:table.
Now composer dump-autoload for good practice.
Finally migrate (php artisan migrate).
NOTE: I'm not 100% sure though if this is the case, but for me this solution worked. I am also aware that this question is really old, but both the developers I work with and myself have had this issue and there doesn't seem to be a solution, so Just though I'd post this.
Managed to figure it out.. Since i use laravel for pretty much all my projects, I forgot to change the session name, as a result, one session was overwriting the other, causing the auto-loggout.. So if you have multiple laravel projects running, make sure they all have different session names. Hope this helps someone in future !
Here is a Laracast thread on this issue.
For me this was the process to solve the problem:
Cleared my browser's cookies for localhost.
Changed value of cookie key in app/session.php.
Ran php artisan config:clear.
It may be a problem that you are accessing the user variable illegally. Please use Auth::check() before accessing Auth::user() This seems to work for my project. Optionally you can try for changing the session driver from .env file.
Might be useful for someone: Had the very same problem. I've changed the cookie name in session settings. By default it is laravel_session, so try setting it to something else
I solved the same issue by clearing cache using php artisan cache:clear and also running composer dump-autoload. Hope this works for you.
I had a similar problem this week. I have a server with multiple Laravel applications. One application was logging the other out.
The problem had to do with session management. The session name was the same for all the applications. Changing it would be enough to avoid different applications conflict. However, I can have different instances of the same application in the server (for testing purposes, for example). So, changing only the session name would not be enough.
To solve my problem properly, I used the session path to make the configuration unique per instance. In the config/session.php, I defined something like this:
'cookie' => 'systemx_session',
'path' => parse_url(env('APP_URL', 'http://localhost'), PHP_URL_PATH),
I use the parse_url function with the environment variable APP_URL because my server has the instances deployed under something like http://example.com/systemx.
I hope this helps someone who might end up having the same kind of problem.
I think you copied an old project for a new application, so you need to change the config/session.php
'cookie' => 'new_session',
I had a similar problem that the users didn't login at all & I found Its because of my authenticatable eloquent model, specified in my auth guard in config/auth.php (User in my case).
I was applying a global scope (in my case verified) so that users were filtered by a specific column & auth guard couldn't find the user so it logged out everytime ...
I solved my problem by this post https://laracasts.com/discuss/channels/laravel/ignore-global-scopes-for-auth