Custom role based authorization from an existing database - c#

Currently, I am developing an web application in ASP.net and till now i have done authenticating the user after successful login using Identity in ASP.Net. Now i want to authorize the user based on the different roles available in the database. I have a database with 3 tables namely Users, Roles and UserRoles. A user can have more than 1 role.
In this case, how can i implement role based authorization in my project.I have done custom authentication using Identity and removed Entity from my project.
public void ConfigureAuth(IAppBuilder app)
{
// Configure the custom user manager and custom signin manager to use a single instance per
request
app.CreatePerOwinContext<CustomUserManager>(CustomUserManager.Create);
app.CreatePerOwinContext<CustomSignInManager>(CustomSignInManager.Create);
}
With this, simple[Authorize] attribute is working fine for me. How can i create something like [Authorize(Roles="Customer")]? Should i use something like IRole for this or just overriding Authorize Attribute method is enough? Is both same or different? Can anyone help me to solve this problem?

Related

IdentityServer4 + Asp Identity + EF Configure two UsersSet/Providers

Having trouble finding a good lead on this. I have a aspnetcore app with identityserver4 configured to use asp identity with a sql database.
There is a business requirement that all non AD users are stored in this asp identity database.
All AD users are defined on Azure. I can authenticate them with LDAP and receive their data.
The issue comes after authentication. Whenever asp identity tries to call:
var user = await UserManager.FindByNameAsync(userName);
With an AD user, it fails because the user does not exist. This is because it is using EF to query the asp identity database, where those users are not defined.
private DbSet<TUser> UsersSet { get { return Context.Set<TUser>(); } }
I can not store any of the AD information in the asp identity database (business requirement). I am trying to find a way to get the user store to look both at the asp identity tables, as well as Azure (via LDAP).
My current method for getting the AD users when doing initial auth is here:
await GetADUser(queryParams),
It uses LDAP to authenticate and grab the user object.
One additional requirement is that I can not use an external login screen, the login must all be done from the same company facing login UI. AKA no external providers.
As per #mxmissile, abstracting the UserManager out was the correct call. Then you can also abstract out other managers as needed for special functionality. This is in fact the only class in the inheritance layer for this part of the code that is virtual.
There are built in functions that let you register your custom managers:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddUserManager<ApplicationUserManager<IdentityUser>>()
.AddSignInManager<ApplicationSignInManager<IdentityUser>>()
Hopefully this is a little help to any others that have a similar question. I ended up just overriding a couple of the functions from the base user manager and just calling the base method for anything that did not need my new logic. By default it looks like ASP Identity does not try to look up users by email - just fyi.

ASP.NET Web API with Bearer authentication. How to get/add/update unique user data?

Currently I am about to develop my first REST web API!
I'm currently designing how the system will work yet I am a little confused how things are going to work.
Primarily, a mobile app will consume the Web API, but it must be secure!
For example I wouldn't want an un-authed request handled at all. (Apart from a user registering)
I have found that I can use SSL + Bearer tokens to achieve this user authentication. I am comfortable with this and have tested to see how this would work. And it's suitable.
The problem arises when I wish to retrieve the user details.
In my system a user would log in to the mobile app which would request the token from the server. If all is good, I can log the user into the app. Great! Now, I need to get the information stored about this user to present to them. i.e. name, email, reward points etc...
I am unfamiliar with how to add extra user data AND retrieve it with the Web API. I understand that the token can be used to uniquly identify a user. but how can I extend this data?
Currently I have not much more than a blank WebAPI project with the bearer token authentication implemented. Still using the Entity framework. How can I add more fields of data to a user record?
Furthermore, how can I update these records? For example, a user has gained some reward points, how can update the user data for this?
One final question, Is this suitable for retaining per user data? i.e. can I link other data to a userID or something similar?
Apologies for sounding over-curious, I am very new to MVC
The below code in the IdentityModel.cs would seem like the appropriate place to add user data, but how do I add to this? for example adding a field for reward points? then how would I update upon it?
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
How I would do it:
Create ActionFilter that would validate token, it would use your custom class that would leverage DI, it would obviously get the user ID as well
Now that you know that user is authenticated and you know the user ID just do your regular CRUD based on this user ID
Note: Remember to also validate the payload, since if I send you PUT: /user/887/points {points: 999} I could potentially gain unlimited points.
It's not necessary to use ASP .NET Identity for implementing security in your web API project.
If you use Identity you will have to stick on to "ApplicationUser" and Identity tables for user management where you won't be able to complete your requirement.
A solution is to handle user management with your own custom table and implement security using OWIN middleware classes available for .NET, ie, you need to write code for generating and validating tokens rather than using Identity.

How in ASP.NET MVC do I maintain info about whether a user is "logged in" throughout pages?

After they type in their password, should I keep a variable in server session storage like Session["loggedIn"] = true that I check when requests are made to pages that require a login, or is there a better/safer way this is traditionally done in ASP.NET?
No, do not keep this in a session variable. In fact, I would argue you should try not to use session for anything. Try to keep the HTTP communication as stateless as possible.
For authentication in ASP.NET MVC, you have 2 alternatives, but ultimately, the both end up working the same way: by writing an encrypted authentication cookie to the browser after you successfully log a user in.
The newer alternative was mentioned in a comment to the OP: Microsoft.AspNet.Identity. To use this, you should be using a newer version of ASP.NET MVC with the OWIN pipeline (though I am not sure if you have to). The older alternative is called Forms Authentication, and can be used with any version of MVC except version 6 (the new vNext / core 1.0 stuff) I believe.
When you have successfully integrated one of these 2 tools into your MVC application, after a user logs on, your Controllers will have a non-null User property of type IPrincipal. You can use this property to determine whether or not a user is authenticated:
// in a controller
bool isThereAUserLoggedIn = this.User != null && this.User.Identity.IsAuthenticated;
If you are using the newer Microsoft.AspNet.Identity, then this IPrincipal User property will be implemented as a ClaimsPrincipal with one or more ClaimsIdentitys. Forms Authentication does not do claims like this, so if you want claims, or social login, etc, use Microsoft.AspNet.Identity.
The way that this is traditionally done in ASP.NET and by my opinion also better and safer is by making use of the ASP.NET Identity package.
ASP.NET Identity handles all aspects around user accounts in a web application:
database for users, including roles and more
user registration and management, like register, email verification, log in, remember me option, forgot my password action and more.
user authentication & authorization
Just to make things more clear, authentication means that the user making the request is actually a valid application user and authorization means that the user has the authority to perform the requested action.
Practically, when a user logs in, Identity automatically keeps that information and makes it available in all controllers and views under User property. So you know at any time which user made the request. Identity also supplies each request with a cookie used for user authentication and authorization.
To check for user authentication you use the User.Identity.IsAuthenticated in a view and the Authorize attribute in a controller:
[Authorize]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users to request this page.
It is also very common to extend the functionality of your application to include roles for the users and user authorization. Identity creates a "Users" table, a "Roles" table and a many to many relationship between them. After assigning roles to your users you can authorize their requests by using User.Identity.IsInRole("YourRoleName") in a view and in a controller:
[Authorize("YourRoleName")]
public ActionResult Create( ... ){ ... }
The above use of the Authorize attribute will allow only to registered users having the "YourRoleName" role to request this page. In any case if Identity fails to authenticate or authorize the request will prompt to the log in page.
ASP.NET Identity is simple to use, it works and it is easy to extend the membership functionality of your application both by making use the many tools supplied with it and overriding its classes to give them a more specific or complex behaviour.
You will find infinite help on the web on how to use it or a step by step guide.

extend HttpContext.User.Identity in asp.net mvc

in my application i want to use the current logged in user details,
in HttpContext.User.Identity there are 'AuthenticationType', 'IsAuthenticated' and 'Name', I want some more details from database when user logged in to the system. Is there any way to extend this identity class?
As Daniel noted in his comment you're going to need to create your own implementation of IPrincipal. I'm going to assume that you're using MVC5. If so, then you're going to need to implement an authentication filter which will allow you to set the principal for the request. This authentication filter would go to the database, retrieve the fields you have added, and populate your IPrincipal implementation. Finally, you would need to globally register that filter in your FilterConfig.cs file in App_Start so that it will be applied to every controller action in the application without you having to type it over and over again.

ASP.NET MVC 4 : Authentication and Authorization:Intranet Application

I'm new to ASP.NET MVC world. I'm building an intranet web application. Authentication and authorization is defined in my case as below:
Authentication: If HttpRequest contains an Header with "USER_ID", user is authenticated.
Authorization: There is one in-house WCF Service, which returns list of roles user is entitled to taking USER_ID as input. I keep the roles required by my application in xml file. If user's required role is in svc response then, she is allowed to use the application.
I'm thinking of implementing it like below:
In Global.asax - > Application_AuthenticateRequest, I'll put code to check http Header. If its non_blank, I'll let user to go through this stage.
In OnAuthorization method of AuthorizeAttribute class, I'll put code to fetch role list and match it against required roles from xml file.
Is there any way that I can use existing authentication,authorization infrastructure?
I see code like this
[Authorize(Roles = "admin")]
public string Index() {
return "only admins!";
}
How can I link Roles property like above to some Xml or Table instead of hard coding?
Please help me to implement this logic in asp.net mvc application.
You should check Windows Identity Foundation (WIF), in particular ClaimsAuthorizationManager and ClaimsPrincipalPermissionAttribute. The later allow you to specify what operation and resource need to be secured, while in ClaimsAuthorizationManager you can check whether the current user can perform the operation on the resource, and that can be read from any source you desire.
For Authorization, I would either:
Create a GenericPrincipal in the global.asax AuthorizeRequest event handler with the appropriate roles, and assign it to both HttpContext.User and Thread.CurrentPrincipal.
Or (better), write a custom RoleProvider that gets the users roles from the xml file. If you configure such a RoleProvider, ASP.NET will assign a suitable RolePrincipal to both HttpContext.User and Thread.CurrentPrincipal.
You can then use the standard AuthorizeAttribute.

Categories

Resources