Reputation: 2841
I'm actually developing a Single Page App for my company that involves different views for different user roles, to prevent people with not enough privileges to access data they are not supposed to see or to execute functions they don't have the rights to do.
I'm using PHP with a REST api on the backend so I think I'm fairly safe there but I don't know nothing about client-side security.
I was thinking about storing an App variable with the current user role like this way in my main.js:
require(['jquery',
'underscore',
'backbone',
'marionette',
'app',
'routers/adminRouter',
'routers/userRouter',
], function($, _, Backbone, Marionette, App, AdminRouter, UserRouter){
App.vent.on("routing:started", function(){
Backbone.history.start();
});
App.addInitializer(function(){
if(userRole==="admin"){
App.Router = new AdminRouter;
} else {
App.Router = new UserRouter;
}
App.vent.trigger("routing:started");
});
App.addRegions({
content: "#main",
page: "#page",
dialogs: "#dialogs"
});
App.start();
App.vars = {};
App.vars.userRole = userRole;
Where App.js is just:
define([
'underscore',
'backbone',
'marionette'
], function(_, Backbone){
var App = new Backbone.Marionette.Application();
return App;
});
Variable userRole
is just a global variable that I bootstrap from my server on index.php page. How much is this safe? There is a way to change userRole
value on page load? Or to change App.vars.userRole
while the App is going? I can't access App
variable from console but as I said I'm very new to the client-side programming and I must know if I can rely on that variable's value. What's the best way to approach a situation like this? Thank you in advance.
Upvotes: 1
Views: 1179
Reputation: 110892
So as long as you put userRole
as a global variable on your page it can be changed from other scripts running on your side. And as you use a reference to the global variable in App
this App.vars.userRole
will change as well. You can make a deep copy userRole
to prevent this.
But this is just a theoretical problem. If someone successfully run its script on your side you have larger problems then that, cause he can call your API with an logged in user.
I've build large single page apps with the approach to render the model of the logged in user right in the initial HTML payload and it works well. And as mention in the comments, all parts of the security has to be done in the backend.
Upvotes: 2
Reputation: 8581
What @devundef says is true. With security, all your authorization must happen on the server side. Once code is loaded client-side and in the wild, there is nothing preventing them from going through and changing it... in ways you don't like. It might in some cases take a lot more effort (for example, if you minify stuff it's harder to read) but it is definitely doable so stuff like that shouldn't be relied on at all.
As long as you're checking server-side, it shouldn't matter if a bad client does this. For example, you can have your userRole as a convenience variable that dictates how your client-side app behaves. They may maliciously change the userRole, give themselves a fake admin status, which gives them access to the admin View, but their play time ends when they want to do anything else (e.g. get data from the server, etc.) This is usually what it comes down to. Basically you want to protect actions (GET, POST, PUT, DELETE) that require certain authorization like admin status. Any sensitive route on your server has to have some check of this sort before it completes the request.
Again, you can not trust when a client sends userRole = admin. What you do is you need to first, have authenticated that they are the user they claim to be, then second, authorize whether that user has appropriate privilege (like admin status). Each time.
I use encrypted cookie sessions. After a user authenticates, they get the cookie which can't be tampered with. So each time they make a request I use that cookie to say "Okay, this is indeed user X". Once I have that I do a DB lookup to say "Okay, he is an admin". If that checks out, I can fulfill the request. If not, I give them a rude error.
In the case that perhaps, certain MODELS, VIEWS, and COLLECTIONS should not be accessible to people without certain privileges, I'm not sure what the best way to go about this would be. Usually the only thing I'm concerned about is the raw data in the DB. But, I might actually compile several different client-side applications (e.g. one for general users, one for only admins) and serve the appropriate one based on their status when they hit index. Well, to be honest I wouldn't even make the initial request hit the same url. The procedure would still be the same though. 1) Authenticate and 2) Authorize.
Upvotes: 5