Is there a best practice for using claims for right-management?
I am using the new .net 4.5 and the new claim classes.
Currently I do something like that:
new ClaimsIdentity(new List<Claim>
{
new Claim("Username", user.UserName),
new Claim("UserNumber", user.UserNumber.ToString()),
new Claim("Creation_Right", ""),
new Claim("Edit_Right", "")
}
I add the right-claims without a value.
Later I check for the presence of a right. There is no need for a value (like true/false) - if it is present, its implicit 'true'.
Is there a better way to do that?
Perhaps. It looks like what you're doing is merging authentication and authorization together, making an access policy decision at the moment of authentication.
You also have the option of separating your authorization component away from your authentication component. Claims represent a set of information about a user that can be used to make an authorization decision. That is, your autheNtication step produces a set of claims, and whenever your user tries to access something, those claims are fed to the authoriZation component which renders a decision.
This provides some flexibility in that your authorization policy can change and evolve independent of your claims issuance system. For example, you might issue a role claim that identifies someone as an administrator, and you might also issue a authentication method claim that specifies how the user logged on, using a smart card or username and password for example. This gives you power in defining your access policy, you can require just an administrator role for access to some resources, while other more sensitive resources require administrator role AND use of a strong authentication mechanism. It also means you can switch between multiple different access policies depending on context. Your online whiskey store might use an ageOver21 claim on the US, but the Canadian version of your site requires over18 or over19 claims instead. Separating your authZ from your authN allows for this kind of flexibility.
Related
Due to the nature of our application we can have users coming in via a wide number of auth providers, several of them using OAuth 1.0 (specifically, LTI). Rather than always creating a new user account whenever we don't recognize a login and then having to deal with complex identity merges later, we want to invite apparently new users to identify themselves via OpenID (Google and Microsoft primarily since that covers most of our users.) We could ask them for their U/P, except we don't do U/P - we have always preferred to only support login via 3rd party identity providers and don't really want to change that.
So the scenario would be that our custom authentication scheme (LTI/OAuth1.0) receives the 3rd party claims, determines that these claims are new to our system, and then forwards a challenge to our default auth scheme. Upon completion of that scheme (either successful auth or the user declining (i.e. NoResult)) we would ideally return to the original scheme to complete either creating a new user using the provided claims or adding an additional login to the existing user. Once all of that was complete, the final AuthenticationTicket would be returned and the request would proceed normally as authenticated.
I may be thinking about this all wrong, and if so I would be glad to be guided in a better direction. But the basic business requirement is that I don't want to create a new user prior to giving incoming individuals the opportunity to identify themselves as existing users via another login method.
Target environment is ASP.NET Core 2.0 or 2.1.
The ASP.NET Core file -> new project template (when you pick 3rd party auth) does something similar when you choose to login from a 3rd party provider. It stores the 3rd party claims in a cookie (signed) and hands you to the registration page. Once you submit the form, it grabs the claims from this cookie together with the registration details, creates the user in the database, nukes this temporary cookie, and issues the real auth cookie that everything else looks to. To mitigate replay attacks, this intermediate cookie is only a session cookie and expires after a short time -- 5 minutes, I think. You're definitely on the right track.
I am trying to secure asp.net web-api 2.0 with Windows Identity Foundation 2. The choice I have to make is between role based authorization and claims based authorization. As a practice, I added a users in DbInitializer and assigned him two roles (Admin and Manager). When I log in with that user, I see that ClaimsPrincipal in debug mode, it already has those roles (Admin and Manager) associated as claims. So here are the questions:
If roles are also treated as claims, what is the difference b/w roles and claims then?
If I keep away from roles, how can I use claims to protect web api controllers and associated action methods. Like, I have an orders controller containing CRUD methods. I want one user (say a manager) to have access to Create and Get method and the second user (an admin) to have access to all those methods.
How would I do that? with role based system, I would simply decorate the action methods with appropriate Authorize(Role = "Admin") attribute. How would I manage the claims itself? do I need to add them in database and grant/revoke those claims to different users through my application?
In principal there is no massive difference between Role and a Claim. I've been all hooked up for Claims-based authorisation, done a lot of research and a few test projects. And at the end of the day it all down to you to decide which one is to use.
As you said, roles are added as type of claims. So in delivery terms it makes no difference. But MVC/WebApi already have built-in infrastructure to handle roles and deny if user does not have the required role. So you won't have to do much yourself.
But you'll have to come up with a bunch of attributes on controllers/actions and make sure all of them exist in DB, so users can be assigned to them.
However I found that you can have too many roles and they become too much of a burden to maintain. Also you can't have too many roles assigned to your user - their authentication cookie will become massive and eventually will have to be unable to login due to cookie size limitation in browsers (4K per cookie, 16K for all HTTP headers).
With claims you can be more flexible. You can have many different types of claims (we have a bit less than one per controller) and a few claim values (Read, Create, Edit, Delete). With a descent sized application (we have above 100) you'll have to have a LOT of roles (4 per controller) to model this level of permission control. With claims we have an enum for claim types (Person, Product, Order) and enum for claim values (Create, Read, Edit, Delete). And in cookie you can set integers as a claim type and claim value - that saves a lot of space on authentication cookie.
But with claims you'll have to code the authentication mechanisms yourself.
I've been playing with this concept here and this is authentication filter for MVC, but WebApi filter will look very similar. Now results of this prototype are in production and working very well.
Overall, the answer to your question is "it depends". Mostly on how granular the authentication have to be and how big is the application.
We are building an ASP.NET MCV 3 application from scratch running on Windows Azure. About Authentication and Authorization layer we are thinking to use the Access Control Service. I went through some articles about ACS where I got the basic idea but I still have some doubts on it.
My understanding is that using the ACS we outsource the Authentication process to one or more Identity Providers (IP), basically we trust another system (i.e. Microsoft Live ID) to authenticate our users.
The basic process is very straightforward: at authentication stage we redirect (ACS does it) the user to one of our “trusted” IPs, that will redirect the user (with a valid token) to the ACS and eventually to our application.
Here comes a number of questions:
Since we don’t want that all the users with a Live ID account can access to our application, I presume there should be another process to validate that user and checking if he is registered in our application. The question is where? In the ACS or in our application?
I have an idea about this but I don’t know if it’s the right way to do it:
At registration stage, the system (our web app.) asks the user which IP (i.e. Live ID, Google, Facebook, and our app.) he wants to use to authenticate himself in the application. Then the user goes through the authentication process on the IP system and when he comes back, we store his username (IP username) in our DB.
So, next time, at authentication stage we can check if that user is registered in our system.
If the above theory is correct, that means in our app. we need to build our membership provider to store usernames coming from IPs and users that chose our app. as IP.
Am I correct? What is the best practice to design the above process?
Now let’s talk about Authorization and “Roles”. How does it work with ACS? Does ACS manage multiple roles per user?
Again my understanding is that with ACS you can create a number of “Rule groups” related to the IP and not to a single user. If this is correct, how do we manage users in role in our application? Let’s say, for example, that we have multiple roles and our users can be associated to those roles, can we use ASC to manage it?
So the final questions are: Does ACS itself cover the whole Authentication and Authorization process? Do we still need to use the .net Membership Provider? What's the best practice in order to cover our requirements?
For the part of the question about the registration stage, the best thing to use to identify users is the NameIdentifier claim type
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
This should be unique for each identity provider and also fixed. If you use the email address claim, it could change for the same user. Technically it could be possible for two identity providers to use the same NameIdentifier (none of the out-of-the-box ones with ACS do) so you could combine the NameIdentifier claim with the IdentityProvider claim type
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider
to guarantee uniqueness.
For the part about role, I would say using ACS to issue role claims from generic identity like Google would be quite hard to manage using the claim transformation rules in ACS on per user basis. You would have to add a rule for each registered user - probably not feasible. I think the ACS rule groups are more suited to transformation of role claims (e.g. issued by a federated ADFS). Your idea to do it in your application is a better one IMHO. In code, the place to do this using WIF is in a custom ClaimsAuthenticationManager. You override its Authenticate method and based on the NameIdentifier claim from the incoming principle, you look up in your membership datastore and create a new IClaimsPrinciple based on the roles that are in your membership DB (i.e. you add a role claim for each role the user is in).
You then make your authorization decision in a custom ClaimsAuthorizationManager. There are some good samples and info on this around on the web. You can start at
http://msdn.microsoft.com/en-us/library/ee748497.aspx
The user validation process is done with claims.
After you set up an IP with ACS, when users authenticate, ACS will get claims about the authenticated user from the IP. You need to configure rules in ACS to say which claims you want forwarded on to your application. You can also tranlate claims into different types, to normalize the incoming claim set to what your application expects
If you want to implement your role based access with ACS, you can. In this case a role just another claim ACS will issue, and you'll implement your application to give user privileges based on the role claim it receives from ACS.
You can configure ACS rules that map certain IP input claims to role output claims. ACS also has a management service that can change these rules so you can implement a user registration process.
Individual claim rules in ACS relate to identity providers that issue the claim, but rule groups don't. Rule groups associate to RPs (your applications). A rule group is simply a group of claims transformation rules that tell ACS: "for this application, apply this rule group policy when you issue the token".
The ACS docs have lots to say about ACS claim rules configuration, both through the web portal and through the management service::
https://msdn.microsoft.com/library/azure/hh147631.aspx
Expanded response:
Let's say you're using ACS to authenticate to an ASP.NET app that's using WIF. You would configure ACS to issue a Role claim of "Manager" for the google user with email "jdoe#gmail.com".
Now in your ASP.NET app, WIF will see this role claim and it will allow you to control access using either HttpContext.Current.User.IsInRole("Manager"), or the web.config equivalent.
You can manage these ACS rules manually using the web UI, or you can implement a registration process that adds such rules to ACS programatically using the ACS management service. There are some ACS management service samples available at acs.codeplex.com.
Also, the identity developer training kit has some examples on WIF role based access:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=14347
Are there Custom ASP.NET Membership Providers for sale with added security?
For example, the ability to have multiple Questions/Answers that are randomly presented for Password reset, set number of login attempts, force password resets every 30 days, prevent duplicate passwords for new password for a certain period of time, etc
I've recently updated my custom provider with some of your requested features. Unfortunately it's not exactly for sale, but I did want to tell you that it wouldn't be terribly difficult to do on your own.
The multiple question/answer feature and the force reset (password expiration) actually can be implemented using any provider because they're not directly enforced by the provider. To enable Password Resets you could simply define a constant in your appSettings, i.e. "PasswordLifetimeInDays". Then in your Login page simply override the Authenticate method and inspected the LastPasswordChange property of the MembershipUser. If their password has expired then redirect them to a ChangePassword page, otherwise log them in. Check out this article for a walk through of implementing this feature.
The pre-generated question scenario is also something that doesn't really fit in as provider functionality. Although, a third party solution could contain this mechanism in a separate API I suppose.
The SqlMembershipProvider already provides a way to set the number of login attempts via the MaxInvalidPasswordAttempts attribute.
Really, the duplicate passwords functionality is the only piece that truly belongs in the provider implementation as it requires an additional table to track the password history.
Let me know if you ever decide to implement this stuff on your own and I could offer some more guidance.
I'm working on a web application that uses the ASP.NET 2.0 Membership and Roles providers with Forms Authentication. There are various roles in the system. I need to have a user role that is essentially a super-user that can "login" as any user account (in effect impersonating the user).
Does anyone know if this is possible using the providers? Any ideas?
One approach I was thinking of was to logout the super-user and sign them in as the desired user with
FormsAuthentication.SetAuthCookie(username, false);
And adding a variable to their Session to flag them as a super-user. I think this would work, but I was just wondering if there's a smarter way to do it without directly using the Session object?
Asp.net approach doesn't support the concept, so you are right on trying to find an alternate way.
Something that you can do is add the IsSuperUser info to the authentication ticket UserData property.
Why don't you have a SuperUser role that can do anything? Then the user can be just part of that role.
If what you really need to have is an ability for an administrator to impersonate someone else, I don't know what is the additional flag for? If it marks the currently logged in user giving him super powers the same will be achieved by setting up a role. If you, however, need to just impersonate someone else (e.g. this is help desk and you need to see exactly the same as the end user sees) - I would just check the credentials normally, then check if a superuser is logging in and who they want to impersonate and based on that just authenticate the logging in user as the one that he's willing to impersonate.
I hope what I wrote makes sense...
Here is what I would do. Sorry no graphics, on ipad here in bed...
1) use claims based architecture. Its easy to implement, see my project.
2) essentially impersonated user will have a second identity on the claims principal object, but will have different realm (realm may be wrong word, the string you use to create the identity)
3) You can construct the identity of the impersonated user and manually build their claims.... They should get written to the token immediately. I would look at a generic Claims Transformer class to do this.
4) You may need to adjust the way the site behaves, based on the presence of a impersonated identity, but thats the fun part.
Working WIF implementation
https://github.com/wcpro/scaffr-generated