Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to password protect a page with Laravel?

Tags:

ajax

php

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).

Standard user account with username/email & password is not applicable. Password only.

Wordpress has this feature built in - why is it so hard to do with Laravel for what seems so trivial?

How would you approach this?

like image 433
GBWDev Avatar asked Dec 28 '25 22:12

GBWDev


1 Answers

This is how I would have done:

Standard user account with username/email & password is not applicable. Password only.

For non standard user account, you may yourself generate a guest id on every correct password entered and store it to session.

Schema::create('active_guests', function (Blueprint $table) {
$table->bigIncrements('guest_id'); # on your model specify this as primary key
$table->unsignedBigInteger('page_id'); # authorized for after validating password
$table->integer('expires_at'); # store it as unixtimestamp now()->addHours(5)->timestamp
$table->timestamps();
});

You can just query this way to check authentication

$page = Page::where('url', $page)->where('password', $password)->first();
if ($page) {
ActiveGuest::updateOrcreate(....);
Session::get('pages_authorized_for', [array_of_pages]);
// push the new page id and store it back to session as array
} else {
// incorrect password or page removed
}

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).

From your ajax you can just increment the expiry time on active_guests table.

For longer upload time to be extended you may add a last_activity as timestamp.

like image 159
Hášíl Páůďýál Avatar answered Dec 31 '25 11:12

Hášíl Páůďýál



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!