In many applications, it’s important to restrict users to be logged in from only one device or browser session at a time. If a user logs in from a new device, the previous session(s) should be automatically invalidated (logged out).
This improves security by preventing multiple active sessions and helps prevent unauthorized use.
In this blog, I’ll walk you through how to implement this single device login feature in Laravel, leveraging Laravel’s database session driver and some custom logic.
Why Single Device Login?
- Improves account security by preventing simultaneous logins from different devices.
- Ensures users don’t forget to log out on shared or public devices.
- Useful for banking, healthcare, and other sensitive applications.
Step 1: Use Database Sessions
First, configure Laravel to store sessions in the database.
In your .env
file:
SESSION_DRIVER=database
Then, generate the sessions table migration and migrate:
php artisan session:table
php artisan migrate
This creates the sessions
table:
CREATE TABLE sessions (
id VARCHAR(255) NOT NULL PRIMARY KEY,
user_id BIGINT UNSIGNED NULL,
ip_address VARCHAR(45) NULL,
user_agent TEXT NULL,
payload LONGTEXT NOT NULL,
last_activity INT(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Step 2: Add session_id
Column to Users Table
We will track which session belongs to a user by storing the current session ID on the users table.
Create a migration to add session_id
:
ALTER TABLE users
ADD COLUMN session_id VARCHAR(255) NULL AFTER remember_token;
Run this migration to update the database.
Step 3: Update Login Logic to Limit Sessions
In your LoginController
, modify the login flow to:
- Regenerate the session ID upon login.
- Check if the user already has a previous session.
- Delete the previous session to force logout on other devices.
- Save the new session ID in the users table.
Here’s a sample implementation:
public function login(Request $request)
{
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
return $this->sendFailedLoginResponse($request);
}
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->limitOneSessionPerUser();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
private function limitOneSessionPerUser()
{
$user = Auth::user();
$previous_session = $user->session_id;
if ($previous_session) {
// Delete the previous session record from sessions table
Session::getHandler()->destroy($previous_session);
}
// Save the new session id to the user record
$user->session_id = Session::getId();
$user->save();
}
How This Works
- When the user logs in, Laravel regenerates the session ID for security.
- The method
limitOneSessionPerPatientUser()
checks if the user has a previous session ID. - If yes, it deletes that session from the
sessions
table — effectively logging the user out from the old device/browser. - Then it updates the user’s record with the new session ID.
This ensures that only the latest login session remains active.
Summary
- Configure Laravel to use database sessions.
- Create the
sessions
table and add asession_id
column tousers
. - In your login logic, destroy the previous session to enforce one active session per user.
- Store the current session ID in the user’s record.
Benefits
- Users cannot stay logged in on multiple devices.
- Automatically logs out previous sessions.
- Better security for sensitive apps.
Final Notes
- Make sure your session driver is correctly set to
database
in.env
. - Clear caches if you change
.env
settings:
php artisan config:clear
php artisan cache:clear