- Sanctum Version:^2.9
- Laravel Version: ^8.12
- PHP Version:7.3.9
- Database Driver & Version: Mysql
Description:
I am writing a use case to logout a user, so on Logout request, I delete the user tokens so that token issued previously becomes invalid for further requests, but on the second request, the user is still logged in.
I have searched online, many other instances of such issues exist with no solution
https://laracasts.com/discuss/channels/testing/tdd-with-sanctum-issue-with-user-logout-case
Steps To Reproduce:
- Create Laravel app with Sanctum.
- Create Two Endpoint : Login and Logout (Protect Logout with auth:sanctum)
- Create test Case: send a request to login.
- Send two request to logout route.
observed behaviour: Both requests will succeed
Expected Behavior: only the first request should succeed, the second request should fail.
My code:
// route/api.php
Route::post('/login',[AuthenticateController::class,"login"])->name("login");
Route::post('/logout',[AuthenticateController::class,"destroy"])->middleware("auth:sanctum")->name("logout");
// login method
public function login(Request $request): array
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
// 'device_name' => 'required',
]);
/** @var User $user */
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
return ["token" => $user->createToken($request->email)->plainTextToken];
}
//logout
public function destroy(Request $request)
{
// Revoke the token that was used to authenticate the current request...
/** @var User $user */
$user = $request->user();
/** @var \Laravel\Sanctum\PersonalAccessToken $accessToken */
$accessToken = $user->currentAccessToken();
$accessToken->delete();
return response( null,204);
}
public function test_logout()
{
/** @var User $user */
$user = User::factory()->create();
$response = $this->post(route("login"),
["email"=>$user->email,"password"=>"password"]
);
$response->assertStatus(200)->assertJson([
'token' => true,
]);
$token = $response->json("token");
$this->withHeader("Authorization","Bearer $token");
$testResponse = $this->post(route("logout"));
$testResponse->assertNoContent();
$testResponse = $this->post(route("logout"));
$testResponse->assertNoContent(); //this is supposed to fail.
}