phplaraveltestingjwt

How to reset Laravel AuthManager/guards in between API calls in tests?


I'm writing a Feature test for an API and I want to test custom auth logic.

I know that when I call the login API endpoint, Laravel caches the fact that the user is logged in so the next API call in the test would consider the user already authenticated...

So for one test, how do I disable this Laravel magic of auth caching so I can manually provide the Bearer auth token to check if my custom authentication logic works?

I'm thinking something along the lines of clearing the guards in AuthManager, or clearing AuthManager entirely so Laravel would be force to reinitialize it. But I'm having no luck in figuring out how to do that in a way that works.

Here's some pseudo-example code:

public function testLogin()
{
    $responseData = $this->post('/login', ['email' => $this->user->email, 'password' => 'password'])->json();

    $this->get('/endpoint-requiring-auth')->assertOk();

    //
    // $this->logicToResetAuth() ?
    //

    $this->get('/endpoint-requiring-auth')->assertUnauthorized();
    
    // I want to manually have to pass the token to get it to work now.
    $this->get('/endpoint-requiring-auth', ['Authorization' => "Bearer $responseData[access_token]"])
        ->assertOk();
}

Also the unknown reset logic should affect multiple guards.

Oh yeah, I'm writing custom logic around the JWT-Auth library.


Solution

  • For Laravel 8.x (and maybe newer)

    auth()->forgetGuards();
    

    But for JWT you may need to additionally do:

    app('tymon.jwt')->unsetToken();
    

    Or

    app()->instance('tymon.jwt', null);
    

    For Laravel 7.x (and maybe older)

    As ->forgetGuards() is not invented yet in this version, and guards-array is protected, do something like:

    /** @var \Illuminate\Auth\AuthManager $auth */
    $auth = app('auth');
    $mirror = new \ReflectionObject( $auth );
    $prop = $mirror->getProperty( 'guards' );
    $prop->setAccessible(true);
    $prop->setValue($auth, []);
    $prop->setAccessible(false); // Back to protected.
    

    But for JWT, do same as above Laravel 8 section.