I am new to AngularJS and trying to grasp the concept of implementing an access control layer so that some pages/menus will be hidden from certain users.
I usually implement ACL and all routes on the back-end (PHP/MySQL) but this project require me to do everything on the client side only.
We have a remote server that is in charge of authentication and upon successful login, will return an is_admin flag so that I know whether to display the additional info.
Although not likely, since Angular is also the rendering engine and is in charge of all the logic, I am afraid that users will be able to play with browser developer tools and/or other 3rd party tools and gain access to those areas (since all scripts & logic will be visible to them in the browser).
So if I do something like:
if (user.is_admin === true)
{
//display the additional admin data...
}
A user can potentially set user.is_admin = true in the browser tools and gain access.
With server side rendering such as PHP, the user will never be able to even know about these hidden areas. i.e
<?php
if ($user->is_admin === true) {...}//user will never ever see that or be able to modify $user properties
?>
Of course that the server will keep on authenticating every request so this exploit will only allow limited access, but still seems like a non secure way of hiding sections from certain users.
Am I missing something in Angular or is there a better way of doing it so that it's bullet-proof for client side hacks?
The Angular way of hiding sections is with the ng-if/ng-show/ng-hide directives, as in:
<div ng-if="is_admin">...</div>
You can't hide those divs from people who look at the source, or the resources you make available in your app. So don't provide admin data to those views.
My approach was to make an "admin" app in addition to the "standard" app and link between them. This way, the only things exposed are links to the admin site, which are blocked to non-admin users:
<div ng-if="is_admin">Link</div>
All requests to my /admin/* pages return a 401 status code if they are not an admin. The REST resources also return 401 status codes as appropriate.
(Edit: changed above ng-hide to ng-if to suppress those divs in the resulting DOM.)
Related
In a regular web app, when someone logs into the system they simply save an encrypted cookie that gets send on each request and the backend decrypts the cookie and uses the e.g. user_id/guid to lookup the user.
How do things differ when authenticating with a angular app?
Is there anything else to consider or it is basically the same process?
We use more or less the same mechanism.
Access to the application as a whole requires authentication - that is unless you're logged in, you don't get any of the javascript experience at all. This could make the login / login failure much less wizzy for the user, but in our authentication provider it's fine.
Part of our auth mechanism means the list of roles that the user has is a data object available within the browser. The javascript code uses this to decide which buttons / menus etc. are displayed. I checked with our security guy and he said something like "Well, it's a kind of direct object reference issue, but as long as each action is authorised properly, you're probably ok." So it's possible that a user could hack data values and change what they can see, but because of the next bit, they can't break our data (or see stuff that they shouldn't).
Each service call our javascript makes is authenticated and authorised. That is, the javascript call will fail if the auth token is missing or bad, but also, we internally match the auth token with a user and a set of permissions, and only execute that if the user is authorised to do so. (Note that this is good practice whether you're using Angular or not). Also note that this applies to GETs as well as POSTs - we don't want to give them data they should not see.
It gets much trickier if your API is hosted separately from your Angular site.
I am creating an Angular 1 SPA. Certain controls are only visible to users with certain permissions. This is based on scope variables set by server api calls.
It occurred to me that if I could access these variables through a browsers dev console, I could change their values.
I tried this for example:
angular.element($0).scope().$parent.myUserInfo.accessType = "admin"
angular.element($0).scope().$apply()
And sure enough, the admin controls popped up on the page even though I was not logged in as an admin. Is there a best practice to stop this or am I going about it completely wrong?
The authentication always have to be made on the server side.
I don't know what you are trying to do, but if the user interacts with some webService/Rest API, etc... the server should disallow such interactions.
If the accessType property of your scope is just a way for you to know which UI you should display to the user, and the authentication/session mechanism is correctly handled by the server, that should not be a problem.
However, you cannot disallow the user to play with the dev console, so you'd better handle the authentication correctly.
I am not sure if there is a way of protecting values in $scope.
But as JavaScript is executed client-side and it is therefore be possible for users to modify said code, I would always verify permissions server-side. Then it wouldn't matter if users enable the admin controls client-side as they have no permission to use the api calls.
I am currently learning Angularjs for an application that will need role-based access control logic. There are scenarios where the logic will be necessary to restrict access to certain pages based on your user role. There are other scenarios where I will have to restrict access to a section of a page or certain fields on a form based upon a users role. If Angularjs is a client side methodology, this seems to present a problem if I don't want the client to have any access to an item they aren't suppose to have access to.
What is the current approach for handling these scenarios from the server without interfering with Angularjs?
I know I have access to razor to restrict page section access but what problems would this present for Angularjs and would this be a good idea to mix razor and angular view syntax?
In my transition to Angularjs, I am having a problem wrapping my mind around how to handle this.
You can request views using ajax from MVC and handle any access restriction with a response.
I don't have good example now but it might set you in the right way?
Using knockout I have used a template enginge to retrieve partial views from MVC.
Same thing should work here and you can keep the access restriction on the server side (which you should).
One of the methods would require setting up a service to check if a user is authorized for the page (in angular), then setting params on a route
{
"/admin": {
templateUrl: 'partials/admin.html',
controller: 'AdminCtrl',
requireLogin: true//THIS
}
and then canceling navigation with in a controller by handling the $locationChangeStart event
(This is all shown in the article I posted below).
My suggestion would be to create views for each logical page element with individual controllers and handle access the same way as the example. Instead of per page, it will be per view.
In the case of adding/removing inputs from your forms, maybe there would be some way you could also handle this inside the service you created and then ng-show/hide the element depending on the access level.
A quick google search for 'Role Based Access Control in Angular' will pull up tons of useful tutorials/articles.
See This
And This
(more in-depth with the same examples)
You need to think about it in two parts:
Securing your API (ASP.NET Web API)
Using security/role information to present an appropriate UI (available options and routes, elements enabled / disabled etc. -> AngularJS)
You should assume that API clients are malicious - they aren't necessarily your application.
In terms of authentication / authorisation options: HTTP header tokens, such as JWT are a common option but HTTP only cookies are still a good option, especially if your clients are all web-based. The other advantage of JWT is that you can allow the client (AngularJS) to read the payload, and easily share information about what the user is allowed to access. If you use cookies you generally have to supply that information in another way (server side injection or API call, for example).
How your generate the token / cookie (and what they contain in terms of claims) depends how you need to authenticate people. It can be your own ASP.NET MVC login form, with credentials stored in a database if necessary.
You can use MVC views as AngularJS templates if you like, though I tend not to see many advantages beyond the layout.
I'm looking for information on how to implement secure pages using ExtJS 4. By secure pages I mean the user will log into our website using Siteminder (SSO) and so we will have the user's identity. Then we would determine what roles the user would have by making a database/LDAP call and only render those views/components that the user has access to.
Several questions come to mind:
1.) Of course I would expect we would do the authorization check prior to rendering the pages on the server-side, so how do you do this prior to firing Ext.onReady()? I need to have the ExtJS wait for the response from the server?
2.) What is the best way to organize a page's components where the case may be someone could see a particular component and another person cannot?
3.) How do I deliver the resulting page (i.e., the pieces the user has access to) to the client?
TIA!
If you're working from a Java background and are comfortable using Spring, I wrote up an approach using Spring Security here. This will allow you to plug-in any authentication mechanism you want. The main difference is that instead of using an index.html to bootstrap the application, I have a JSP so that the Spring Servlet Filter will fire for authentication. The Ext JS app blocks until the user is authenticated and the user's roles/permissions are provided.
Use a server side technology to pre-process authorization by putting your JS App launch script into a JSP/GSP. What this does is forces server side components to kick off first and then render the HTML/JS/CSS to the client. For full RIA app use index.gsp(or jsp) and the your URL stays "domain/contextroot" .
You can interrogate access privs to content via ajax request to server or alternatively you could set JS variables via again JSP technology that is processed first before the rest of the client response is returned.
< g:javascript>
//global env var definition
var env = "${System.getProperty(Environment.KEY)}";
< /g:javascript>
Both of these are not 100% safe as client side code can be altered. The real security enforcement must be handled on server side when data is submitted for processing.
'3. Easy way would be to hide/show views etc based on 2. above. There are also some experimentation out there with modularizing the client side MVC application by lazy(manually) initializing controllers that may or may not be needed.
Hope this helps.
DB :)
I am currently experimenting with the following solution. Although it will only work for apps with a rather simple set of users, it could be of some help to you.
To begin with, user authentication is done without extjs, using a simple HTML/CSS page. Once the user logs in, its details (user id, role) are saved into the PHP session. And then the page redirects to one of two extjs apps.
One app for normal users (I'll call them clients), these are people who's client side JS does not include any admin functionality. The other app is for admins.
Both apps have their classes inherit from base classes. So we have, for example, base.mainMenu from which both admin.mainMenu and clients.mainMenu inherit. The only difference in the app.js script is the controllers loaded, and per extJS 4 dynamic loading module, only the related views are loaded (ie, seen on the client side). In my case, all pages load dynamically anyway, so my users can only dynamically load pages in their mainmenu.
The admin app blocks certain features using a global JS variable that includes the user's role. So for example, the hiding of an 'edit' button from moderators (an admin group with less rights) is done once the view is loaded (in practice this is actually done by not loading a plugin that allows editing on the view).
To wrap it all up, any call to the server checks whether the session user has rights for the requested operation, so regardless of client side scripts, server operation can only be performed by people with the appropriate rights.
To summarise, you have 3 different strategies that you can mix-and-match:
Loading different apps for different users. If your classes all inherent from base classes, this is easier than maintaining 2 or more completely different apps.
Using a global JS variable to disable/enable certain features for certain users. This is only good if you don't have a problem with the client side loading features that are then disabled (but still seen by debuggers).
Regardless of anything, all server-side calls are checked against session variable.
check out Role-based access control. I use Yii's database-based RBAC, and have a php script that returns the rbac rules in json format when ext starts up
on the client, the best bet is to simply hide or disable functionality that is not allowed.
on the server, you should throw a 403 http error if the user is not allowed to perform a function. handle ajax exceptions in ext and check for 403s.
I have been struggling all day with an issue. I am sure there must be some easy solution that lots have already implemented as it looks to me as a basic setup.
I am building an app with GWT and appengine using requestfactory. This app has some "pages" (they are actually MVP views) that everybody should have access to. It's like the home page and a couple of views where the service we provide is described. Then if you want to use the service you have to login (with google accounts and all that). Only being logged in you have access to the rest of the views (pages) in the app. The question is, how to handle this?, the fact that some pages and some requestfactory calls are public and some other have to be available to those that have logged in?
I have already discarded the auth-constraints tags in web.xml because they work with all or nothing.
The next alternative was to use servlet filters (as the expenses demo does). That could work, but only if the "open" or not secured pages didn't need to access any data from appengine datastore (and I don't want to close that door, maybe in the future I want to show status or number of users, etc etc). The reason for this is that with request factory you only have one servlet so if you put a filter you shut down all comunication with appengine if the user is not logged in.
I was thinking of implementing this filter, with requesfactory for all the stuff once the user is logged in and also implement some RPC services for the data i might want to display in the "home or information pages" that i might need to retrieve from the datastore. However it looks a bit overkill for me.
Another alternative is to implement a check that the user is logged in all the request factory service methods that i want to protect. But that doesn't look to elegant either...
Anyone had the same problem? any ideas?
I'd appreciate any help on this.
Thanks,
You say that the auth constraints are "all or nothing", but that's not true - they're per-url. See here for details. Also, your connection of servlet filters and datastore access is a non-sequitir - the two have nothing to do with each other.