Passport: No way to logout Token Guard?

Created on 24 Jul 2017  路  6Comments  路  Source: laravel/passport

Hi, I'm writing some tests for my API that uses Laravel Passport and I have a problem with not having ability to log out the Guard. If I try to run Auth::logout() on my logout api endpoint it will throw an error: Call to undefined method Illuminate\Auth\RequestGuard::logout(). I use instead Auth::user()->token()->revoke(); to log out user in my code. However when I write test, Guard::check() still returns true and original user and ->dontSeeIsAuthenticated('api') fails. Is there a way to perform full logout immediately so Guard will return false on Guard::check() on next code line?

Most helpful comment

This isn't possible. There's a difference between a stateful guard (like web) and a stateless guard (like api). Stateless guards are for short lived sessions which don't persist into other requests (like api tokens for api calls). These don't offer logout functionality because the session will expire immediately after the call. That's why you don't have a logout method.

If you need to revoke the token during your call you can't call any auth functionality after revoking it. This seems purely a way of where some logic is implemented wrong.

For this particularly use case I'd say that checking auth state with Auth::check() isn't useful. It might be better to simply check if the token was revoked.

Also: revoking token doesn't necessarily mean that the current session was made invalid. It just means that the token was revoked for the next session.

Please feel free to provide feedback if you think I'm wrong somewhere with my above statements.

All 6 comments

Today I faced the same problem.

+1

@vedmant I found the workaround. I override the RequestGuard and add the method for unset/logout user:

class CustomRequestGuard extends Illuminate\Auth\RequestGuard
{
    public function unsetUser()
    {
        $this->user = null;
    }
}

Also override PassportServiceProvider as well and implement method makeGuard where you will create instance of your CustomRequestGuard.

    protected function makeGuard(array $config)
    {
        return new CustomRequestGuard(function ($request) use ($config) {
            return (new TokenGuard(
                $this->app->make(ResourceServer::class),
                Auth::createUserProvider($config['provider']),
                $this->app->make(TokenRepository::class),
                $this->app->make(ClientRepository::class),
                $this->app->make('encrypter')
            ))->user($request);
        }, $this->app['request']);
    }

After that you are able to call auth()->unsetUser(); anywhere for logging out.

@akalongman Yeah, this will work, but it's too much hassle just to test one logout feature.

+1

This isn't possible. There's a difference between a stateful guard (like web) and a stateless guard (like api). Stateless guards are for short lived sessions which don't persist into other requests (like api tokens for api calls). These don't offer logout functionality because the session will expire immediately after the call. That's why you don't have a logout method.

If you need to revoke the token during your call you can't call any auth functionality after revoking it. This seems purely a way of where some logic is implemented wrong.

For this particularly use case I'd say that checking auth state with Auth::check() isn't useful. It might be better to simply check if the token was revoked.

Also: revoking token doesn't necessarily mean that the current session was made invalid. It just means that the token was revoked for the next session.

Please feel free to provide feedback if you think I'm wrong somewhere with my above statements.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SwiTool picture SwiTool  路  3Comments

Adesubomi picture Adesubomi  路  4Comments

gbgelado picture gbgelado  路  3Comments

brryfrmnn picture brryfrmnn  路  3Comments

ghost picture ghost  路  3Comments