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

rawilk's avatar
Level 47

Revoke single session by id

I'm trying to implement a feature where I list out a user's sessions (I'm using the database session driver), and allow them to revoke a given session if they choose to. When I do that, I delete the session from the database, which forces a logout of that specific session if the remember cookie is not set for it. If the remember cookie is set, the session does not get logged out.

I know I could just use Auth::logoutOtherDevices('current-password'), however I'd like to be able to just revoke a single session as well if needed. I've written a solution that seems to work for what I want, however I'm not sure if there's any implications to what I'm doing in it. Any help/advice on my implementation would be greatly appreciated.

Here is my Livewire component right now for managing the user's sessions:

use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Livewire\Attributes\Computed;
use Livewire\Component;
//...

class SessionManager extends Component implements HasActions, HasForms
{
    use InteractsWithActions;
    use InteractsWithForms;

    #[Computed]
    public function isUsingDatabaseDriver(): bool
    {
        return config('session.driver') === 'database';
    }

    #[Computed]
    public function sessions(): Collection
    {
        if (! $this->isUsingDatabaseDriver) {
            return collect();
        }

       // This is based off Jetstream's implementation
        return collect(
            $this->sessionsDb()
                ->where('user_id', Filament::auth()->id())
                ->orderBy('last_activity', 'desc')
                ->get(),
        )->map(function ($session) {
            return (object) [
                 'id' => Crypt::encryptString($session->id),
                 'agent' => $this->createAgent($session),
                 'ip_address'  => $session->ip_address,  
                 'is_current_device' => $session->id === session()->getId(),
                'last_active' => Date::createFromTimestamp($session->last_activity)->diffForHumans(),
            ];
        });
    }

    public function revokeAction(): Action
    {
        return Action::make('revoke')
           // ...
           ->form([
               TextInput::make('password')
                     ->password()
                      ->required()
                      ->currentPassword(),
           ])
           ->action(function (array $arguments, Form $form) {
                 // I encrypt the session id on the front-end
                 $sessionId = Crypt::decryptString($arguments['session']);

                 $this->deleteSessionById($sessionId, $form->getState()['password']);

                  // ...
            })
    }

    public function deleteSessionById(string $sessionId, string $password): void
    {
        // Here's where I'm not sure if there's anything else I should be doing
        Filament::auth()->user()->forceFill(['password' => $password])
              ->save();
     
        session()->put([
            'password_hash_web' => Filament::auth()->user()->getAuthPassword(),
         ]);

          // Preserve login status of other sessions
          $this->sessionsDb()
              ->where('user_id', Filament::auth()->id())
              ->whereNotIn('id', [session()->getId(), $sessionId])
              ->select(['id', 'payload'])
              ->cursor()
             ->each(function ($session) {
                 $payload = unserialize(base64_decode($session->payload));

                 $payload['password_hash_web'] = Filament::auth()->user()->getAuthPassword();

                 $this->sessionsDB()
                      ->where('id', $session->id)
                      ->update(['payload' => base64_encode(serialize($payload));
             });

             $this->sessionsDb()
                   ->where('user_id', Filament::auth()->id())
                   ->where('id', $sessionId)
                   ->delete();
    }

     // ...

     protected function sessionsDb(): Builder
     {
            return DB::connection(config('session.connection'))
                   ->table(config('session.table', 'sessions'));
     }
}
0 likes
0 replies

Please or to participate in this conversation.