├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── auth-timeout.php └── src ├── AuthTimeout.php ├── AuthTimeoutServiceProvider.php ├── Contracts └── AuthTimeout.php ├── Events └── AuthTimedOut.php ├── Facades └── AuthTimeout.php ├── Listeners └── InitializeAuthTimeout.php └── Middlewares └── CheckAuthTimeout.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## v4.2.(2024-03-02) 9 | 10 | ### Added 11 | 12 | - Support for Laravel 12.x. 13 | 14 | ## v4.1.0 (2024-04-02) 15 | 16 | ### Added 17 | 18 | - Support for Laravel 11.x. 19 | 20 | ## v4.0.1 (2023-05-11) 21 | 22 | ### Fixed 23 | 24 | - Should properly initialize auth timeout session. 25 | 26 | ## v4.0.0 (2023-02-16) 27 | 28 | Laravel Auth Timeout has received a complete refresh. Please make sure to read through all the changes. 29 | 30 | ### Added 31 | 32 | - Support for Laravel 10.x. 33 | - Added `event` in config. 34 | 35 | ### Changed 36 | 37 | - Deprecated `JulioMotol\AuthTimeout\Contracts\AuthTimeout`'s `reset()` method and will be remove on a future release. Use `hit()` instead. 38 | - The same change applies to `JulioMotol\AuthTimeout\Facade\AuthTimeout` and `JulioMotol\AuthTimeout\Facade\AuthTimeout` 39 | - Renamed ~~`JulioMotol\AuthTimeout\Events\AuthTimeoutEvent`~~ to `JulioMotol\AuthTimeout\Events\AuthTimedOut`. 40 | - Renamed ~~`JulioMotol\AuthTimeout\Middleware\AuthTimeoutMiddleware`~~ to `JulioMotol\AuthTimeout\Middlewares\CheckAuthTimeout`. 41 | - Auth Timeout initialization has been moved by listening to the `Illuminate\Auth\Events\Login`. 42 | - This was previously initialized within the `JulioMotol\AuthTimeout\Middleware\AuthTimeoutMiddleware` 43 | 44 | ## v3.1.1 (2022-06-03) 45 | 46 | ### Fixed 47 | 48 | - Fix compatibility with v2 session timeout storing. [#24](https://github.com/juliomotol/laravel-auth-timeout/issues/24) 49 | 50 | ## v3.1.0 (2022-04-18) 51 | 52 | ### Added 53 | 54 | - Add `AuthTimeoutMiddleware::setRedirectTo()` method. 55 | - Support for Laravel 9.x 56 | 57 | ### Changed 58 | 59 | - Update syntax to PHP8.0. 60 | 61 | ### Removed 62 | 63 | - Remove support for PHP7.4 and lower. 64 | 65 | ## v3.0.1 (2021-01-09) 66 | 67 | ### Added 68 | 69 | - Restore PHP 7.3 support. 70 | 71 | ## v3.0.0 (2021-01-08) 72 | 73 | ### Added 74 | 75 | - PHP 8 Support. 76 | 77 | ### Changed 78 | 79 | - AuthTimeout now uses `carbon\carbon` to check and store timeout sessions. 80 | 81 | ### Removed 82 | 83 | - Removed `auth-timeout.redirect` in favor of `AuthTimeoutMiddleware::redirectTo()`. 84 | - If you are using this config key, we highly suggest to use `AuthTimeoutMiddleware::redirectTo()` as it provides much better flexibility. 85 | 86 | ## v2.2.1 (2020-10-12) 87 | 88 | - Fixed `AuthTimeout` facade. 89 | 90 | ## v2.2.0 (2020-10-12) 91 | 92 | - Added `AuthTimeout` facade. 93 | 94 | ## v2.1.0 (2020-09-11) 95 | 96 | - Added support for Laravel 8.x. 97 | 98 | ## v2.0.0 (2020-08-03) 99 | 100 | ### Breaking Changes 101 | 102 | - The `AuthTimeoutMiddleware` class' `redirectTo()` method signature has changed. If you are overriding this method, you should update your method's signature: 103 | 104 | ```php 105 | /** 106 | * Get the path the user should be redirected to when they timed out. 107 | * 108 | * @param \Illuminate\Http\Request $request 109 | * @param mixed $guard 110 | * 111 | * @return string|null 112 | */ 113 | protected function redirectTo($request, $guard = null) 114 | { 115 | // 116 | } 117 | ``` 118 | 119 | ### Features 120 | 121 | - The `AuthTimeoutEvent` class now has a `$guard` property. 122 | 123 | ## v1.0.0 (2020-04-04) First Release! 124 | 125 | Welcome to Laravel Auth Timeout! 126 | 127 | See the [documentation](./README.md) to get started. 128 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Julio Motol 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Auth Timeout 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/juliomotol/laravel-auth-timeout.svg?style=flat-square)](https://packagist.org/packages/juliomotol/laravel-auth-timeout) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/juliomotol/laravel-auth-timeout/run-tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/juliomotol/laravel-auth-timeout/actions?query=workflow%3Arun-tests+branch%3Amaster) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/juliomotol/laravel-auth-timeout/fix-php-code-style-issues.yml?branch=master&label=code%20style&style=flat-square)](https://github.com/juliomotol/laravel-auth-timeout/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amaster) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/juliomotol/laravel-auth-timeout.svg?style=flat-square)](https://packagist.org/packages/juliomotol/laravel-auth-timeout) 7 | 8 | Handle Authentication timeouts in Laravel. 9 | 10 | > When upgrading to v4, please see the [CHANGELOG.md](./CHANGELOG.md). 11 | 12 | > For Laravel 8+ support, see [v3](https://github.com/juliomotol/laravel-auth-timeout/tree/v3). 13 | > 14 | > For Laravel 6+ support, see [v2](https://github.com/juliomotol/laravel-auth-timeout/tree/v2). 15 | 16 | ## Why Laravel Auth Timeout? 17 | 18 | There are times where we want to log out a user when they haven't done any request within a set time. There is a workaround (below): 19 | 20 | ``` 21 | /* Somewhere in config/session.php */ 22 | 'lifetime' => 15, 23 | ``` 24 | 25 | But this affects the entirety of the session. But it doesnt have to be and that is where Laravel Auth Timeout comes in. 26 | 27 | Laravel Auth Timeout is a small middleware package that checks if the user had made any request in a set of time. If they have reached the idle time limit, they are then logged out on their next request. Thanks to Brian Matovu's [article](http://bmatovu.com/laravel-session-timeout-auto-logout/). 28 | 29 | ## Installation 30 | 31 | You can install the package via composer: 32 | 33 | ```sh 34 | composer require juliomotol/laravel-auth-timeout 35 | ``` 36 | 37 | You can publish the config file with: 38 | 39 | ```bash 40 | php artisan vendor:publish --tag="auth-timeout-config" 41 | ``` 42 | 43 | This is the contents of the published config file: 44 | 45 | ```php 46 | 'last_activity_time', 54 | 55 | 56 | /** 57 | * The minutes of idle time before the user is logged out. 58 | */ 59 | 'timeout' => 15, 60 | 61 | /** 62 | * The event that will be dispatched when a user has timed out. 63 | */ 64 | 'event' => JulioMotol\AuthTimeout\Events\AuthTimedOut::class, 65 | 66 | ]; 67 | ``` 68 | 69 | ## Usage 70 | 71 | ### Quick Start 72 | 73 | For a simple usage, register the `CheckAuthTimeout` in your `Kernel.php`. 74 | 75 | ```php 76 | protected $routeMiddleware = [ 77 | ... 78 | 'auth.timeout' => \JulioMotol\AuthTimeout\Middlewares\CheckAuthTimeout::class, 79 | ... 80 | ]; 81 | ``` 82 | 83 | Then use that middleware on a route. 84 | 85 | ```php 86 | Route::get('/admin', [ 87 | 'uses' => 'FooBarController@Foobar', 88 | 'middleware' => ['auth.timeout'] 89 | ]); 90 | ``` 91 | 92 | ### Using Different Guards 93 | 94 | You might have multiple guards and only want to apply `CheckAuthTimeout` to certain ones. We got you covered, `CheckAuthTimeout` accepts a `$guard` parameter. 95 | 96 | ```php 97 | Route::get('/admin', [ 98 | 'uses' => 'FooBarController@Foobar', 99 | 'middleware' => ['auth.timeout:custom-guard'] // Add the guard name as a parameter for the auth.timeout middleware. 100 | ]); 101 | ``` 102 | 103 | > NOTE: This package only works with guards that uses a `session` driver. 104 | 105 | ### AuthTimedOut 106 | 107 | An `AuthTimedOut` will be dispatch every time a user has timed out. You can assign a listener for this event in your `EventServiceProvider`. 108 | 109 | ```php 110 | protected $listen = [ 111 | \JulioMotol\AuthTimeout\Events\AuthTimedOut::class => [ 112 | // ... 113 | ], 114 | ]; 115 | ``` 116 | 117 | `AuthTimedOut` has two properties that you can access in your `EventListener`. 118 | 119 | ```php 120 | class FooEventListener 121 | { 122 | public function handle(AuthTimedOut $event) 123 | { 124 | $event->user; 125 | $event->guard; 126 | } 127 | } 128 | ``` 129 | 130 | ### Redirection 131 | 132 | To modify the redirection when a user has timed out, you can use `CheckAuthTimeout::setRedirectTo()` within your `AppServiceProvider` to set a redirection callback. 133 | 134 | ```php 135 | class AppServiceProvider extends ServiceProvider 136 | { 137 | public function boot() 138 | { 139 | CheckAuthTimeout::setRedirectTo(function ($request, $guard){ 140 | return match($guard){ 141 | 'custom-guard' => route('some.route'), 142 | default => route('auth.login') 143 | }; 144 | }); 145 | } 146 | } 147 | ``` 148 | 149 | ### AuthTimeout Facade 150 | 151 | This package also provides a facade with the following methods: 152 | 153 | ```php 154 | AuthTimeout::init() // Initialize the timeout session when no has been set yet. 155 | 156 | AuthTimeout::check($guard) // Check if a user has timed out and logs them out if so. 157 | 158 | AuthTimeout::hit() // Reset the user's timeout session. 159 | 160 | AuthTimeout::lastActiveAt() // The last activity time of the user. 161 | ``` 162 | 163 | ## Changelog 164 | 165 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 166 | 167 | ## Contributing 168 | 169 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 170 | 171 | ## Security Vulnerabilities 172 | 173 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 174 | 175 | ## Credits 176 | 177 | - [Julio Motol](https://github.com/juliomotol) 178 | - [All Contributors](../../contributors) 179 | 180 | ## License 181 | 182 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 183 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juliomotol/laravel-auth-timeout", 3 | "description": "Authentication Timeout for Laravel", 4 | "keywords": [ 5 | "laravel", 6 | "auth", 7 | "authentication", 8 | "timeout" 9 | ], 10 | "homepage": "https://github.com/juliomotol/larave-auth-timeout", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Julio Motol", 15 | "email": "julio.motol89@gmail.com", 16 | "homepage": "https://juliomotol.github.io" 17 | } 18 | ], 19 | "require": { 20 | "php": "^8.1", 21 | "spatie/laravel-package-tools": "^1.13.0", 22 | "illuminate/auth": "^9.0|^10.0|^11.0|^12.0", 23 | "illuminate/events": "^9.0|^10.0|^11.0|^12.0", 24 | "illuminate/session": "^9.0|^10.0|^11.0|^12.0", 25 | "illuminate/support": "^9.0|^10.0|^11.0|^12.0" 26 | }, 27 | "require-dev": { 28 | "laravel/pint": "^1.0", 29 | "nunomaduro/collision": "^6.0|^7.0|^8.0", 30 | "larastan/larastan": "^2.0.1|^3.0", 31 | "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", 32 | "pestphp/pest": "^1.21|^2.34|^3.7", 33 | "pestphp/pest-plugin-laravel": "^1.1|^2.3|^3.1", 34 | "phpstan/extension-installer": "^1.1", 35 | "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", 36 | "phpstan/phpstan-phpunit": "^1.0|^2.0", 37 | "phpunit/phpunit": "^9.5|^10.0|^11.5.3" 38 | }, 39 | "autoload": { 40 | "psr-4": { 41 | "JulioMotol\\AuthTimeout\\": "src/" 42 | } 43 | }, 44 | "autoload-dev": { 45 | "psr-4": { 46 | "JulioMotol\\AuthTimeout\\Tests\\": "tests/" 47 | } 48 | }, 49 | "scripts": { 50 | "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", 51 | "analyse": "vendor/bin/phpstan analyse", 52 | "test": "vendor/bin/pest", 53 | "test-coverage": "vendor/bin/pest --coverage", 54 | "format": "vendor/bin/pint" 55 | }, 56 | "config": { 57 | "sort-packages": true, 58 | "allow-plugins": { 59 | "pestphp/pest-plugin": true, 60 | "phpstan/extension-installer": true 61 | } 62 | }, 63 | "extra": { 64 | "laravel": { 65 | "providers": [ 66 | "JulioMotol\\AuthTimeout\\AuthTimeoutServiceProvider" 67 | ], 68 | "aliases": { 69 | "AuthTimeout": "JulioMotol\\AuthTimeout\\Facades\\AuthTimeout" 70 | } 71 | } 72 | }, 73 | "minimum-stability": "dev", 74 | "prefer-stable": true 75 | } 76 | -------------------------------------------------------------------------------- /config/auth-timeout.php: -------------------------------------------------------------------------------- 1 | 'last_activity_time', 9 | 10 | /** 11 | * The minutes of idle time before the user is logged out. 12 | */ 13 | 'timeout' => 15, 14 | 15 | /** 16 | * The event that will be dispatched when a user has timed out. 17 | */ 18 | 'event' => JulioMotol\AuthTimeout\Events\AuthTimedOut::class, 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /src/AuthTimeout.php: -------------------------------------------------------------------------------- 1 | lastActiveAt()) { 22 | return; 23 | } 24 | 25 | $this->hit(); 26 | } 27 | 28 | public function check(?string $guard = null): bool 29 | { 30 | $user = $this->auth->guard($guard)->user(); 31 | 32 | if (! $user) { 33 | return false; 34 | } 35 | 36 | if ($this->lastActiveAt()?->addMinutes(config('auth-timeout.timeout'))->isFuture()) { 37 | return true; 38 | } 39 | 40 | $this->auth->guard($guard)->logout(); 41 | $this->event->dispatch(new (config('auth-timeout.event'))($user, $guard)); 42 | $this->session->forget($this->getSessionKey()); 43 | 44 | return false; 45 | } 46 | 47 | public function reset(): void 48 | { 49 | $this->hit(); 50 | } 51 | 52 | public function hit(): void 53 | { 54 | $this->session->put($this->getSessionKey(), (string) Carbon::now()); 55 | } 56 | 57 | public function lastActiveAt(): ?Carbon 58 | { 59 | if ($lastActivity = $this->session->get($this->getSessionKey())) { 60 | // In v2, `$lastActivity` was stored as `int` using `time`. To preseve compatibility 61 | // with v3, lets first check if it is numeric then parse it back to `int` just in case 62 | // Laravel's session store messes with its type. 63 | return Carbon::parse(is_numeric($lastActivity) ? (int) $lastActivity : $lastActivity); 64 | } 65 | 66 | return null; 67 | } 68 | 69 | protected function getSessionKey(): string 70 | { 71 | return config('auth-timeout.session'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/AuthTimeoutServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('laravel-auth-timeout') 18 | ->hasConfigFile(); 19 | } 20 | 21 | public function packageRegistered(): void 22 | { 23 | $this->app->singleton(AuthTimeoutContract::class, function ($app) { 24 | return new AuthTimeout($app['auth'], $app['events'], $app['session.store']); 25 | }); 26 | 27 | $this->booting(fn () => Event::listen(Login::class, InitializeAuthTimeout::class)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Contracts/AuthTimeout.php: -------------------------------------------------------------------------------- 1 | guest()) { 19 | return $next($request); 20 | } 21 | 22 | if (! AuthTimeout::check($guard)) { 23 | throw new AuthenticationException('Timed out.', [$guard], $this->redirectTo($request, $guard)); 24 | } 25 | 26 | AuthTimeout::hit(); 27 | 28 | return $next($request); 29 | } 30 | 31 | protected function redirectTo(Request $request, ?string $guard): ?string 32 | { 33 | if (! self::$redirectToCallback) { 34 | return null; 35 | } 36 | 37 | return (self::$redirectToCallback)($request, $guard); 38 | } 39 | 40 | public static function setRedirectTo(Closure $callback): void 41 | { 42 | self::$redirectToCallback = $callback; 43 | } 44 | } 45 | --------------------------------------------------------------------------------