Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

m615's avatar
Level 2

After setting an api token for a user why is $user->tokens() empty?

My Laravel 8 application has an REST Api for other applications to login and logout with. I'm able to log a user in successfully and send back a token to put in the headers for all requests that require an auth token.

The problem I'm having right now is logging the user out. I have a method for logging out that has the following line of code.

I'm trying to use the Sanctum tokens. I do see that the personal_access_tokens table is populated. I'm just not sure why my User tokens array is empty.

$user->tokens()

I've looked at the array that comes back when calling this and it is empty. I'm not sure where my tokens are being stored or how to delete them. In theory I should be able to call $user->tokens()->delete() but like I said, there are not tokens to be found after I look up the user in the DB.

here is my current logout code.

public function logout(Request $request)
    {
        $user = User::where('email', $request->email)->first();
        $bt = $request->bearerToken();

//        return response()->json([
//            'bt' => $user->tokens()
//        ]);

///I'd like to check to see if the bearerToken in header matches before deleting
///not sure if ->where('id') is the right way to find if the tokens match
        if($user) {
            if($user->tokens()->where('id', $bt) == $bt)
            {
                $user->tokens()->where('id', $bt)->delete();
            }
        }
        else
        {
            return response()->json([
                'status_code' => 400,
                'message' => 'We could not locate the proper info in order to logout this user'
            ]);
        }


        $request->user()->currentAccessToken()->delete();
        return response()->json([
            'status_code' => 200,
            'message' => 'Logged out successfully'
        ]);
    }

0 likes
5 replies
rodrigo.pedra's avatar

In this line you are comparing a query builder instance to a string:

if($user->tokens()->where('id', $bt) == $bt)

You can change it to:

if($user->tokens()->where('id', $bt)->exists())
m615's avatar
Level 2

I still get an empty array. I'm wondering if this has anything to do with using Nova and how it's auth system works?

ousid's avatar

Try searching by name


$user->tokens()->where('name', $tokenName)
m615's avatar
Level 2

I changed my method to this for testing to see what I get back in the array and it's still empty after doing the following.

$user = User::where('email', $request->email)->first();
        $bt = $request->bearerToken();

        return response()->json([
            'bt' => $user->tokens()->where('name', 'authToken')
        ]);

My DB table is called personal_access_tokens and looks like this

https://drive.google.com/file/d/11NWeETJC4rplZTnWArnap3q8rAYMj6d_/view?usp=sharing

m615's avatar
Level 2

Still some refactoring to do but this is what I had to do to get logout from a SPA working.

public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if($validator->fails())
        {
            return response()->json(['status_code' => 400, 'message' => 'Bad Request']);
        }

        $credentials = request(['email', 'password']);

        if(!Auth::attempt($credentials))
        {
            return responce()->json([
                'status_code' => 500,
                'message' => 'Unauthorized'
            ]);
        }

        $user = User::where('email', $request->email)->first();
        $tokenResult = $user->createToken('authToken')->plainTextToken;
        $user->save();

        return response()->json([
            'status_code' => 200,
            'token' => $tokenResult
        ]);

    }

    public function logout(Request $request)
    {
        $user = User::where('email', $request->email)->first();
        $bt = $request->bearerToken();

        if(!$bt) return response()->json([
            'status_code' => 400,
            'message' => 'We could not locate the proper info in order to logout this user'
        ]);

        $split_string = explode("|", $bt);
        $token_id = (int)$split_string[0];

        $personal_token_object = DB::table('personal_access_tokens')->where('id', $token_id)->first();


        if($user && $bt && $personal_token_object) {

            if(($personal_token_object->tokenable_id == $user->id) && ($personal_token_object->id == $token_id))
            {
                $personal_token_object = DB::table('personal_access_tokens')->delete($token_id);
            }
        }
        else
        {
            return response()->json([
                'status_code' => 400,
                'message' => 'We could not locate the proper info in order to logout this user'
            ]);
        }

        if($personal_token_object)
        {
            return response()->json([
                'status_code' => 200,
                'message' => 'Logged out successfully'
            ]);
        }
        else
        {
            return response()->json([
                'status_code' => 400,
                'message' => 'We could not locate the proper info in order to logout this user'
            ]);
        }

    }

if there is a better way or you happen to figure you what I'm missing in order to be able to just call delete on the tokens() method on the user object, I'll see if I can refactor and get it working that way.

Please or to participate in this conversation.