codecasts/laravel-jwt

302 Redirect on Expired Token?

robmpreston opened this issue · 11 comments

Am I missing something?

Using this with Laravel 5.5, testing expired tokens.

Set the timeout to 1 minute.

Works before it times out, then after 1 minute when I make the call, rather than returning a 401 "Expired Token" it does a 302 redirect to /auth/login

Am I crazy or is something not working right there?

@robmpreston that's on your app middleware doing that.

this package authenticates, when you are trying to access something you should not, the Auth middleware redirects you.

That's something this package does not cover (and also no other does I guess).

I'll create a setup guide about how to handle with that

I must be confused... The only middleware I have on api is auth. I'm pretty sure when I used tymon's jwt-auth that it returned a 401 when the token was expired?

but yeah if you could help that'd be great :)

Check out config/auth.php

There's the default guard there, make sure to change web to API and let me know if the issue remains

I have guard set to api

under guards I have api driver set to jwt

I removed all middleware in app\Http\Kernel.php other than auth

I tried auth and auth:api

Both 302 redirect

@robmpreston my bad, just remembered how it wors. I was on mobile so I could not check.

Here's the deal. the auth middleware checks if you are logged in in all available guards.

as you are not in none of them. it throws the Illuminate\Auth\AuthenticationException

Who sends the 302 is the Exception Handler.

on app/Exceptions/Handler, there's this method:

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        return redirect()->guest('login');
    }

So you can just remove the expects json part and return json always:

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        return response()->json(['error' => 'Unauthenticated.'], 401);
    }

Got it?

On a quick not, this happens because Laravel only treats the request as API requests when the header Accept: application/json is present.

There are some tricks to auto inject this header on each request, but if you are doing a API only project, you won't need it.

Laravel needs to improve the API vs WEB mode, since you need to tweak the ExceptionHandler a bit to avoid redirections and html error pages.

I can help you set that up, but it's not really simple.

I may create a package with that in mind or try to contribute on the official code.

anyway, just me let me know if you need help

unauthenticated seems to be gone in Laravel 5.5 so I just added it to the render function

It's just hidden.

The Exception class extends the framework class.

that's what it looks in 5.5

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        return $request->expectsJson()
                    ? response()->json(['message' => 'Unauthenticated.'], 401)
                    : redirect()->guest(route('login'));
    }

see the redirect there, you can just create the method, it will override the parent class one.

Thanks, all seems good now - got my full refresh flow working with axios.

Thanks. Please share the word about this package if you found it useful :) thanks