Revoking the token is working. It is the test that is not working, but it is not obvious why.
When making multiple requests in one test, the state of your laravel application is not reset between the requests. The Auth manager is a singleton in the laravel container, and it keeps a local cache of the resolved auth guards. The resolved auth guards keep a local cache of the authed user.
So, your first request to your api/logout
endpoint resolves the auth manager, which resolves the api guard, which stores a references to the authed user whose token you will be revoking.
Now, when you make your second request to /api/user
, the already resolved auth manager is pulled from the container, the already resolved api guard is pulled from it's local cache, and the same already resolved user is pulled from the guard's local cache. This is why the second request passes authentication instead of failing it.
When testing auth related stuff with multiple requests in the same test, you need to reset the resolved instances between tests. Also, you can't just unset the resolved auth manager instance, because when it is resolved again, it won't have the extended passport
driver defined.
So, the easiest way I've found is to use reflection to unset the protected guards
property on the resolved auth manager. You also need to call the logout
method on the resolved session guards.
I have a method on my TestCase class that looks something like:
protected function resetAuth(array $guards = null)
{
$guards = $guards ?: array_keys(config('auth.guards'));
foreach ($guards as $guard) {
$guard = $this->app['auth']->guard($guard);
if ($guard instanceof IlluminateAuthSessionGuard) {
$guard->logout();
}
}
$protectedProperty = new ReflectionProperty($this->app['auth'], 'guards');
$protectedProperty->setAccessible(true);
$protectedProperty->setValue($this->app['auth'], []);
}
Now, your test would look something like:
public function test_logout()
{
$response = $this->json('POST', '/api/logout', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(200);
// Directly assert the api user's token was revoked.
$this->assertTrue($this->app['auth']->guard('api')->user()->token()->revoked);
$this->resetAuth();
// Assert using the revoked token for the next request won't work.
$response = $this->json('GET', '/api/user', [], [
'Authorization' => $data->token_type . ' ' . $data->access_token
]);
$response->assertStatus(401);
}