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

jezzdk's avatar

Lock screen middleware

The ever famous AdminLTE admin theme has (as many admin themes do) a lock screen, and I was wondering how to implement this the Laravel way.

So far I've figured I could make a middleware of some sort and a couple of routes to set/remove a session var, but since I'm somewhat new to Laravel I'm not sure if I'm on the right track.

If anyone has a link to a tutorial, some code snippets, or even just some good ideas about this, that would be much appreciated :)

0 likes
31 replies
Pendo's avatar

At the moment I'm also still very new to Laravel. But as far as my knowledge goes, middleware would be the perfect way to add this functionality to your application? It would require a view that can be accessed both by GET as by POST. Add the middleware to protected routes and check a "last activity" session, if the time passed is greater than X (you decide the time) display the "lockscreen" view, otherwise you simpley do the following to proceed to the next step.

return $next($request);

Simplified, this is what the middleware should do:

    public function handle($request, Closure $next)
    {
        if ( time() - Session::get('last_activity') >= 600 ) {
            return redirect('lockscreen');
        }

        return $next($request);
    }

The example in the docs (https://laravel.com/docs/master/middleware) should push you in the right direction.

1 like
Snapey's avatar

I'm missing the point.

if the user goes away, their session should expire and any activity after the point will be presented with the login screen.

This leaves the gap in time between the user walking away from their desk and the time before the session expires. This would require protection by JavaScript since no requests are hitting middleware at the time.

jezzdk's avatar

These are all good suggestions. I forgot to mention though, that the lockscreen could be enabled manually, not only by session timeout. The reason for this action might be for another post, but it can be compared to when a user locks his Windows or Mac machine instead of logging out completely.

d3xt3r's avatar
d3xt3r
Best Answer
Level 29

If i understand it correctly, you are considering a soft logout. See if this works. Make a new controller that handles lock screen

class LockScreenController extends Controller
{
    public function get(){
    
    // only if user is logged in
        if(Auth::check()){
            \Session::put('locked', true);

            return view('locked');
        }

        return redirect('/login');
    }

    public function post()
    {
    // if user in not logged in 
        if(!\Auth::check())
            return redirect('/login');

        $password = \Input::get('password');

        if(\Hash::check($password,\Auth::user()->password)){
            \Session::forget('locked');
            return redirect('/home');
        }
        
        ... handle the password mismatch errors
    }
}

You also need to modify the auth middleware to take this into account

public function handle(Request $request, Closure $next)
{
    ... usual authentication stuff

    if(\Session::get('locked') === true)
        return redirect('/lockscreen');
}

the lock will be active only until the session do not expire.

5 likes
jezzdk's avatar

Yes, that was exactly what I was looking for. Your example gave me the missing piece of the puzzle, I wasn't sure just how I would unlock the screen again with a password check :) Thanks!

Ibbe's avatar

Here is a working lock screen solution Laravel 5.4

Create the LockAccount Middleware


<?php

namespace 
App\Http\Middleware;


use Closure;

use Illuminate\Support\Facades\Auth;


class LockAccount
{
    
/**
     
* Handle an incoming request.
     
*
     
* @param  \Illuminate\Http\Request  $request
     
* @param  \Closure  $next
     
* @return mixed
     
*/
    
public function handle($request, Closure $next, $guard = null)
    
{
           
    if ($request->session()->has('locked')) {
                    
        return redirect('/lockscreen');
                
        }
            
            

        return $next($request);
    
    }

}


Now register the middleware in the $routeMiddleware group.

'lock' => \App\Http\Middleware\LockAccount::class,

Next create the LockAccountController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class LockAccountController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function lockscreen()
    {
        session(['locked' => 'true']);
        return view('users.lockscreen');
    }

    public function unlock(Request $request)
    {

        $password = $request->password;

        $this->validate($request, [
            'password' => 'required|string',
        ]);

        if(\Hash::check($password, \Auth::user()->password)){
            $request->session()->forget('locked');
            return redirect('/dashboard');
        }

        return back()->withErrors('Password does not match. Please try again.');
    }
}

Now add the routes

Route::get('lockscreen', 'LockAccountController@lockscreen');
Route::post('lockscreen', 'LockAccountController@unlock');

That's it. And apply the 'lock' middleware wherever you apply the 'auth' middleware.

Hope this helps.

6 likes
BluCrew's avatar

@Ibbe is that only for sessions via DB with a new column called locked? Im not seeing how the user account actually gets locked....

Snapey's avatar

@BluCrew You misunderstand I think? This thread is for locking your session whilst you leave your desk, or after a time period. Not for locking a user out of their account.

BluCrew's avatar

@Snapey I understand it locks the user session and not account. I worded it wrong. My question is, if this is only for DB sessions or file as well. Im just trying to figure out what what @Ibbe posted works. Because I am trying the code and it doesn't work. I use file sessions. I can click LockScreen button which redirect to lock page where asks for password. And if I enter wrong it fails. If I enter correctly then redirects to home. Which is good. But at same time I can lock, and then on page where it asks for password I could just type in a page URL and it allows me to go there. So it seems its not really locking session.

Snapey's avatar

@BluCrew it relies on the middleware being in place, then in the middleware checks if the session contains a locked variable.

From what I see, it should be irrelevant if you use file or db session management as long as you have a session associated with your user account.

To answer your original question, you don't need to add a column since session data is serialised. When locking, a key value pair is stored in the session object

Ibbe's avatar

@BluCrew if you do follow my suggestion above and apply the middleware correctly it will work. This is 100% tried and tested and I am using it.

Just remember to apply the 'lock' middleware with 'auth' middleware.

In your controller you can use like below.

public function __construct()
{
    $this->middleware(['auth', 'lock']);
}
roknifard's avatar

@Ibbe, sorry for my dumb question, but do you have by chance any idea how I can preserve the user's location on the website before going to lockscreen and after authentication in lockscreen return him back to the same page?

Considering if he is editing a form and he locks the screen and then coming back to the station and login to the application again and see the same form he was editing.

Thank you for your help.

Ibbe's avatar

@roknifard

Simplest solution is to change the lockscreen() & unlock() functions in LockAccountController as below.

public function lockscreen()
{
    session(['locked' => 'true', 'uri' => url()->previous()]);
        
    return redirect('locked')
        ->with('flash', 'Account Locked Successfully!');
}

public function unlock(Request $request)
{

    $password = $request->password;

    $this->validate($request, [
        'password' => 'required|string',
    ]);

    if(\Hash::check($password, \Auth::user()->password)){
        $uri = $request->session()->get('uri');

        $request->session()->forget(['locked', 'uri']);

        return redirect($uri)->with('flash', 'Welcome Back! ' . auth()->user()->name);

    }

    return back()->withErrors('Password does not match. Please try again.');
}
1 like
roknifard's avatar

@Ibbe, this is exactly what I was looking for. Thank you for the solution. Very much appreciate it.

BluCrew's avatar

silly mistake on my end forgetting to add

'lock' => \App\Http\Middleware\LockAccount::class,

but even so now I when I click lock account my browser throws a to many redirects error? Ever seen this?

richardksizemore@gmail.com's avatar

@roknifard @Ibbe on bad password situations I find myself stuck indefinitely. Because the previous URL naturally becomes /lockscreen with return back->withErrors(). How did you handle that after adding the additional markup of returning to the last page post unlock?

TechnicallyGio's avatar

@lbbe, how would one go about setting it up so the user can temporarily lock their account voluntarily?

TechnicallyGio's avatar

@lbbe Also, I'm trying to get this to work but when I click somewhere else after the timeout, it redirects me to the login page as if I was never logged in..

roknifard's avatar

@Ibbe Actually I also have the same issue like what @richardksizemore@gmail.com has experienced. The problem is, the account locks perfectly. First try correct password, everything is fine. But if first try is wrong password, and second try you provide the correct password, it stucks to the lockscreen route. Is there any work around?

Ibbe's avatar

@roknifard mine is working perfect, no issues such. go through you code line by line and match up with mine. or show me your code please.

roknifard's avatar

@Ibbe I can confirm that my code is identical to your code. I have figured it out the problem, but I dont know how to resolve it. The porblem is happening exactly where after a wrong try of password, user is redirected to the lockscreen, which through route, lockscreen() from the controller is called, and the previous visited page (in this case /lockscreen) will sit in the session "uri". So next time the user tries evev with correct password, will be redirected to the /lockscreen! as per session "uri" which is updated through wrong try.

roknifard's avatar

Okay, with a bit of try and error, the best thing I could come up with is this:

In lockscreen() in controller we can use:

    ...
    if (url()->previous() == route('lockscreen'))
        {
            session(['locked' => 'true']);
        }
        else
        {
            session(['locked' => 'true', 'uri' => url()->previous()]);
        }
    ...

And to avoid any possible being stuck, we add this to unlock() in controller:

    ...
    $uri = $request->session()->get('uri');
        if ($uri == route('lockscreen')) $uri = route('main');
    ...

The "if" statement is the new line of code, which should be placed after $uri.

karina_amengol's avatar

Hi

I am following your "tutorial" and like BluCrew i always get "ERR_TOO_MANY_REDIRECTS"

Any idea???

rabat13's avatar

Maybe someone still has a problem with too many redirects so change in middleware:

if ($request->session()->has('locked'))

to

if ($request->session()->has('locked') && url()->current() != route('lockscreen'))
parthl's avatar

@Ibbe I'm stuck at html < form method = " POST " action = " ___ " > Please help with view file of lock screen

Please or to participate in this conversation.