{"id":3098,"date":"2025-05-15T11:46:41","date_gmt":"2025-05-15T11:46:41","guid":{"rendered":"https:\/\/www.devopssupport.in\/blog\/?p=3098"},"modified":"2025-05-15T11:46:43","modified_gmt":"2025-05-15T11:46:43","slug":"how-to-allow-login-on-only-one-device-at-a-time-in-laravel-logout-other-sessions","status":"publish","type":"post","link":"https:\/\/www.devopssupport.in\/blog\/how-to-allow-login-on-only-one-device-at-a-time-in-laravel-logout-other-sessions\/","title":{"rendered":"How to Allow Login on Only One Device at a Time in Laravel (Logout Other Sessions)"},"content":{"rendered":"\n<p>In many applications, it&#8217;s important to restrict users to be logged in from <strong>only one device or browser session at a time<\/strong>. If a user logs in from a new device, the previous session(s) should be automatically invalidated (logged out).<\/p>\n\n\n\n<p>This improves security by preventing multiple active sessions and helps prevent unauthorized use.<\/p>\n\n\n\n<p>In this blog, I\u2019ll walk you through how to implement this <strong>single device login<\/strong> feature in Laravel, leveraging Laravel\u2019s <strong>database session driver<\/strong> and some custom logic.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Why Single Device Login?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Improves account security by preventing simultaneous logins from different devices.<\/li>\n\n\n\n<li>Ensures users don&#8217;t forget to log out on shared or public devices.<\/li>\n\n\n\n<li>Useful for banking, healthcare, and other sensitive applications.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Use Database Sessions<\/h2>\n\n\n\n<p>First, configure Laravel to store sessions in the database.<\/p>\n\n\n\n<p>In your <code>.env<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SESSION_DRIVER=database\n<\/code><\/pre>\n\n\n\n<p>Then, generate the sessions table migration and migrate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php artisan session:table\nphp artisan migrate\n<\/code><\/pre>\n\n\n\n<p>This creates the <code>sessions<\/code> table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE sessions (\n    id VARCHAR(255) NOT NULL PRIMARY KEY,\n    user_id BIGINT UNSIGNED NULL,\n    ip_address VARCHAR(45) NULL,\n    user_agent TEXT NULL,\n    payload LONGTEXT NOT NULL,\n    last_activity INT(11) NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Add <code>session_id<\/code> Column to Users Table<\/h2>\n\n\n\n<p>We will track which session belongs to a user by storing the current session ID on the users table.<\/p>\n\n\n\n<p>Create a migration to add <code>session_id<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ALTER TABLE users\nADD COLUMN session_id VARCHAR(255) NULL AFTER remember_token;\n<\/code><\/pre>\n\n\n\n<p>Run this migration to update the database.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Update Login Logic to Limit Sessions<\/h2>\n\n\n\n<p>In your <code>LoginController<\/code>, modify the login flow to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Regenerate the session ID upon login.<\/li>\n\n\n\n<li>Check if the user already has a previous session.<\/li>\n\n\n\n<li>Delete the previous session to force logout on other devices.<\/li>\n\n\n\n<li>Save the new session ID in the users table.<\/li>\n<\/ul>\n\n\n\n<p>Here\u2019s a sample implementation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function login(Request $request)\n{\n    if ($this->attemptLogin($request)) {\n        return $this->sendLoginResponse($request);\n    }\n    return $this->sendFailedLoginResponse($request);\n}\n\nprotected function sendLoginResponse(Request $request)\n{\n    $request->session()->regenerate();\n\n    $this->limitOneSessionPerUser();\n\n    $this->clearLoginAttempts($request);\n\n    return $this->authenticated($request, $this->guard()->user())\n            ?: redirect()->intended($this->redirectPath());\n}\n\nprivate function limitOneSessionPerUser()\n{\n    $user = Auth::user();\n    $previous_session = $user->session_id;\n\n    if ($previous_session) {\n        \/\/ Delete the previous session record from sessions table\n        Session::getHandler()->destroy($previous_session);\n    }\n\n    \/\/ Save the new session id to the user record\n    $user->session_id = Session::getId();\n    $user->save();\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">How This Works<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When the user logs in, Laravel regenerates the session ID for security.<\/li>\n\n\n\n<li>The method <code>limitOneSessionPerPatientUser()<\/code> checks if the user has a previous session ID.<\/li>\n\n\n\n<li>If yes, it deletes that session from the <code>sessions<\/code> table \u2014 effectively logging the user out from the old device\/browser.<\/li>\n\n\n\n<li>Then it updates the user&#8217;s record with the new session ID.<\/li>\n<\/ul>\n\n\n\n<p>This ensures that <strong>only the latest login session remains active<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Configure Laravel to use database sessions.<\/li>\n\n\n\n<li>Create the <code>sessions<\/code> table and add a <code>session_id<\/code> column to <code>users<\/code>.<\/li>\n\n\n\n<li>In your login logic, destroy the previous session to enforce one active session per user.<\/li>\n\n\n\n<li>Store the current session ID in the user\u2019s record.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Benefits<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Users cannot stay logged in on multiple devices.<\/li>\n\n\n\n<li>Automatically logs out previous sessions.<\/li>\n\n\n\n<li>Better security for sensitive apps.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Final Notes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Make sure your session driver is correctly set to <code>database<\/code> in <code>.env<\/code>.<\/li>\n\n\n\n<li>Clear caches if you change <code>.env<\/code> settings:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>php artisan config:clear\nphp artisan cache:clear\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In many applications, it&#8217;s important to restrict users to be logged in from only one device or browser session at a time. If a user logs in&#8230; <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[2599,2601,42,566,174,2603,2606,35,175,743,2605,2604,1514,2600,2602],"class_list":["post-3098","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-authentication-security","tag-database-sessions","tag-laravel","tag-laravel-migration","tag-laravel-sessions","tag-logout-other-devices","tag-one-device-login","tag-php","tag-session-handling","tag-session-management","tag-session-table","tag-single-device-login","tag-user-authentication","tag-user-sessions","tag-web-security"],"_links":{"self":[{"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/posts\/3098","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/comments?post=3098"}],"version-history":[{"count":1,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/posts\/3098\/revisions"}],"predecessor-version":[{"id":3099,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/posts\/3098\/revisions\/3099"}],"wp:attachment":[{"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/media?parent=3098"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/categories?post=3098"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopssupport.in\/blog\/wp-json\/wp\/v2\/tags?post=3098"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}