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

Arantor's avatar

Separate admin and user session

I've been reading around - been a while since this question ever really came up.

Designing a new application, with the following thoughts:

  1. People who are users can also be admins
  2. There is not a compelling reason to have separate models for users vs admins
  3. Users and admins can both create rich content

Given the last point in particular it seems prudent to me (and, as far as I can tell is generally best practice), I want to separate the sessions between users and admins.

Now, every time before this was asked, the answer is 'do role based permissions' or something to that vogue, and that'll be happening anyway; not just anyone can log into the admin area! But because of the user content angle, and potentially quite rich user content, it seems prudent to try to minimise XSRF type attacks where possible. It also ensures that while users might remain logged in for longer periods in the main app, they will be forced to periodically reauthenticate for the admin area.

I suppose I have two questions:

  1. Is this actually a good idea from a security perspective? Gut instinct says it is (and not having separate user models means users don't have multiple passwords to manage, which is also a good idea)
  2. If this is a good idea, what seems to be the best way to go about doing it?
0 likes
9 replies
Arantor's avatar

Thanks for the thoughts - I am using permissions to figure out admin vs non-admin but I don't think that adequately deals with the problem around users potentially trying to do XSRF requests, short of moving the admin area to another domain entirely (which isn't really how I want this service to work)?

Snapey's avatar

you should authenticate all users the same way

having a flag on the the user model is a simple way to indicate they have admin rights.

Unless you need distinct permissions then this is all you need

From a security point of view, it is far better to use tried and tested practices and not try and come up with some fancy scheme of having different sessions or some such

Arantor's avatar

I don't think you understand my use case, though I don't think I expressed it very well.

The use case is a forum. Content will be visible to guests, regular users and admins (and the admins will be posting in the forum area along with regular users).

Admins, of course, will also have the admin only area. I already have permissions for determining which users are admins and are permitted in the admin only area (and no, not by a flag on the user model, but that's not the relevant point here)

Users - all users - will be able to add rich content. That means HTML. Possibly iframes depending on what embed options are in use. Now I'm in the position where I need to figure out how to prevent users triggering drive-by XSRF against admins. Because while things like HTMLPurifier exist, I'm not willing to bet the farm on it catching everything, especially in an environment where I know people will be in the admin area doing things, and then in the regular area seeing how their changes look.

The other suggestion is to have a timeboxed elevated session, but that doesn't solve the problem, it just reduces the risk of it happening because it still by definition keeps everything in the same session. I've seen what happens here.

I can solve the problem by putting the admin area on a subdomain and disabling CORS but that still implies having a separate (therefore second) auth cookie that is set up for the admin area (which in turn, a second session), even if the same user model is used for validation of the password.

How does 'distinct permissions' protect against XSRF, short of my restricting the functionality that users can have? (Which I don't really want to do, it's a direct component of what the users want to do in terms of customisation of their content.)

Snapey's avatar

The point is you should block all types of xsrf for ALL users, and for the protection of guests

If you are allowing html content and dumping it as raw input into blade views then you are opening up for all types of abuse.

Having separate sessions for admins would make zero difference, if for instance they think they are clicking on a link when really they are submitting a form that gives your bad actor admin rights, Its still them that is doing it.

martinbean's avatar

@arantor I don’t really understand what CSRF has to do with sessions? Laravel blocks CSRF regardless of the user type, session length, etc.

Arantor's avatar

@snapey yes, that's the plan - however I'm not going to assume that I'll catch every case immediately owing to the level of customisation being offered to users for rich content. So I want to head off the single biggest risk I can in the process. My immediate rival in this space gives all users the ability to write arbitrary HTML, including scripting, in user-facing content. The only reason this hasn't been abused is because the community as a whole broadly isn't smart enough to figure out how, not that it can't. I want to provide a safer alternative with a defence-in-depth approach, trying to cover all my bases.

@martinbean for Laravel to block CSRF, it has to match the CSRF token in the page, with the CSRF token in the session - when you use the @csrf Blade directive, it's getting the value from the session. If there's no way to leverage the session by way of a drive-by request in the page (i.e. a malicious user encouraging the admin to make a request), there's no way to make that exploit even if someone does figure out a way to break through the other protections.

jlrdw's avatar

@Arantor why not build like this: https://laracasts.com/series/build-a-forum-with-laravel

One user table is all that's needed, example of an app I have:

  • Bob is an admin

  • Suzy is admin and does bookkeeping

  • Mary is a bookkeeper only

  • If Bob is logged in, Bob can only do admin stuff and all access to user stuff. But Bob cannot mess with bookkeeping.

  • If Suzy is logged in she can access admin stuff and bookkeeping and accounting stuff.

  • If Mary is logged in she cannot mess with admin stuff, but has access to bookkeeping and accounting stuff.

So I just check at method level if the logged in users role can or cannot access that method / function.

And use query scopes to let a user edit / view their own data or an admin can access all users data.

Each app will be different as to who can do what.

So in pseudocode:

public function makeInvoice()
    {
        if (a required role of bkeep is not true here) {   // bkeep = bookkeeper
            return redirect('somewhere'); // whereever you redirect to if not authorized
        }
        // Rest of method here is accomplished if 
        // the logged in user has the required role of 'bkeep'.
    }

Again just examples.

Also a Spatie example I saw:

public function update(Request $request, Post $post) {
    if ($post->author !== auth()->user()->id || auth()->user()->cannot('edit posts'))
        abort(404);// or redirect, or whatever action 
    }
    //rest of method if all okay
}

In summary RBAC is at least 3 main steps:

  • A login required
  • An authorization implementation to determine what the logged in person with role can or cannot do
  • Protection of URL and parameters, checking that the logged in users id matches the id used in a query

Each application will require unique tweaks in RBAC, no two apps are exactly the same.

But I suggest you take the forum course I showed above.

Note: just example given.

I suggest NOT letting any stray malicious code in the app, rather treat the code like this forum does for safety.

Snapey's avatar

@Arantor Correct about csrf protecting against form submission as the bad actor cannot know the csrf currently in use by the admin

However, if the bad actor can cause the admin to load a page that contains a hidden form, then that form will have the admin's csrf token and can be submitted and accepted by the framework as a valid request.

Sounds like you are wanting something akin to Unix' sudo which a user has to specify if the command they wish to perform should assume admin rights. In a web application the closest you could probably get to this is a slider on the page header that puts the admin user into an 'admin' mode, from which they can perform system admin functions, but should they perform any regular user functions such as viewing or creating rich content then the slider is automatically slid back to user mode.

Please or to participate in this conversation.