Thursday, 2 January 2020

How to password protect a page with Laravel?

I'm trying to set up some page in Laravel that require a password to view.

A page is a model, called Page.

Each page has an associated password, stored in the Pages database table.

The schema

Schema::create('pages', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('name');
    $table->string('client_id');
    $table->string('url');
    $table->text('content');
    $table->string('password');
    $table->timestamps();
});

I have a route, e.g. Route::get('/page/{url}', 'PageController@index')->middleware('gate'); which will show the 'page', it's just a blade/vue file with specific information injected into the template. These pages allow the user to upload files via AJAX.

Currently, I created some middleware to actual authentication part.

Middleware

public function handle($request, Closure $next)
{
    if(Cookie::get($request->route('url'))){
        return $next($request);
    }
    session(['page' => $request->route('url')]);
    return redirect()->route('gate',['page'=> $request->route('url')]);
}

PublicController.php

public function gate_check(Request $request)
{
  //this part just ensures the correct page is loaded after being authed
  $past = parse_url($request->session()->get('_previous')['url']);

  if(array_key_exists('query', $past)){
    $page = str_replace('page=', '',parse_url($request->session()->get('_previous')['url'])['query']);

    $stored_password = Page::where('url', $page)->first()->password;
    $password = $request->password;  

    if($password === $stored_password){
      //if password matches, then redirect to that page
      return redirect()->route('page', session('page'));
    } else {
      //else redirect them back to the login page to try again
      return back();
    }
  } else {
    //if there is no page information that use should go to, just send them to google instead
    return redirect('https://google.com');
  }

}

The idea of the middleware/auth method was to redirect the user to a login page if they weren't authed. This login page consists only of a password that you need to enter.

Once they enter it, I set a cookie so that they can bypass having to re-login again.

I now realise that is is insecure, or at least it seems that way as the expiry time of the cookie can be manipulated by the client/user - resulting in them being able to stay logged in forever.

Just wish to re-iterate that the method described above is working, but it is insecure. I also should re-iterate that these 'pages' allow users to upload files via ajax. And only should the user be allowed to upload if they're on that specific page e.g. by CSRF.

I need a secure way to password protect pages, which the expiry time of the 'session' can be customised. I'd also need a way to 'refresh' or 'extend' the active session without a page refresh using AJAX so that the user can stay on the upload page (in case uploads take a long time).

How would you approach this?



from How to password protect a page with Laravel?

No comments:

Post a Comment