Laravel Sanctum | Delete current user token not working

Viewed 6694

i really need help with one little thing I try to do. I try to use concurrent personal_access_tokens in my laravel / Vue setup for one user. Everything is working fine, all but one thing where I want to delete one token by it's id when the user is logging out. With the login of one user, I create a personal_access_token for them. With the logout this specific access_token should be deleted.

Right now in my logout method, I delete all tokens. That works fine, but when deleting one specific token (which should work) I always get errors that this method doesn't exist:

public function logout(Request $request){
    
   Auth::guard('web')->logout();
    
   // First try: auth()->user()->currentAccessToken()->delete();
   // Second try: $request->user()->token()->revoke();
   auth()->user()->tokens()->delete();
}

The error:

LOG.error: Call to undefined method Laravel\Sanctum\TransientToken::delete() {"userId":18,"exception":{}}

api.php

Route::group(['middleware' => 'auth:sanctum'], function () {
    Route::post('/logout', [AuthController::class, 'logout']);
});

I tried following things from:

https://laracasts.com/discuss/channels/laravel/passport-how-can-i-manually-revoke-access-token (passport) https://laracasts.com/discuss/channels/laravel/deleting-users-passport-token-on-logout https://divinglaravel.com/authentication-and-laravel-airlock https://laracasts.com/discuss/channels/laravel/spa-and-mobile-logout?page=1&replyId=698040

In all those threads the used methods should work but not for me. Do I overlook something?

I appreciate every help!

5 Answers

I have the same problem, calling auth()->user()->currentAccessToken()->delete() gives the error Call to undefined method Laravel\\Sanctum\\TransientToken::delete().

I figured out that this is because of how the Sanctum authentication guard works. When a Laravel session is already in place, via a session cookie, the guard puts a TransientToken on the user, which is then returned via currentAccessToken(). However this TransientToken is not the real PersonalAccessToken and doesn't have the delete() method.

Found this out in the source code here.

My way around is to put the logout route not in the web group but instead in the api group, which doesn't include the middleware for the sessions.

For a specific user:

Auth::user()->tokens()->where('id', $id)->delete();

For requested user who want to logout

$user = request()->user();
$user->tokens()->where('id', $user->currentAccessToken()->id)->delete();

I faced the same problem, It seems like Laravel Sanctum uses TransientToken as default Token class instead of PersonalAccessToken if the user is logged in via session/cookie. And the TransientToken only has can/cant methods, so it doesn't support delete() or ->id property.

so what I did is checking if currentAccessToken object has delete method, if so I use it, if not then I go further and delete the session.

if(method_exists(auth()->user()->currentAccessToken(), 'delete')) {
    auth()->user()->currentAccessToken()->delete();
}

auth()->guard('web')->logout();

If you use a bearer token for the logout this code will help. Sanctum Bearer token starts with token ID from the personal_access_tokens table

$tokenId = Str::before(request()->bearerToken(), '|');
auth()->user()->tokens()->where('id', $tokenId )->delete();
Related