I m using Angularjs project and using Asp.net identity custom storage provider with Enterprise library for token authentication.
Implemented custom userstore to create an account.
[Authorize] attribute works well after logged in. i want to restrict the method for particular user.
So tried to implement [Authorize(Roles="Admin,User")].
Here one user can have two roles in practical. But as per the system, when user login, we restrict the user to select the particular role.
So, after validated by asp.net identity, user should select any one of the role.
Here my need is,
I want to maintain the role which he selected (we consider this concept like impersonate user, but not exactly).
Or,
Need to implement in the Authorize attribute itself.
I've seen some of the examples like we can add claim to identity.
But I can add custom claims only inside the method,
GenerateUserIdentityAsync
in my case I need to add claim after log in validated. I've gone through some example and implemented like following.
ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim(ClaimTypes.Role, "Test"));
After added claim, when I try to get the claim to check the logged in user role,
List<Claim> claim = claims.Where(c => c.Type == ClaimTypes.Role).ToList();
I didn't get the Role "Test".
Here my bad luck is, in claims, I've all the roles of the user except role = test
How to authorize the user role or maintain logged in here..
I see at least three solutions for your problem:
Use a claim transformation to filter the role claims, to match a role the user choose. You can use a claim transformation middleware or you can filter the claims during login (be aware, that you do not know the user roles BEFORE login, and afterwards filtering might be too late). PRO Does not necessarily need session state; CON User can not choose during runtime.
Store the role in the session and authenticate against that role. Make sure, that you check against the role claims, when the user chooses his role. PRO User might change role without re-sign-in. CON Needs session state (Might be an issue in farm environments).
Don't do it at all and I'm totally serious about that. Provide your user a clean interface, that makes him know, what role he has and use areas and other technics to separate the concerns.
Related
I'm having some issues with getting the currently signed-in user's username from Azure b2c to my Blazor web app. Essentially, I want to make a username account where a username is the User Principal Name. I was originally using an email sign-up policy with a display name as the username. However, b2c doesn't enforce display names to be unique, so there's an inherent issue with that. No claim comes back with a username in it, so I have no way in my Blazor app to keep tabs on who is signed in or display their username. There are a few options I can do, and I'm curious which one is the easiest to implement/how to implement it, cause I've been ripping my hair out with this the past few hours.
On b2c account creation, take User Principal Name and also make it the display name
Have the user principal name be sent via claims (Not sure how to do this)
Do Email sign up with Display Names, but somehow enforce b2c to ensure display names are unique
Some other way to have a unique display name for users from b2c
Thanks in advance!
You need to use custom policies: https://aka.ms/ief. Username is not returned in the token with User Flows.
Using custom policies, you can sign up the user using username, and return their username (signInNames.username attribute, shown as userPrincipalName in the Azure Portal) into the token.
You can quick deploy custom policies using my tool here. And quick deploy the username sample using this page with the sample folder name username-signup-or-signin.
If you need any additional claim you need to enter in your Azure AD BC tenant and configure the Application Claims from your User Flow, in the following example the User flow is called B2C_1_signupsignin:
The above example, as you can see, lists all the other available claims, because dome claims are always returned, as the User Name.
You can configure the claim (mode) used to login in the Identity Provider:
Than the claims you receive are the following:
But as you can see there isn't any userPrincipalName or signinNames.
This is a known issue in Azure AD B2C and including this claims from the user flow manifest doesn't work.
The only solution I've found is to upload your custom policy and add a:
<OutputClaim ClaimTypeReferenceId = "signInName" />
but this works only for local accounts.
If you want to add signin names also for external (social) accounts you need to map them, like:
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="upn" />
look at the base source XML here:
https://github.com/azure-ad-b2c/samples/tree/master/policies/sign-up-with-social-and-local-account
I'm trying to solve the following problems:
The user can have just one role at time.
He can change his current role inside application, without need to logout. For example, he wants to change from "Admin" to "Annalist".
I'm using this example as my authorization approach.
In there I can set multiple roles to user, but once he is logged, he has all roles at same time.
Here is the way I handled this:
The user has only one "main" role.
The user has a list of other possible roles.
When logged in, only main role is active in the claims.
When switching role, another token is created for the user.
I've been looking around how to use roles in SPA, and the basic project that Visual Studio (2019) creates is quite fine, however [Authorize(Roles="")] does not work properly, so I can use Authorize attribute to check if user is actually logged in but not the role.
My approach now in controllers is to get the user and use IsInRole(), but this seems like a big overhead since I should have his token already which should include the role.
ClaimsPrincipal currentUser = this.User;
var currentUserId = currentUser.FindFirst(ClaimTypes.NameIdentifier).Value;
User user = await _userManager.FindByIdAsync(currentUserId);
if (await _userManager.IsInRoleAsync(user, "Admin"))
...
You should stick to the original [Authorize(Roles="")] attribute.
As stated here:Store/assign roles of authenticated users
Roles are added to the IPrincipal of the HttpContext. You can create a GenericPrincipal, parse the list of roles in the constructor and set it as HttpContext.User. The GenericPrincipal will then be accessible through User.IsInRole("role") or the [Authorize(Roles="role")] attribute
Depending on your authentication scheme, you need to create a GenericPrincipal and add the roles there for all requests so that they can be accessed.
Example for FormsAuthentication is in the mentioned answer.
This question already has an answer here:
Change from Roles authorization to Claims authorization
(1 answer)
Closed 6 years ago.
In our system we have a way to setup users with permissions. They create a group name, for example, Admin and then assign all the permissions for the tasks they would like to do.
For example, they can add AddCompany, ViewCompany, DeleteCompany, EditCompany
This makes it very easy to make different permissions groups and we can control security very easily.
Am i right in thinking that in this instance the group name = Role and each permission is a claim?
Roles-based authorization is used to group users into groups (roles) and then set permissions on the role rather than on individual users.
E.g: In your case you can create Admin role and provide permission to do "AddCompany, ViewCompany, DeleteCompany, EditCompany" tasks.
In this case easier to manage large set of users through small set of roles. This is the most commonly used model for authentication.
Claims-based authorization provides additional layers of abstraction on your authorization strategy. Further, claims are a method of providing information about an user rather than group of users. You create authorization policies that are used to generate a claim-set based on the authentication evidence presented by the user. Then the user presents claims to the application in order to access resources.
A claim is a statement that one subject makes about itself or another
subject. The statement can be about a name, identity, key, group,
privilege, or capability, for example. Claims are issued by a
provider, and they are given one or more values and then packaged in
security tokens that are issued by an issuer, commonly known as a
security token service (STS)
Resources : http://msdn.microsoft.com/en-gb/library/ff649821.aspx
http://msdn.microsoft.com/en-gb/library/ff649821.aspx
http://msdn.microsoft.com/en-gb/library/ff359101.aspx
Hope this helps.
Roles are claims, but not all claims are roles.
In a claims-based authorization system, you may use roles as permissions, but you may use something else as well. On my current project, we have a many to many mapping from roles to permissions.
I am working on an ASP.NET MVC5 web app that has the following relevant properties:
Uses MVC5.1, Identity 2.0, not restricted to any legacy stuff - can use newest everything.
A user belongs to at least one organization.
Each organization has at least one user that is an organization admin.
The organization admin can allow users specific rights, such as becoming another organization admin.
From what I have understood, a good way to handle this would be to use claims.
In addition to the default claims, a user could then typically have the following claims:
Organization: {some guid}
Organization-Admin: {same guid as above}
Organization-Publisher: {same guid again}
There could potentially be super-admins, or even super-users, with claims giving them access to different roles in multiple organizations.
Now, lets imagine I am user admin logged on to my administration panel, and I want to grant user user the Organization-Publisher claim for an organization that I have the Organization-Admin claim for.
For simplicity, I have a model object that would look something like this:
public class GrantRightModel
{
public string OrganizationId { get; set; }
public string UserId { get; set; }
public string Right { get; set; }
}
and for the purposes of this example, we get the following values from our admin user:
OrganizationId: The GUID of an organization that admin has an Organization-Admin claim for.
UserId: user
Right: Organization-Publisher
There are a number of things that have evaded me about this way of doing things. Lets say we have an OrgAdmin controller with a GrantRight action;
Will the controller action need to check that the currently logged in user (found using for instance ClaimsPrincipal.Current) has the Organizaton-Admin claim for GrantRightModel.OrganizationId "manually", or are there clever auth attributes for this kind of thing?
What is the correct way in code to add the Organization-Publisher: {guid} claim to user? My controller will get a UserManager as necessary by dependency injection.
If user is signed in to the application when this happens, is there a way to have him automatically have the correct claim starting with his next request? I've seen mentioned ways to do this that would cause the user to be logged out, so that he would log in again and start a fresh session with his new claims. I see why that is the way it is, but given that the user could be working on something that takes a lot of time, it might not be popular to just have him logged out when he tries to submit his work.
There is a bit of information on this on the web, but my google-fu has failed me in finding the one that shows me how to beat these three points.
Anyone?
Thanks!
Regardins your questions.
Will the controller action need to check that the currently logged in user (found using for instance ClaimsPrincipal.Current) has the Organizaton-Admin claim for GrantRightModel.OrganizationId "manually", or are there clever auth attributes for this kind of thing?
No. The Authorize attribute takes an optional list of roles that are checked upon authorization. If one of role claims points to that role, used is authorized with no custom code involved.
What is the correct way in code to add the Organization-Publisher: {guid} claim to user? My controller will get a UserManager as necessary by dependency injection.
You create the ClaimsIdentity with proper claims and then ask the authorization manager to sign in used with the identity. The identity is typically then persisted in a cookie together with claims.
If user is signed in to the application when this happens, is there a way to have him automatically have the correct claim starting with his next request? I've seen mentioned ways to do this that would cause the user to be logged out, so that he would log in again and start a fresh session with his new claims. I see why that is the way it is, but given that the user could be working on something that takes a lot of time, it might not be popular to just have him logged out when he tries to submit his work.
I've read it twice and don't quite get it. When you issue a cookie, the cookie is responsible for retaining the authenticated session. Claims are then rebuilt early in each request pipeline based on the cookie. Numerous requests can be then issued by the user and he is still "logged in" as long as the cookie is not invalidated or the auth token stored in the cookie expires.