We have an application (C# on the server, using AngularJS / Web Apis for a single page application) that assigns users different roles, which are stored in the database. When the user logs in, the user object (including RoleID's and RoleName) is transformed into a JWT and sent to the user, which is then used as authentication.
We're having trouble determining the best way to maintain and use these access roles however. Specifically, to use them in the current set up, it would seem that we have to hard code either the name of the role or the ID into the application.
For example, on the client side, if we want only users with a Manager role to be able to see and click a button, we would have to explicitly state that, ie if (UserService.HasRole('Manager')) { doStuff(); }.
Conversely, we'd have to do the same thing on the server side (because everyone knows relying on client-side security is bad). When the server gets a request on the API, it checks the JWT for validity and, if valid, checks the User's roll to see if they are allowed access to the specific web API endpoint.
This all seems prone to breaking if a role is renamed, or the ID changes. I generally hate hardcoding things like this. Is there a better methodology or approach that can be taken here?
In the past, when we've done RBAC (Role Based Access Control), we decouple the Role from the Permission e.g.
Role Permission
===============================
Manager Create Order
Manager Delete Order
Till Operative Create Order
Administrator Create User
Administrator Suspend User
etc.
This could be stored in a database and cached in something like Redis. Two tables, Role and Permission, where the Permissions need to match the ones built into the application (you could script this).
So your permissions grow with your application e.g. you add a new dining service, you can add a "seat diners" permission. The permissions for existing/mature bits of the software should rarely change (unless they were written incorrectly), whereas the roles are entirely fluid and can be renamed etc.
You can then use an annotation/security framework to ensure that the user making each API call on the server side has the correct role required.
You can even make it additive and allow a user to occupy multiple roles at once to blend things together.
You may maintain your user to role mapping in the database also in another table (using FK constraints) or you may use something like LDAP with the mapping being looked up from the DB/cache.
On the server side, Microsoft has built in management for roles. I would first look at
http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity
And then I'd also look at the the IdentityServer project for working with JSON Tokens on the server side.
https://brockallen.com/2013/04/14/getting-json-web-tokens-jwts-from-adfs-via-thinktecture-identityservers-adfs-integration/
On the client, I would suggest storing the tokens as either just in memory javascript or if you want them to persist, I would store them as cookies but make sure to set the cookies to not be accessible by JavaScript by using the httponly parameter when creating the cookie.
HTH's
Related
I have a web app and I can login as admin or customer in it. Admin has access to all pages, customer has access to certain pages only.
When customer logs in, the required pages, say 3 pages are shown, after he logs out and the admin loges in, still only those 3 pages are shown. Although, After manual refresh, I'm able to see all the required admin pages.
How do I refresh automatically when user logs out? I'm using Angular 10 framework.
Since you're question is pretty generic, it is hard to get into specifics.
You must have some login code, so presumably you are loading a users permissions from some system and storing those permissions as part of the app--presumably as a cookie?
You can protect routes using auth guards. We primarily use canActivate guards.
You can hide elements on a page--such as screen navigation links--with an *ngIf. We created our own structural directive to accept in a list of allowed user permissions, and the current user's permissions and use that to determine if certain dom elements should be created or not.
I'm not sure about C#, but in Java we created a Spring Annotation to validate user permissions when a user tries to access a REST Endpoint. I suspect something similar must exist in the .NET world.
Conceptually it is not much different than our Angular custom structural directive; comparing allowed permissions to perform the action with user permissions, and then either allowing or denying the action.
It sounds like your users are getting elevated permissions by reloading the app; so I suspect there are some underlying security issues with your full implementation, but without a code review cannot begin to speculate what that is.
I am using a stateless design for a MVC5 Web API 2, ASP.NET application.
User roles are created by administrators by selecting permissions.
Each user in the application is assigned a custom user role, one role may be shared amongst users.
Razor views are structured based on the permission in the users role.
MVC and API controllers are available depending on the permissions in the users role.
For each request to the server, the users permissions need to be processed.
I can think of 2 ways to do this:
Store the id of the users role in the Role claim and perform a database lookup to retrieve the permissions for each page-load/request.
At the user login, retrieve all the permissions assigned to the users role, serialise them as JSON and store them in the Authentication claim. Then at each page-load/request, de-serialise the JSON back into objects and process the permissions.
Which of these would be the better option?
Option 1 is a lot slower than option 2.
Is there a security risk of storing the permissions in the cookie?
Is there a better or alternative solution which is quick and secure.
Storing permissions and other sensible data inside a cookie is always a very bad idea as it's quite easy to manipulate them. Trusting cookies requires an additional server-side check which defeats the purpose of storing it inside a cookie.
You're way better off only trusting the data that is under your control, aka the data in your database(s).
Depending on your application it might be useful to lazily evaluate permissions only when you really need to access them if the performance hit is too big. Keep in mind that you can make use of things like Redis to improve performance dramatically.
So again, depending on your application I'd probably go for option 1 as it's the more secure way.
I am building an application using azure mobile services, where I have used azure authentication services for user authentication. Each user can store some of their information. I want to add more than one admin who can manipulate the information of all user when needed. I also want to provide admins a separate front-end. Is it possible to implement. If possible kindly provide me some resources.
Mobile Services on it's own doesn't have any concept of what an Admin is in your application. For that reason, you'd have to design the admin system yourself. You can do this in a few different ways including:
Create an Admin only app that the admin's use and send the Mobile Service Master Key over in the headers. This will make the user.level property return "Admin" while user's who are just authenticated to your app will have a user.level property of "Authenticated". You can use this in your server scripts to basically say "If admin, do THIS, otherwise if authenticated, do THAT".
You can create a Role table in your database and check if the user making the request is an admin for reach request. If so, you can then use similar server side logic above to perform specific logic for the admin vs the non-admin.
If you know the specific user IDs of people who will be admin's, you can just check against the user making the request in your server side logic (the advantage of this approach is that it doesn't require an admin only app or an additional check against the database to see what the user's role is).
Again, Mobile Services doesn't have a concept of an admin as far as your users go (only the sense that if the Master Key is sent in the request is "from an admin") so that's something you have to put in place yourself.
I am creating a web application that, simply put, allows for the users to create their own "sites" which have their own set of users. I look at the domain name of the request coming in to determine which "site" to display. I need to have completely different sets of users depending on which "site" you are on. For example: If I visit site1.example.com I am able to register as bob. Trying to login to site2.example.com with my credentials from site1 would fail, because I don't have an account there. Likewise, I should be able to create another, independent bob user on site2. Therefore, not only will I need to store additional information with the user (like what site they registered on), I also need to make the username field non-unique. Any ideas on how to accomplish this? I would like to use the built-in security provider in ASP.NET, so I can use things like [Authorize], but if some 3rd-party security suite would work, I am open to that as well.
With Asp.net membership provider ... one easy way is to change "role" s for each set of users. All users registered for site will get role "site1user" assigned. And so on. You can maintain all users in one database ... differentiated by roles.
I want to implement roles and permissions on a web app we have created and I am looking at using System.Web.Security.SqlRoleProvider to implement this.
My problem is that each client will want to be able to configure who can and cannot perform actions in the system and no two clients will want the same, so creating basic
Admin, User, Manager roles to cover all won't suffice.
What I am proposing to do for each screen is create roles as follows
Screen1Create, Screen1Update, Screen1Delete, Screen1Read
Screen2Create, Screen2Update, Screen2Delete, Screen2Read
and so on.
I would then allow the client to select the roles per user, which would be stored in a cookie when the user logs in.
I could then read the cookie and use user.isinrole to check if each method can be called by the current user.
I realise there is a size constraint with cookies that I need to be aware of. Apart form that, does this sound feasable, is there as better way to do it?
Many thanks for any input.
Really if you want to program this all yourself to the cookie level you're risking opening security holes. The way to do this is with forms authentication combined with role based authorization. Asp.net will give the user a tamperproof cookie.
If you implement roles you can then easily mark methods:
[PrincipalPermission(SecurityAction.Demand, Role="Screen1Create")]
or use code to see if someone is in a particular role.
Lots of info:
http://weblogs.asp.net/scottgu/archive/2006/02/24/ASP.NET-2.0-Membership_2C00_-Roles_2C00_-Forms-Authentication_2C00_-and-Security-Resources-.aspx
Remember that cookies are user-supplied inputs, so if you're going to store the privileges of users in cookies, you must use a keyed hash function (such as HMAC-SHA256) to make sure that users do not grant themselves additional permissions.
Or, if you store all the permissions in your database, it'll be persistent across client computers and you won't need to validate its integrity every time you wish to use it.