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

FrancescoPassanti's avatar

Back button browser

Hi, sorry for my poor english and for possible grammar error.

Recently, during develop a university project, my tutor have explain me a security problem which have many web site and platform. I talk about the problem derivate from browser's back button. I try this procedure on my laravel project and i confirm this theory. In fact when we do logout from an private area, clicking on back button it's possible to read all information.

I have implemented a solution after learning this article http://www.codeproject.com/Tips/549347/Browser-Back-Button-Issue-After-Logout

So i wrong something?

sorry again for my english but i hope which the problem is clear.

Bye, Francesco

0 likes
19 replies
JeroenVanOort's avatar

Nothing is wrong, this is just how browsers have been made; you can't do anything from the Laravel side of things. They cache the page you are served and if you get back to it from another page, your browser doesn't request the page again; it just shows you the page it has received and saved earlier (when you were still logged in).

As for a security risk, I don't really see the significance of it; you're only seeing what you've seen before and you can't do anything from that page. If the page has a form and you submit it, you thus make a new request and the server will not process the request because you're not logged in. The only place where this could be a problem is when using a computer that is also used by others that you don't want to see that information, like the computers in a public library for example. In that case, don't use the computer at all and if you do, empty the browser's cache and history.

skashizadeh's avatar

it's about cache and history in your browser's js. you can not override your browser behavior but you can disable history in js and cache by adding following code :

for js history :

    history.go = function(){};

and for your routers :

Route::group(array('before' => 'auth', 'after' => 'no-cache'), function()
{
    Route::get('dashboard', array('as' => 'getDashboard', 'uses' => 'DashboardController@getIndex'));
    Route::get('logout', array('as' => 'getLogout', 'uses' => 'LoginController@getLogout'));
    Route::group(array('prefix' => 'users'), function()
    {
        Route::get('users', array('as' => 'getUsers', 'uses' => 'UsersController@getIndex', 'before' => 'hasAccess:users.index'));
    });
});
Route::filter('no-cache',function($route, $request, $response){
    $response->headers->set('Cache-Control','nocache, no-store, max-age=0, must-revalidate');
    $response->headers->set('Pragma','no-cache');
    $response->headers->set('Expires','Fri, 01 Jan 1990 00:00:00 GMT');
});
FrancescoPassanti's avatar
Level 1

Thanks :) .It's all how i think. Now, I post my solution good and functional for laravel 5. I put this code in template admin page, after the jquery file.

       CheckingSeassion();
        function CheckingSeassion() {
            $.ajax({
                type: "POST",
                url: "{!! url('auth/secure') !!}",
                data: {},
                success: function (response) {
                    if (response==0) {
                        document.location.href="{!! route('index') !!}";
                    }
                    else
                    {
                    $("body").removeClass("hide");
                    }
                },
                failure: function (msg) {
                    alert(msg);
                }
            });
        }

This function is always execute, also when we click browser back button.

The ajax call this method

 public function postSecure()
    {
        if (\Auth::check())
            return 1;
        else
            return 0;
    }

The only problem which i found is about csrf request. But i change te default VerifyCsrfToken Middleware in this way :

class VerifyCsrfToken extends BaseVerifier
{
private $openRoutes = ['auth/secure'];

    public function handle($request, Closure $next)
    {
        foreach($this->openRoutes as $route) {

            if ($request->is($route)) {
                return $next($request);
            }
        }
        return parent::handle($request, $next);
    }
}
1 like
RomainLanz's avatar

@FrancescoPassanti Why not create a package with your solution? If you don't want, I ask you the permission to do one.

EDIT: BTW if the user disable JavaScript your solution doesn't work.

1 like
FrancescoPassanti's avatar

It 's right . But i think most of the Which web application must use javascript to run . I use laravel from about six month but i do not have the skill to develop a package. In Additions to, i am working very much in this period . in the near future , when i will improve my skills , i will develop the package and put all code on github . Thanks

sitesense's avatar

Just for fun I thought I'd try something similar using nothing more than a snippet of Javascript/jQuery and a hidden field in the layout.

This seems to work quite well. The logic being that the input will retain it's value when the back button is pressed, but will reset when the page loads.

    <input id="auth" type="hidden" value="" />
    <script>
        $(document).ready(function() {
            $('body').hide();
            if ($('#auth').val().length == 0)
            {
                $('#auth').val('yes');
                $('body').show();
            }
            else
            {
                location.reload();
            }
        });
    </script>
sitesense's avatar

Ok, I had another thought about this last night. Just given it a try and it seems to work and it's server side - no javascript involved so more secure.

If when you logout - you are then redirected to the previous page, if the previous page was protected then the auth middleware will kick in and direct you back to the login page again. Seems effective at preventing the back button from displaying the previous secure page.

Just need to add this to Http/Controllers/Auth/AuthController.php:

    public function getLogout()
    {
        $this->auth->logout();

        return redirect(\URL::previous());
    }

@RomainLanz maybe no package needed after all :)

6 likes
RomainLanz's avatar

Nice work, but with this code we need more HTTP request. :(

sitesense's avatar

@RomainLanz only one more request that is barely noticeable. How many times can you logout without logging back in :P

Also, the marked answer needs a further request via Ajax.

1 like
johnabdev's avatar

@sitesense , I was moved by the way you answered the problem. It's freaking simple without adding too much tweaks and it's on the server side and you fixed the problem. How can I commend you? :D

1 like
shaN's avatar

@sitesense but there is one problem if you hit backspace twice, it will load from the cache. just checked right now

2 likes
rafaelbeckel's avatar

My 2 cents:

What about putting this on auth middleware?

    protected function nocache($response)
    {
        $response->headers->set('Cache-Control','nocache, no-store, max-age=0, must-revalidate');
        $response->headers->set('Expires','Fri, 01 Jan 1990 00:00:00 GMT');
        $response->headers->set('Pragma','no-cache');

        return $response;
    }

And then, instead of calling $next($request) directly, you do:

    return $this->nocache( $next($request) );
1 like
NikRadadiya's avatar

@sitesense - Your solution is working but for that I need to modify getLogout() function in \vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php in laravel 5.2 how can I do without modifying this file,Can I override that function?If yes,how to do that, As I new to laravel I don't have any idea to do that.

RaZik's avatar

This solutions is works! Create a middleware using artisan.

php artisan make:middleware RevalidateBackHistory

Within RevalidateBackHistory middleware, we set the header to no-cache and revalidate.

<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class RevalidateBackHistory
{
 /**
 * Handle an incoming request.
 *
 * @param \Illuminate\Http\Request $request
 * @param \Closure $next
 * @return mixed
 */
 public function handle($request, Closure $next)
 {
 $response = $next($request);
  
 return $response->header('Cache-Control','nocache, no-store, max-age=0, must-revalidate')
 ->header('Pragma','no-cache')
 ->header('Expires','Fri, 01 Jan 1990 00:00:00 GMT');
 }
}

Update the application’s route middleware in Kernel.php

protected $routeMiddleware = [
    .
    .
    'revalidate' => \App\Http\Middleware\RevalidateBackHistory::class,
    .
    .
    ];

And that’s all! So basically you just need to call revalidate middleware for routes which require user authentication.

2 likes
carlos.ribeiro's avatar

Having javascript to handle this issue in my oppinion won't do any good, just adds a little complexity to the 'hacker' that needs to delete that code in order to succeed and use the back button again with all it's information leaks.

1 like
grafix's avatar

@RaZik , Sir It didn't work on me when I tried to include the middleware in the contruct function. Does this work on the latest version on laravel?

Please or to participate in this conversation.