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

stesvis's avatar

Error with logoutOtherDevices

I have never done this before and I am not super experienced with Laravel APIs, but I was trying to use Auth::logoutOtherDevices($request->password); after a successful login.

I am not sure if it matters to enable \Illuminate\Session\Middleware\AuthenticateSession::class, in the 'web` middlewareGroups as I am only using this for APIs.

However, when I call Auth::logoutOtherDevices($request->password); I get this exception:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'portal_access_token' in 'field list' (SQL: update users set password = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, portal_access_token = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, users.updated_at = 2022-08-16 17:39:22 where id = 8)

I am not sure why it's looking for a column named portal_access_token in the users table.

That only identifies a custom field that I return in my UserResource object:

class UserResource extends ResourceBase
{

    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    public function toArray($request): array
    {
        $includes = Helpers::getIncludesFromRequest($request);

        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'createdAt' => $this->created_at,
            $this->mergeWhen($includes->contains('tokens'), [
                'portal_access_token' => $this->portal_access_token,
            ]),
            'roles' => new RoleResourceCollection($this->roles),
            'ts' => new TSUserResource($this),
            'ld' => new LDUserResource($this),
            'meta' => new MetaDataResourceCollection($this->metaData),
            'logo' => new FileResource($this->logo()),
        ];
    }
}

Does anybody know why it throws this error and how to make it work? Let me know if i need to post mode code details, thanks!

0 likes
2 replies
Sinnbeck's avatar

Show the complete method where you call it please

stesvis's avatar

It's a quite long login method, it checks for 2FA plus other things:

    private function executeLogin(LogInRequest $request)
    {
        if (Auth::attempt(['email' => $request->username, 'password' => $request->password])) {
            $twoFactorEnabled = filter_var(Auth::user()->getMetaData(MetaKeyEnum::TwoFactorEnabled), FILTER_VALIDATE_BOOL);

            if ($twoFactorEnabled) {
                $userTwoFACodes = $this->twoFactorCodesRepository->findByUserId(Auth::id());

                $isAllowed = $userTwoFACodes?->where('client_ip', $this->request->ip())
                        ->where('status', StatusEnum::Completed)
                        ->where('created_at', '>=', now()->subDays(env('2FA_CLIENT_DURATION_IN_DAYS')))
                        ->count() > 0;

                if (!$isAllowed && !$request->authKey) {
                    $twoFactorCode = $this->twoFactorCodesRepository->generateNewCode(Auth::user(), $this->request->ip());

                    return new JsonResponse(null, Response::HTTP_ACCEPTED);
                }

                if ($request->authKey) {
                    $match = $this->twoFactorCodesRepository->find(Auth::id(), $request->authKey);
                    // check that the code is correct and that it's not expired
                    $success = $match?->updated_at->addMinutes(env('2FA_CODE_DURATION_IN_MINUTES')) >= now();
                    if (!$success) {
                        return parent::badRequestResponse('Invalid code.');
                    }

                    $this->twoFactorCodesRepository->complete($match->id);
                }
                // All good
            }
        }

        if (Auth::user() !== null) {
            // attaches the role only if it does not exist
//            Auth::user()->roles()
//                ->syncWithoutDetaching(Role::where('name', RolesEnum::User)->first());

            $token = Auth::user()->createToken('API token');

            $userData = Auth::user();
            $userData['portal_access_token'] = $token->plainTextToken ?? null;

            UserActivityEvent::dispatch([
                'user_id' => Auth::id(),
                'key' => UserLogKeysEnum::LogIn,
            ]);

            Auth::logoutOtherDevices($request->password);

            return new UserResource($userData);
        }

        return parent::badRequestResponse('Invalid credentials.');
    }

For some reason this line throws it off: $userData['portal_access_token'] = $token->plainTextToken ?? null;

UPDATE: if I move that line below a few lines it does not throw the exception:

// ...
            Auth::logoutOtherDevices($request->password);
            $userData['portal_access_token'] = $token->plainTextToken ?? null;

            return new UserResource($userData);

However, I can log in from one device, then log in from another device, and the first device still has a valid token while I expected a 401 status.

Please or to participate in this conversation.