3

I'm very curious to know what strategy usually use different developers for managing user permission policies to different parts of single-page web application.

Just for a case: under single-page web app I mean web application with only one HTML (JSP, PHP, whatever) page as entry point and all the other client UI components/pages built with JavaScript).

Are there are any best practices, approaches or frameworks for making this things more easy and straightforward?

Let's take an example:

  • There is a single-page web application with 2 tabs: A and B
  • Each tab has 3 components (grids, buttons, whatever): A1, A2, A3 and B1, B2, B3
  • There are 3 user groups: U1, U2 and U3
  • U1 has access to both tabs and all the components
  • U2 has access to both tabs but only to components A1 and B1
  • U3 has access only to tab A and all the components within this tab

One solution which lies on the surface is to build a global JS object on page load (or with separate AJAX request) and store the user groups there. And then use conditions in the code to verify the current group and allow or restrict a specific functionality. A simplified example would look something like this:

index.html

<script type="text/javascript">
    window.onload = function() {                
        MyApplication = {
            userGroup : 'U3' // can be also U1 or U2. This value comes from server
        };
    }
</script>   

And then in code we will have checks like:

if (MyApplication.userGroup == 'U1') {...}
if (MyApplication.userGroup == 'U1' || MyApplication.userGroup == 'U2') {...}
if (MyApplication.userGroup != 'U3') {...}

The example can be extended with the scenario of handling events in different ways depending on the user group. Let's say A1 is the button and A1OnClickHandler is its on-click-handler:

var A1OnClickHandler = function() {
    if (MyApplication.userGroup == 'U1') {
        console.log('A very private information'); 
    } else if (MyApplication.userGroup == 'U2') {
        console.log('Less private information'); 
    } else if (MyApplication.userGroup == 'U3') {
        console.log('Public information'); 
    }
}

A drawback of the approach I described is the possibility to change value of MyApplication.userGroup by user on the fly after the page is rendered. Just open console and type:

MyApplication.userGroup = 'U1';

Bingo, user of group U3 has now rights of U1 and will be able to see private information on A1 click. Ok, he will still not be able to see those components which have not been rendered on page because of the initial conditions. But he will still be able to access the functionality available after these post-checks conditions.

To be honest I was a bit surprised by not being able to find any specific information related to this issue in the web. Do I miss anything? It would be interesting if anybody could share own experience of solving this kind of things.

UPDATE: Of course all the actions that should not be done by users of groups U2 U3 will not be executed on the server because there are security checks on server as well. For example, even if a hacker will be able to show a button or a field on frontend, the action will not be executed on the backend. But what I'm looking for is not to give a chance to do this kind of things on frontend at all.

Dmitry B.
  • 99
  • 3
  • 9

1 Answers1

0

You can't use JavaScript for anything related to permissions or security: Users can simply open the browser console and edit your JavaScript. So this approach is a no-go (well, unless you don't care at all).

The correct solution is to implement security on the server and only send those components to the browser which a certain user (which you identified by some kind of login) can actually see/use as per the permissions stored on the server.

If a component contains sensitive parts, then you need to figure out a way to split it and send different versions to the browser, depending on the user.

[EDIT] Try to figure out a way to split your scripts into smaller parts (components). The ZK Framework works like this: You have a framework of HTML components (component = JavaScript, HTML template + CSS) plus a JavaScript core that loads components and configures them depending on a JSON configuration which the server prepares.

That way, you can build the UI structure in PHP, convert that to JSON, send it to the client which will render the UI using this "configuration". The components will be reusable and the same for all clients. There will be no need at all to check permissions on the client side because the client code never needs to know.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thanks for the input! Yes, I fully agree that the security check on the server is the most reliable and ideal way to go. I also pointed out that user can open console and change JS code or value of a variable. However, if the application is very complex and has hundreds of components with thousands of events, sending all the components custom from the server may become a quite challenging deal. So I wonder whether there are any tricks and approaches to handle a part of permissions on client code. – Dmitry B. Jan 20 '15 at 09:20
  • @DmitryB.: As far as I can tell, no one ever tried this since it feels like a bad idea to begin with. Also: You don't have hundreds of *different* components. 20 text fields are still just the same component repeated 20 times. – Aaron Digulla Jan 20 '15 at 09:25
  • Ok, then to summarize your suggestion: if for example somewhere on the page (let's say on abstract component UserPanel) there should be a button which should be shown only for users of group U1, there should be 2 copies of UserPanel.js file one with the button and another without? Another option which I can see following your suggestion is to render the button on the callback from AJAX request after the component rendering. P.S. Also with components I mean not simple fields but custom built user UI widgets like grids, panels, windows, trees, so on. – Dmitry B. Jan 20 '15 at 10:02
  • I also doubt no one has ever tried managing permissions in client code :) – Dmitry B. Jan 20 '15 at 10:05
  • I never actually changed the JavaScript for this; the JS can build any component. With AJAX, I send data structures which describe the UI. Those drive the JS code and build the UI. They also send the data which should be displayed in the UI. So the JS code never changes, the data structures (= UI description) and the data does. – Aaron Digulla Jan 20 '15 at 12:30
  • I forgot to mention that the approach I described also loads user group name (or ID) from the server. But this happens only once on page render or can be actualized with separate AJAX call like you described (I actually load these configs as additional synchronous call from the page). So let's say you loaded data structures which describe UI at A moment. Then a user event happens at moment B which should be handled differently depending on the user group. So what if user hacked a value from the data you received at A before the event happened? – Dmitry B. Jan 20 '15 at 13:12
  • Server side validation needs to catch all such attacks. You always have to assume that the user (or some attacker) changed the data which is received by the browser and which the browser sends to the server (for example, hiding additional money transfers just before you click the "OK" button in your online banking or inserting additional transactions or modifying amounts, etc.). – Aaron Digulla Jan 20 '15 at 13:23
  • Which is why modern online banking systems will send you a copy of your transactions over a second channel, like an SMS or a printed letter. – Aaron Digulla Jan 20 '15 at 13:24
  • 2
    AaronDigulla, I think you didn't understand the idea of a single page application. Of course permissions are checked on the server. The question was how to make user interface match the permission. It's not about security, it's about usability. Sending only certain parts to the client is not SPA, it's MVC style. Imagine you are developing a desktop application, are you going to deliver different versions of your executables for each user group? That would be ridiculous... – Dominik Dec 02 '16 at 07:50
  • @Dominik And that's exactly what you have to do for SPA web apps: Every user gets a different app. The server code is the same for all of them but the server must meticulously select each bit that it will send to the client. If you send each user the same app and just hide parts which they should not be able to use, they can simply right click and make them visible. – Aaron Digulla Dec 06 '16 at 09:37
  • I agree with @Dominik, i don't think SPA framework like VueJs are capable of delivering different page component from the backend based on user permission, the idea behind SPA is to avoid calling the backend for each page html but just for page data/content – fudo Jun 10 '22 at 08:27