One approach is to:
- Add a field to the users' table to store a session token
- Generate a new value after the user logs in and store both in the session and in the database
- Use a middleware so to compare the value stored in the user's record to the session, if those values are different, log the user out
I will try to scratch the steps:
- Add token to user migration
database/migrations/2014_10_12_000000_create_users_table.php
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('session_hash', 100)->nullable(); // ADDED THIS
$table->rememberToken();
$table->timestamps();
});
}
- Generate token on login
If you are using the default Laravel Authentication, after running php artisan make:auth you should have a App/Http/Controllers/Auth/LoginController.
There you can add an authenticated method to this controller
// app/Http/Controllers/LoginController.php
protected function authenticated( Request $request, $user )
{
$token = str_random( 40 );
$request->session()->put( 'app.session_hash', $token );
$user->forceFill( [ 'session_hash' => $token ] )->save();
}
You should also add a similar code to the registered method on the RegisterController if you let the users self-register:
// app/Http/Controllers/RegisterController.php
protected function registered( Request $request, $user )
{
$token = str_random( 40 );
$request->session()->put( 'app.session_hash', $token );
$user->forceFill( [ 'session_hash' => $token ] )->save();
}
If you prefer add a method on the User model to handle these similar code and call it from these methods above.
- Add a middleware to check the token
run php artisan make:middleware GuardSession
Replace the handle method on the generated middleware with this code:
public function handle( $request, Closure $next )
{
$user = $request->user();
if (is_null( $user )) {
// not logged in
return $next( $request );
}
if ($user->session_hash !== $request->session()->get( 'app.session_hash' )) {
auth()->guard( 'web' )->logout();
$request->session()->invalidate();
throw new \Illuminate\Auth\AuthenticationException;
}
return $next( $request );
}
Add the middleware to the Http\Kernel.php:
'web' => [
// ... other middlewares
\App\Http\Middleware\GuardSession::class,
],