Skip to content

The good, the bad and the ugly of ASP.NET Identity

October 20, 2013

Ok, here we go again… and if you don’t know what I’m talking about, then see this post.

With Visual Studio 2013 and .NET 4.5.1 we have a new framework called ASP.NET Identity. ASP.NET Identity is yet another identity management framework from Microsoft (recall that we also had two prior frameworks from Microsoft: Membership and SimpleMembership).  Let’s take a look at the good and the bad aspects of this new framework.

TLDR; Click here to get to the ugly conclusion.

Good: Storage customization

One of the major complaints with the previous identity management frameworks was that it was either too cumbersome (with Membership) or too subtle (with SimpleMembership) to customize the storage. With this release, they’ve actually achieved a separation of the storage of the identity information (e.g. username, password, etc.) from the code that implements the security (e.g., password hashing, password validation, etc.). The way they’ve done this is by defining the account related data behind an interface, IUser and the storage operations behind another interface IUserStore. Here they are:

public interface IUser
{
   string Id { get; }
   string UserName { get; set; }
}

public interface IUserStore<TUser> : IDisposable where TUser : IUser
{
   Task CreateAsync(TUser user);
   Task DeleteAsync(TUser user);
   Task<TUser> FindByIdAsync(string userId);
   Task<TUser> FindByNameAsync(string userName);
   Task UpdateAsync(TUser user);
}

The idea is that you then implement these interfaces and this puts you in control of how the account data is actually stored. This also makes it easier for developers to customize the user account data. If you want more data associated with your user you can add it on your custom user class that implements this interface. This extra data would then be stored by your implementation of the IUserStore.

There are default implementations of these interfaces that use Entity Framework 6. When you choose “Individual User Accounts” in the new ASP.NET templates in Visual Studio 2013 you will get an IUser implementation in a class called ApplicationUser. Any custom data you’d want stored on your user accounts would be added to this class. Given EF’s support for POCOs, this extra data on the user account class will simply be mapped into the database with little effort on your part. See this post for an example.

For the class that implements IUserStore, there is a class from the ASP.NET Identity EF assembly called UserStore. It requires an EF DbContext, which is provided by another class generated in your project called ApplicationDbContext. There’s even less to code or customize on the ApplicationDbContext because its base already defined the DbSet for the user accounts (in its base class). The ApplicationDbContext class is primary there for you to control connection strings to indicate the database to actually use.

With this design it should be very straightforward and obvious for a developer using this framework what data is stored and how it is stored. In this sense, this new identity framework is a success and quells one of the long standing complaints about the previous membership systems.

Sidebar – Identity vs Authentication

Keep in mind that (as always) the provider model is simply about the storage and management of account related data. In a running application, once the user’s password has been validated (against the persisted password) then the user is logged into the application (typically) with some sort of cookie based mechanism like ASP.NET’s Forms authentication, WIF’s Session Authentication Module, or now in Visual Studio 2013 OWIN cookie middleware. Far too often the line between these two different subsystems (storage vs. authentication) is blurred. See this post for more context.

Good: Asynchronous support

Another nice addition I should point out is that most (if not all) of the APIs in the new ASP.NET Identity system are asynchronous. This is a nice addition to the API, and almost assumed these days. I give kudos more to the EF team than anyone else since EF6 now supports asynchronous APIs.

Good: Decoupled

So this new design segregates the storage of identity information from the rest of the security code. Well, what’s left? In theory it’s all the hard and complicated stuff related to identity management and the idea is that Microsoft will implement it for us. This is achieved via the UserManager class:

public class UserManager<TUser> : IDisposable where TUser : IUser
{
   public UserManager(IUserStore<TUser> store);

   public ClaimsIdentityFactory<TUser> ClaimsIdentityFactory { get; set; }
   public IPasswordHasher PasswordHasher { get; set; }
   public IIdentityValidator<string> PasswordValidator { get; set; }
   protected IUserStore<TUser> Store { get; }
   public virtual bool SupportsUserClaim { get; }
   public virtual bool SupportsUserLogin { get; }
   public virtual bool SupportsUserPassword { get; }
   public virtual bool SupportsUserRole { get; }
   public virtual bool SupportsUserSecurityStamp { get; }
   public IIdentityValidator<TUser> UserValidator { get; set; }

   public virtual Task<IdentityResult> AddClaimAsync(string userId, Claim claim);4
   public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
   public virtual Task<IdentityResult> AddPasswordAsync(string userId, string password);
   public virtual Task<IdentityResult> AddToRoleAsync(string userId, string role);
   public virtual Task<IdentityResult> ChangePasswordAsync(string userId, string currentPassword, string newPassword);
   public virtual Task<IdentityResult> CreateAsync(TUser user);
   public virtual Task<IdentityResult> CreateAsync(TUser user, string password);
   public virtual Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType);
   public virtual Task<TUser> FindAsync(UserLoginInfo login);
   public virtual Task<TUser> FindAsync(string userName, string password);
   public virtual Task<TUser> FindByIdAsync(string userId);
   public virtual Task<TUser> FindByNameAsync(string userName);
   public virtual Task<Collections.Generic.IList<Claim>> GetClaimsAsync(string userId);
   public virtual Task<Collections.Generic.IList<UserLoginInfo>> GetLoginsAsync(string userId);
   public virtual Task<Collections.Generic.IList<string>> GetRolesAsync(string userId);
   public virtual Task<bool> HasPasswordAsync(string userId);
   public virtual Task<bool> IsInRoleAsync(string userId, string role);
   public virtual Task<IdentityResult> RemoveClaimAsync(string userId, Claim claim);
   public virtual Task<IdentityResult> RemoveFromRoleAsync(string userId, string role);
   public virtual Task<IdentityResult> RemoveLoginAsync(string userId, UserLoginInfo login);
   public virtual Task<IdentityResult> RemovePasswordAsync(string userId);
   public virtual Task<IdentityResult> UpdateAsync(TUser user);
   public virtual Task<IdentityResult> UpdateSecurityStampAsync(string userId);
}

Notice the constructor accepts the IUserStore. An application developer would instantiate the UserManger passing in their user store. The developer would then code to the UserManager’s APIs to do all of the account related functions, such as creating an account, validating a password, changing the password, etc. The APIs, as you can tell from the names, are fairly self-explanatory. This pattern is apparent in any of the new ASP.NET templates in Visual Studio 2013 when you choose “Individual user Accounts” for the authentication configuration.

Also, notice how most of the APIs are virtual; if the developer wishes to customize any of the built-in behavior then they would simply override the appropriate method. Hopefully the need for such a thing is rare.

Bad: Where are the claims?

One of the selling points about the new identity system is that it supports claims. Here’s an excerpt from the announcement:

“ASP.NET Identity supports claims-based authentication, where the user’s identity is represented as a set of claims.”

“Claims-based authentication” is a misnomer, and is akin to saying “role-based authentication”. I think what they mean is that the new identity system can model user identities with claims. They get around to that sentiment in the latter half of the sentence, but their terminology misuse confuses the point. For clarity, the new identity system uses password-based authentication (just like the prior systems). There’s also federation support, but, strictly speaking, it’s not a feature of the new ASP.NET Identity system.

Ok, back to claims: Notice on the IUser definition there are no claims (also notice that a Claim doesn’t appear anywhere in the code for the new ASP.NET templates in VS2013). Ok, so where are they? Well, I think Microsoft is still not confident enough in developers to understand how claims work so they made this piece optional. Depending on your perspective maybe this is good and maybe this is bad. I think it’s bad.

Anyway, to model claims there is another interface called IUserClaimsStore:

public interface IUserClaimStore<TUser> : IUserStore<TUser>, IDisposable where TUser : IUser
{
   Task AddClaimAsync(TUser user, Claim claim);
   Task<System.Collections.Generic.IList<Claim>> GetClaimsAsync(TUser user);
   Task RemoveClaimAsync(TUser user, Claim claim);
}

The approach here is that your user store would then also implement this API to be able to associate claims with the user account.

I find this approach distasteful. If you are building a custom user store, then you now have to implement an additional store interface to support claims. It’d be much easier and obvious if the user definition had a claims collection property.

Also, to confuse the situation, you now have two ways of modeling additional identity data on your user: one as custom properties on the user class and another as claims in the claims store. Which leads me to the next issue.

Bad: Once authenticated, custom user data is not in the ClaimsIdentity claims collection

As I mentioned above, a driving feature in the design of ASP.NET Identity was that it’s easy to store custom properties on the user. The only problem is that if they’re custom, then once the user logs into your application these properties won’t automatically be made available in the claims on the ClaimsIdentity (which is the standard class in .NET 4.5 for modeling an identity, is what represents the logged in user in any .NET application, and is what people mean when they say claims-aware). The reason that custom properties on your user class won’t be part of the ClaimsIdentity’s Claims collection is that the built-in code only knows about the IClaimsStore and not your custom properties.

This leads us to the next extensibility point, which is the ClaimsIdentityFactory on the UserManager. This is the class that maps the data on the user class to a ClaimsIdentity (presumably when the user logs in). If you need your custom properties to your user class as part of the ClaimsIdentity then you need to implement a custom ClaimsIdentityFactory to do this mapping.

This makes me wonder if it makes sense to add custom identity data to the user class and instead store it in the claims store. Also, this makes me wonder if it makes sense to add custom non-identity data to the user class at all and instead store it elsewhere in the database. I don’t know the right answer.

Bad: Wait, there’s also an IUserRoleStore?

Yep, to complicate things there’s also an interface to associate roles with users called IUserRoleStore:

public interface IUserRoleStore<TUser> : IUserStore<TUser>, IDisposable where TUser : IUser
{
   Task AddToRoleAsync(TUser user, string role);
   Task<System.Collections.Generic.IList<string>> GetRolesAsync(TUser user);
   Task<bool> IsInRoleAsync(TUser user, string role);
   Task RemoveFromRoleAsync(TUser user, string role);
}

This interface, like IUserClaimStore, is optional and if you want explicit role support you will need to implement this on your user store.

For those who are already familiar with claims, you know full well that claims are a superset of roles and this it’s unnecessary to treat roles special and separate from claims. That also make this IUserRoleStore interface superfluous. Microsoft knows this as well, but for some reason they continue to feel that there’s demand for roles separate from claims.

For what it’s worth, the previously mentioned ClaimsIdentityFactory will read from both the claim store and the role store and will map them both to the ClaimsIdentity Claim collection.

But this also leads to the potential (rather, likely) confusion as to where should a role be kept. Should you store roles in the claims store or in the role store? Well, you get to decide and ensure everyone else on your team knows the right answer, especially if you have your own code querying those stores directly.

Neutral (but actually Bad): Passwords are optional

Notice the lack of a password (or rather hashed password) on the user account? That’s right, passwords are optional. Just like the claims and role stores, there’s an optional store if your application needs to persist passwords (actually, hashed passwords) for the user called IUserPasswordStore:

public interface IUserPasswordStore<TUser> : IUserStore<TUser>, IDisposable where TUser : IUser
{
   Task<string> GetPasswordHashAsync(TUser user);
   Task<bool> HasPasswordAsync(TUser user);
   Task SetPasswordHashAsync(TUser user, string passwordHash);
}

So if you want your users to be able to use passwords to login then your user store must also implement this interface.

I’m on the fence about this – I can imagine scenarios where users would only login with an external identity provider and thus never have a local password. But if this is your scenario, I don’t see much point in the ASP.NET Identity system. You have innumerable ways to store data anyway you want to without tying yourself to the ASP.NET Identity system APIs.

So I guess this really is bad, because why else would you be using this API.

Good (but actually Bad): Password hashing is pluggable

I’ve been complaining for a long time that the default password hashing (PBKDF2) from Microsoft only performs 1000 iterations. With the UserManager API we can now plug in a custom implementation (via IPasswordHasher) and do more iterations as recommended by OWASP and this is good.

Unfortunately, this means you have to write security code and this is bad. I thought this was the whole point of using a security framework; someone else who supposedly knows what they’re doing is has already has done all the complex security work. This should have been implemented by Microsoft with an iteration count property instead.

Good: External logins

The new ASP.NET Identity system allows you to map an external login provider to a local user account. This feature was introduced with SimpleMembership and is similarly available with this new framework. To store this info, though, there’s yet another store interface called IUserLoginStore which relies upon a class called UserLoginInfo which maintains the provider name and the identifier for the user:

public interface IUserLoginStore<TUser> : IUserStore<TUser>, IDisposable where TUser : IUser
{
   Task AddLoginAsync(TUser user, UserLoginInfo login);
   Task<TUser> FindAsync(UserLoginInfo login);
   Task<System.Collections.Generic.IList<UserLoginInfo>> GetLoginsAsync(TUser user);
   Task RemoveLoginAsync(TUser user, UserLoginInfo login);
}

public sealed class UserLoginInfo
{
   public UserLoginInfo(string loginProvider, string providerKey);

   public string LoginProvider { get; set; }
   public string ProviderKey { get; set; }
}

This is sounding like a broken record; if you want external login support, your user store must also implement this interface. Again, I feel like this additional interface is burdensome and it’d be simpler if the external logins were a collection on the user definition.

Bad: Queries

Notice there are no APIs for arbitrary queries. This means you’ll have to go around the interfaces to query your user data.

Bad: Back to leaky abstractions?

One of the complaints with the old membership system was the leaky abstractions. So many APIs might not be implemented and your application had to know which APIs it could and couldn’t invoke on the membership APIs. This meant you were forcing yourself to adhere to an interface contract without the benefit of the interface abstraction.

In the new system, I think it’s better designed, but it still feels like there’s a lot of leaky abstractions. You notice on the UserManager (beyond the simple user related APIs) there are APIs for managing claims, roles, passwords and external logins. These APIs only work if the user store implements the corresponding IUserClaimStore, IUserRoleStore, IUserPasswordStore, and IUserLoginStore. This seems like it’s the same problem as before, just in a different form.

I must admit, the story is slightly better with the new ASP.NET Identity; if an application wants to use these APIs, though, it can first query the UserManager and ask if it can use these APIs (via SupportsUserClaim, SupportsUserRole, SupportsUserPassword and SupportsUserLogin). Again this is better than before, but it still feels like a weak API design in that it’s trying to be too many things to too many people. If your application needs one of these features, it’s going to just use it. This then means any other user store you’d want to use must implement these same features.

It’d be much stronger of a design if the programming model had claims, passwords and external login support as properties on the user account class (and no roles*). If your application didn’t want to use them then it could ignore those APIs. This would simplify the design by eliminating all of these extra store interfaces and we’d be left with just the one user store. This design change would be better specifically for NoSql implementations (see below: Bad: Non-EF implementations).

* Specific support for roles is unnecessary given claims being a superset of roles, as previously mentioned. And if you really want a role specific API then just add an extension method that sits on top of the claims.

I suppose technically this design allows those aspects of the user to be stored separate from the user itself, but then this feels as if the framework is trying to be all things to all people. If I were designing a system where my user’s claims/roles needed to be loaded from a different system then I’d probably do that as a deliberate step in my authentication code (with something like a claims transformer, which is WIF’s pattern for modeling this type of operation).

Good: The default EF implementation does all of this for you

As mentioned earlier, there is a default implementation of the user store that uses EF 6. This implementation is called UserStore and it implements IUserStore, IUserLoginStore, IUserClaimStore, IUserRoleStore and IUserPasswordStore. This means it’s implementing all the store interfaces I droned on about earlier. This also means you are getting all of these features with little or no effort and the EF-specific implementation does many of the things I suggested: it defines claims, passwords, roles and external logins as part of the user class. I suppose my only complaint here is that roles are unnecessary (as previously mentioned). Of course if I don’t want the possibility of roles in my application, I’d have to go implement my own user store that omits the role store interface, but implements all of the other store interfaces.

One other minor issue is that the EF implementation of IUserStore, the API to delete a user throws a NotSupportedException. This stinks and harkens back to some of the leaky abstractions from the previous membership APIs.

Bad: Non-EF and/or custom implementations

I feel for those who are using NoSql or anything not with EF. The reason is that given the multiple interface design, your user store will be responsible for implementing all of the aforementioned store interfaces. As I previously mentioned, it would be much simpler if there were one user store with all the pertinent identity information stored on the user definition.

Aside (and probably Bad): I wonder if Azure (or Live) is using this framework?

As we evaluate frameworks and products from Microsoft, a useful metric on the quality and longevity is if Microsoft is using them internally. I suspect they’re not using the new ASP.NET Identity anywhere internally, thus there’s little mileage and internal feedback on it.

I wonder what Azure’s (or Live’s) identity management looks like and why Microsoft didn’t just use that instead for ASP.NET Identity. Now that I think about it, I’d also be curious what they use for their password hashing iterations. I digress.

Ugly: Where’s the hard and complicated security stuff?

As I see it, the reason for using a security framework (and in this case, an identity management framework) is because there’s some hard security stuff that you want to ensure has been done properly by a security professional. Looking over the UserManager API above, my question is “where’s all the security functionality?” I don’t know.

What sort of features am I talking about? Well, here’s a list:

  • Email account verification : It’s not easy to ensure that a user is really in charge of an email account they claim to own.
  • Password reset : What happens when a user forgets their password?
  • Username reminder : What happens when a user forgets their username?
  • Account lockout : What happens when an admin needs to lock an account?
  • Password guessing prevention : How do you detect and prevent someone from attempting to brute force an account’s password?
  • Close/Delete account : How do we handle an account that the user wants to close or delete? (right now the EF implementation throws a NotSupportedException… nice)
  • Modern password storage (OWASP) : We should be able to ask the framework to do a better job of storing passwords.
  • Mobile phone verification : It’s not easy to ensure that a user is really in charge of a mobile phone they claim to own.
  • Two factor authentication : To improve security, we want the user to provide something they know and something they have to prove their identity.
  • Certificate based authentication : How do we allow users to authenticate with certificates?
  • Auditing : How do we audit changes to the user account information?
  • Tracing : How do we debug failures in the identity management and authentication system?

This list of features is the hard part of building an identity management library. If you want any of the above features, then you get to implement them yourself. Many of these are non-trivial to implement and in doing so you will want to ensure you don’t open up any vulnerabilities in your application. G’d luck.

Also, with the previous membership frameworks we used to have support for: account lockout, password guessing prevention, and close/delete account semantics. So with this version, we’ve lost features.

This glass is half empty

Really the main bulk of code that Microsoft has provided for us in this new framework is the persistence code (via the EF-specific implementation). Unfortunately, the persistence is the easy part. What we really needed was a framework that solves the hard and complicated problems related to identity management.

As it stands now, these missing features in ASP.NET Identity make it unusable for all but the most trivial demo applications. It’s just not ready for prime time today. Of course, with this redesign, I think Microsoft is in a much better place to add these features in a future release. But it ain’t there now.

MembershipReboot

Given my frustrations with the previous provider APIs, I decided to build and open source my own identity management library called MembershipReboot. With this version of ASP.NET Identity, I really wanted it to be great so that there would no longer be a need for MembershipReboot, but I guess that didn’t happen. So if you’re looking for an alternative you can get it here.

114 Comments leave one →
  1. Michael permalink
    October 20, 2013 10:02 am

    I hate to ask the obvious, but why don’t they consult with you, as you obviously know a lot about this stuff? You sure pointed out a lot of “bad” things in the new framework.

  2. October 20, 2013 11:20 am

    Reblogged this on http://www.leastprivilege.com.

  3. October 20, 2013 2:35 pm

    How about extending their framework to support your missing features?

    • October 20, 2013 2:45 pm

      You must not have read the entire post. The last paragraph says:

      MembershipReboot

      Given my frustrations with the previous provider APIs, I decided to build and open source my own identity management library called MembershipReboot. With this version of ASP.NET Identity, I really wanted it to be great so that there would no longer be a need for MembershipReboot, but I guess that didn’t happen. So if you’re looking for an alternative you can get it here (https://github.com/brockallen/BrockAllen.MembershipReboot).

      • Erik permalink
        October 20, 2013 3:41 pm

        I don’t think you understood Dh. He’s saying, why don’t you extend ASP.net Identity to supply the missing features like PasswordReset, etc.. Not why don’t you implement a new API.

        Dh, just implementing those feature doesn’t address many of Brock’s other points.

        • October 20, 2013 3:52 pm

          Actually, I did get what he was saying :)

          But since I’ve already done much of this implementation already in MR I am not sure if I’m willing to invest this effort in their API as well. I’m on the fence weather it’s worth it to bolster their library. Also, as you suggest, their design might not lend itself to all of the features MR has.

          So, short answer: I dunno if I’d do it. I’ll have to think about it.

          • October 22, 2013 11:29 am

            I also question whether it is worth the effort to extend ASP.NET Identity to include the features Brock mentions. First, this is the second complete rework of membership in as many versions. If you had embraced SimpleMembership, you would be now using legacy code. Is this first iteration of ASP.NET Identity doomed to be abandoned like SimpleMembership? Or, is it going to be a moving target, filled with breaking changes, as the Identity team rethinks it’s strategy? I’ve seen posts elsewhere that allude to a roadmap that the Identity team is working on which may include some or all of these features. Who knows?

            I think one point that Brock could have added to his good/bad list is that, unlike much of the other parts of today’s ASP.NET development story, the ASP.NET Identity parts are not currently open source and available to the community. I think the availability of the aspnetwebstack and katanaproject projects on CodePlex are a huge benefit to everyone. Without having access that source, a broad misunderstanding of the best way to use it (user claims? identity claims? authmanager claims? huh?) will continue until trial and error or guidance from the Identity team clears the air. It would be nice for the ASP.NET Identity team to get their code out for review and possibly pull in community created improvements such as Brock’s missing feature list.

          • Mike permalink
            March 5, 2014 8:00 pm

            I doubt this will be their last implementation of Security either, but that doesn’t make it a bad choice to embrace it… for now.

  4. October 20, 2013 3:06 pm

    Way back when I was in uni, I had an online interview with a certain Seattle based company. I was asked what I thought was the worst part of ASP.NET was. My instant response was that the Membership API is a bunch of worst practices put in one big dump. I was almost laughed at – MVC was coming on big, and I was expected to say something about ViewState, or page life cycles, or intelligent UI, or something. Several versions later, things still don’t seem to have improved much. Ah well…

    • October 20, 2013 3:11 pm

      Well, we all gets some things right and other not. I think it’s good to give Microsoft credit when they get things right too :)

  5. Erik permalink
    October 20, 2013 3:29 pm

    Brock, your review appears to be of the pre-release version.. this changed somewhat for RTM. For instance, there is no longer an IUserPasswordStore, and hashed passwords are now stored in IIdentityUser. I’m a little surprised that you would go ahead and publish this article after the RTM, without having actually evaluated the RTM version…

    • October 20, 2013 3:38 pm

      Hmmm, I’ve been evaluating this since VS2013 RTM (so since last Thursday) and I’ve not installed any other version on my main machine. Perhaps the templates were pulling from the pre-release bits? I’ll go double check now.

      • Erik permalink
        October 20, 2013 3:43 pm

        Odd, since my RTM version is quite different. I also read comments from the ASP.NET team that IUserPasswordStore was going away for RTM. I don’t know why it would pull pre-release, since these tempatates are, I think, included on disk and not pulled via the net.

        • October 20, 2013 3:48 pm

          Do you have a link for the comment about them removing the IUserPasswordStore?

    • October 20, 2013 3:44 pm

      Well, I just went and double checked — the assemblies in C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Stack 5\Packages match those from NuGet in the ~/packages folder for a project I just created. My version number for Microsoft.AspNet.Identity.Core is 1.0.0.0 with file version of “1.0.20911.0”. Have you seen a newer one?

  6. tafs7 permalink
    October 20, 2013 10:26 pm

    Ye!, been waiting for you to blog your opinions on this :) Thanks for sharing!

  7. October 21, 2013 12:00 pm

    How does the method SetPasswordHashAsync store the salt? Is it joined together with the hash?

    • October 21, 2013 12:02 pm

      Yep, essentially same as before. I didn’t check yet to see if the binary is compat w/ the old version.

  8. October 21, 2013 9:24 pm

    Reading the conversation a few comments above made me go check the nightly build.

    Looks like some of the points addressed in the post is getting addressed. Heres some of the methods coming on the UserManager

    IsConfirmedAsync(string userId)
    ResetPasswordAsync(string userId, string token, string newPassword)
    SetConfirmedAsync(string userId, bool confirmed)

    But yes, the general impression is that this is not done and it would have been more interesting to see what Microsoft use as Brock asks. But well, at some point they will get things right :) Before I had no doubt that I would use MembershipReboot. I guess with a few iterations / releases of AspNet Identity I would have no problem using either of them. But right now using Identity involves decompiling the dll to see what is going on under the hood.

    Hoping that they just put up the source code soon.

    What I miss the most right now is some documentation / examples, finding it hard to extend the functionality and using MembershibReboot just gives me those extra little things.

  9. nportelli permalink
    October 24, 2013 4:44 pm

    I’m left wondering if anything they released would be good enough.

    • October 24, 2013 5:35 pm

      There is certainly a long list of features necessary to build a robust identity management system — it took me a whole year to get all the features I have in MembershipReboot. I also understand they have to prioritize all of their features in a large release like this, but they’ve been working on this and promising a replacement for the prior frameworks for well over a year. Also, for some reason Microsoft isn’t being very forthcoming about the fact that this version is simply an incomplete base framework and that they’re working on adding more features for the future. Look at their nightly builds nuget feed and you can see that there’s already more features coming. Of course, I’ll reserve judgement on how it’s implemented until it’s released :)

      But yea, we could use an announcement from Microsoft clarifying these things.

      • nportelli permalink
        October 31, 2013 9:04 am

        At least they are finally changing things. How long did it take them to even admit the 1st iteration of Membership was a PITA? Bad part is if you have a system that uses the old membership, there isn’t an easy way to upgrade to a new/better one.

  10. October 26, 2013 12:50 am

    After waiting patiently for the ASP.NET Identity RTM, I have to say that I’m very disappointed. Like you say, it’s pretty much a work in progress and there’s no way I can use it on a real world site. I did not know about Membership Reloaded, but I’ll play with it this weekend and will consider using it for my new site being released at the beginning of November.

  11. Rich permalink
    November 1, 2013 1:01 pm

    Although I consider myself relatively still a novice programmer, membership reboot seems like the direction that I would like to move forward with for my app. I took a look at your samples on github, but the logic is still a bit above my head. Is there a step by step tutorial available for beginners such as myself? Also, how would one use this system in terms of authorizing controllers in asp.net mvc?

    • November 1, 2013 1:07 pm

      I started on some docs — check the wiki on github. Also, the samples are meant to show feature by feature (register, login, logout, etc) and they’re in MVC. Perhaps the MVC code is not familiar, so apologies (but I needed to have some delivery mechanism). But that’s about all I have right now for support, samples, etc. Feel free to search and/or post questions on the github issue list.

  12. November 5, 2013 4:29 pm

    Brockallen:
    Thanks so much for his article. I have been spending a LOT of time trying t get things to works (esp associating users with claims). Thinking I was doing something wrong. I wish MS had acknowledged that some of these basic elements are still a work in progress. Your article has confirmed to me that ASP.Net identity was not ready for prime time.

  13. evilmonkeydance permalink
    November 6, 2013 6:23 am

    Just wanted to say something before I forget. All the stuff about these so-called “claims”… I don’t get it. I consider myself relatively good at english but I hardly know the translation in my own native language for that word so it makes it even more confusing. So imagine the confusion for people less good at english. Roles, that is a word that we all can relate to. Everybody knows what a role is if you think of a CMS which has different roles (Admin, Publisher, Editor etc) for instance. What I’m trying to say is that the word “claim” is a confusing word for these new features/APIs and should not be used.

    • November 6, 2013 7:58 am

      I suspect it’s just like anything else — if you’re not exposed or familiar with something then it’s uncomfortable or confusing. It’s just a matter of time and understanding.

  14. November 6, 2013 2:39 pm

    I’ve spent days with MR and still didn’t have a working solution of anything but login. Then I went to ask few questions on Github and the response from Brock was that security is hard. So instead of making it easier, yeah, go ahead and use MR and after a while you will find out you also need ThinkTecture Identity Server (and a dozen of other things) and make things even harder. With MR you will find yourself going through dozens of online articles of almost scientific level and e-books on Claims and Security and you’ll still be running into scenarios that you won’t know how to handle and with what tools. It’s just too hard and too high of a learning curve. If I invested a month of time, then probably I’d get it.
    With ASP.NET Identity I bet they’ll issue new features in a few months time and after that the technology will probably last at least 2-3 years and at Microsoft they’ve always been good at making even highly complicated things simple. While with MR I don’t want to end up in a situation where Brock&Co. someday decide they feel the product is finished or don’t find time to develop it further or a least fix bugs (I am finding more and more open sourced Github projects that looked promising but nowadays initial authors don’t even accept good and tested Pull Requests). Actually, this happens so often that I have to take long term support and development into consideration when choosing a techonology too.
    That being said, of course ASP.NET Identity is not perfect (what is) but it is a huge step forward while still keeping things simple (and also offer a decent degree of extensibility).
    As one wise man once said “It takes a genius to keep things simple”.

    • November 6, 2013 4:00 pm

      Sorry you had so many issues. The SingleTenantWebApp is a fully functioning sample, so I’d suggest spending some time with it.

      As for the complaints — it seems that you’re conflating different things. I stick by my comments about security being hard, and the point wasn’t to discourage you but to rather let you know there are many different aspects and it takes time to understand the purpose or each piece. I’m not trying to talk down to you — just trying to console you in that it takes a long time to understand the different layers.

      MembershipReboot is about identity management, and so is ASP.NET Identity and the old Membership Provider. That’s all these libraries do — they manage passwords and the storage of this identity data.

      Claims is simply a concept that has to do with identity. You’ll run into them when working with identities if you’re using external identity providers or some of the more modern identity providers. But it’s also possible you don’t work with the specific concept of claims, but I suspect they’re still in your app in some sense.

      In your app if you need to keep track of the logged in user you will then need some sort of cookie based authentication. That’s what Forms authentication, WIF’s session authentication module and the new OWIN cookie middleware do. This is separate from the identity management part.

      If you need single sign-on for many different apps, then you’ll need a centralized identity provider. Identity Server, ADFS, WAAD, Google, facebook, etc. are all considered identity providers. Each one implements different protocols for transferring this identity to the application that needs it. And you’ll need some library for handling those protocols in your app. WIF, Identity Model and OWIN authentication middleware do that.

      Hopefully this provides some clarity to your confusion. As you can see, there are many moving parts, and your assertions that you need IdentityServer is incorrect. Those are just options depending upon your requirements.

      As for your complaints about github and open source — I don’t know what issues you ran into, and your accusations are vague and somewhat insulting. But it’s open source and free. I’m perplexed as to why you sound so upset about this arrangement. The license does say “as-is” and you don’t have to use it.

      Good luck with those password resets.

      • November 7, 2013 6:53 am

        Maybe it’s because we see the “hard” stuff differently. For me, almost everything on your “where’s the hard and complicated security stuff” doesn’t seem that hard to implement properly (the hardest probably being certificates and two factor) and we’ve done it before with ASP.NET Membership (since we skipped Simple Membership). On the other hand, the stuff you somewhat left out of MR or deemphasized like third-party auth providers via OpenID and OAuth2, getting everything out on the wire correctly, the cookie&tokens issuing and management that’s where ASP.NET Identity comes in hand. For me, those are the hard parts, generating confirmation URLs and sending confirmation emails certainly isn’t.

        Other than that, I did spend considerable amount of time on MR and it looks nicely engineered, decoupled, partitioned and whatnot but when you need the whole package it becomes hard to properly set everything up, well that’s just my impression.

        • November 7, 2013 8:43 am

          Again, I think you’re confused. MR is about managing local identities and all of the security stuff that revolves around that. Implementing the protocols for external identities is not the purpose of MR. Perhaps this explains your prior snipe about an application needing a bunch of other libraries. I think not implementing too much is a good thing, as it gives the application developer the ability to choose the components they want for each piece of the puzzle. And, again, ASP.NET Identity doesn’t do cookies either — that’s the OWIN cookie middleware (see this post: https://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/). So my sense is that you still don’t yet have an accurate understanding of the delineations between each moving piece in these security systems.

          As for the other stuff not being hard, sure it’s not hard if you use a library that implements it, but Membership didn’t have all the features, plus it’s abstraction model was poorly designed (see this post: https://brockallen.com/2012/09/02/think-twice-about-using-membershipprovider-and-simplemembership/). In many scenarios the built-in membership wouldn’t work for people, so they were left on their own to implement these features from scratch, and it proves to not be so easy. This is why I built MembershipReboot and open sourced it.

        • Erik permalink
          November 7, 2013 12:08 pm

          The problem here is that you misunderstand what “hard” means. It doesn’t mean hard to do something that works. It means, it’s hard to do something that works correctly, and securely. It’s extremely easy to implement poor security, and most people (and i’m guessing you’re among them, given your comments) don’t even realize you’re doing insecure things. In fact, even the experts get it wrong frequently if they’re not paying close enough attention.

          Little issues, like information leaking may simply not be important to you, but they’re important to a secure implementation.

          Security is very hard to do correctly and securely, that’s why it’s important to NOT roll the important, hard things yourself.

          However, many other issues are very application specific, and providing an implementation provides too much of a straight jacket, so a good implementation of a security framework leaves those portions to the app developer.

          One of the big problems with asp.net FormsAuthentication is that it’s too confining.. if you want to customize anything, you’re left basically overriding almost everything.

          You also need to consider that things like Request authentication (cookies, tokens, etc..) are different from credential authentication or verification. Which are different from Authorization, which are different from Profiles (names, addresses, etc..).

          • November 8, 2013 4:42 am

            @Erik: I had a longer post written but it boils down to one question: are you getting off of a fact that you do security 24/7 and you think of yourself as being this smartass security champ? Coz that’s what your response reads like.

            “Everyone is doing it wrong, MR is the only thing that does it right, I am the only one that has the right to do security, no one shouldn’t roll their own and it has to be as complex as it is because security is hard and that’s the only way to go about it?”

            srsly

          • Erik permalink
            November 8, 2013 10:40 am

            You missed the important part of that statement.

            “In fact, even the experts get it wrong frequently if they’re not paying close enough attention.”

            Security is Hard. This has nothing to do with MR, in fact, I’ve never even looked much at MR, nor do I use it. Nor do I claim to be an expert (or that I am even getting it right all the time). But, experts understand how difficult this is, and people that think it’s easy are displaying the fact they don’t know enough to know how difficult it is.

            I’m not being a smart ass, i’m being serious. In security, you have to have a thicker skin, because you will be called out. So try not to be so defensive, and read the post as a whole.

            There’s something known as the Dunning-Kruger effect, in which people who know less about something rate themselves as having more expertise than those that actually know a lot more about it. This is basically the age old saying “You don’t know enough to know how little you know”.

            Unfortunately, security researchers (and again, I don’t count myself among them) have been dealing with this problem for decades. People think they can roll their own security algorithms and have them be more secure than well tested and peer reviewed algorithms.

            This is a huge problem with all the people that roll their own membership providers. All too often, they also implement their own password hashes, rather than using the Membership class supplied ones (or even the framework supported higher security versions). And they are all absolutely convinced that what they are doing is secure. And maybe, sometimes it is.. but the odds are, they’re not.

            My point is, based on your comments, you clearly misunderstand a lot of key security terms and concepts. That means you lack the experience to know whether something is secure or not. That’s not a diss, or being a smart ass. That’s a suggestion that you dig in and learn a bit more before criticizing things. We’re all guilty of this on occasion (I did it on this very blog very recently), but you have to be professional enough to recognize this and learn more.

        • December 5, 2013 1:28 pm

          I read 20+ page whitepaper outlining only how to handle password recovery. Nothing more than that. Nothing fancy, advanced stuff – just a checklist of basic things that I as a website developer should think about when implementing password recovery. I would like to say, Yes, generating URL:s, sending the right e-mails, asking the right questions, giving the right error messages, all that “easy” stuff is actually Hard to make truly secure as there are so many small problems that will completely ruin your security..

          • December 7, 2013 3:26 pm

            Yep. My recent talk at NDC went over these exact issues. If you’re interested I just posted my slides (not that they’re very good), but it’s something to look at.

  15. jonnysalmon permalink
    November 20, 2013 7:14 am

    10,000 thanks to you. Indeed nowhere in the VS2013 project templates do I find Claims code. Thanks to you all at ThinkTecture for your productions that help me understand how to add Claims to the templates. Microsoft disappoints by omitting code in the templates to simply persist (in the DB and in the cookie) the user’s email claim from external (social network) login.

  16. Sam permalink
    December 18, 2013 7:09 am

    Good review.

    Apart from the increased degrees of seperation, and the async methods, the Identity API is something I’ll be ignoring, and still sticking to the original Membership system since I’ve made the effort to kit it out with external provider support anyway.

    I never know why Microsoft would want to use STRINGS as Ids. Even the base IUser uses a string ID with no way to change this. Half the API requires a user to implement IUser. Then all the AccountMangement part, requires the User to inherit from IdentityUser, so you can’t even use the Interface anyway.

    The end result is the same as the original Membership system, you end up with a user object full of stuff you don’t want.

    Plus there doesn’t seem to be a neat way to populate the user/claims/secrets/roles etc at once. At the moment they’re all seperate which might be nice from an organisational point of view but seems like a quick way to kill a database will tiny in-efficient hits.

  17. December 18, 2013 5:46 pm

    Reblogged this on Savita's Notepad and commented:
    Reblogged this on http://dotnotepad.wordpress.com/

  18. January 5, 2014 2:39 pm

    Just a quick note: As I was working on my own version of a custom UserStore I noticed that IUserPasswordStore inherits from IUSerStore. The same is true for IUserClaimStore, IUserRoleStore, IUserEmailStore and IUserLoginStore. IUserStore is essentially redundant if anyone of these interfaces are implemented.

    • Erik permalink
      January 20, 2014 2:22 pm

      No, it’s not redundant. They all share a common base interface for polymorphic use. If you want to support multiple stores, you need a common interface to apply to them, or you cannot treat them the same.

  19. January 20, 2014 1:05 pm

    What I’m disappointed in is the implementation of Authentication in MVC makes it very difficult to separate it out of the Controller. I like to have a Client\Web, Doman, Business and Repository class.
    Where repository has all of the data access and business has the business rules and Domain are DTLs or data objects.

    When my users login I want to add additional checks as business rules or centralize my logic outside of the client/web assembly.

    Also, with the identity framework I now have to have my domain assembly reference Entity Framework and Identity Assemblies.

    • Erik permalink
      January 20, 2014 2:19 pm

      I’m not sure you understand how authentication actually works in MVC. First, one must realize that authentication *IS* a web function. That means it has to be handled in the UI framework code. No, that doesn’t mean the logic has to be there, but the actual implementation of the authentication method does. The reason is that this is dependent upon specifics between the browser and the server (is it cookie based, Kerberos based, basic authentication, etc..)

      MVC makes it very easy to move your authentication logic wherever you want. They have chosen to decouple authentication from the implementation using an interface based filter approach. You need only implement an IAuthorizationFilter based object. This can live in your business layer if you want, although that would probably mean a dependency on MVC to get access to the interface definition. Instead, you would create a small wrapper object in your UI layer that wraps your business layer authentication vi an IAuthorizationFilter.

      This allows you to use attribute based (ie similar to Aspect Oriented Development) authentication.

      Yes, if you do your authentication in the controller itself, you’re tied to the controller, but that’s not really the recommended way to do it.

      MVC5 has added AuthenticationFilters as well, which run before AuthorizationFilters.

      You do not have to have yoru domain assembly reference EF or Identity assemblies if you do not need them. You can do it the other way around. You write an assembly which does your identity processing, which calls into your business layer.

  20. Jarvis902 permalink
    January 25, 2014 6:45 am

    Good read, thanks. What I really like about ASP.NET Identity is the direction it is taking as opposed to the older approaches by Microsoft, e.g. the decoupling and especially the clear separation of security/identity management logic and data access are great. As I see it, the default EF implementation is just meant to be a quick start. The main point of this framework is the management logic.

    Also the framework is very young and if you have a look at the roadmap on CodePlex (https://aspnetidentity.codeplex.com/wikipage?title=Roadmap), they are addressing at least some of the issues, although it may take an awful lot of time as it is often the case with these things. But so far it seems to go in the right direction.

    E.g. they are about to add a delete functionality and let you customize the user’s primary key. What isn’t on this particular roadmap is the issue with the strange separation of roles and claims though. My suspicion is that they wanted to keep things easy to understand for developers not familiar with claims, so they added the IUserRoleStore — but it is optional and is mapped to OWIN claims so you should be able to work with claims exclusively. I still have to try it for myself though. But I suppose they will keep the IUserRoleStore as a simple and traditional alternative to claims.

    • January 25, 2014 10:11 am

      Sure, but when they release v1 and taut it the way they did without mentioning all the missing features then it’s just lame.

  21. Justin permalink
    February 13, 2014 3:15 pm

    During migrating from SqlMembership to AspNet Identity, one of the ugly parts I just ran into were all the Id columns being enforced to nvarchar(128). If you have custom tables joined together with the previous SqlMembership tables (ex: aspnet_Users) then this causes huge problems. Switching the nvarchar to a uniqueidentifier causes all kinds of errors in the default methods used to manage these users in the AspNetUsers table. Basically, the two options for AspNet.Identity were either to change all of our related membership FK columns to match the nvarchar type of AspNet Identity’s tables or override almost every method AspNet.Identity provides.

    I read on some SO questions that you can download the nightly build for AspNet.Identity 1.1 but when managing an enterprise application, it seems like a terrible idea to have your app rely on an alpha version of a product that already has so many cons and missing features. Maybe Asp.Net Identity can be useful to some developers but in our case, it’s been a huge waste of time.

    That’s the end of my rant. Also, thanks for the great article. This was my number one resource in getting a good, non-biased overview of AspNet.Identity and it’s capabilities before diving in. It’s too bad it didn’t provide what our application needed.

    • February 13, 2014 3:40 pm

      Thanks. Except I’m pretty biased — I’m biased in that I expect them to do a better job.

  22. February 26, 2014 12:50 am

    Amazing, just want to keep track of folks visiting our site, so we can show them what they did last time… I am stunned at how complex and obscure the information needed is, to correctly implement this system. Even if I read every word of what you wrote, and understood every concept exactly, I still would not have confidence that whatever system I came up with would be secure, and extensible (this is MS fault, not your very well written article). Hats off to you guys who live and breath this… first reaction: what a cluster fck, let me break out my 1000 page .NET programming manual so I can have a guy click a Google button so he can see the 2 files he uploaded yesterday… lol.

    • Erik permalink
      February 26, 2014 12:53 pm

      Security is difficult to get right. This has nothing to do with .NET or this particular API or anything else. You have to learn about security in detail in order to have confidence that you have done it correctly.

      Brock’s analysis, while it’s now a little dated in some areas because new versions of the Identity API are coming down the pipe, is very good. But you have to understand that Brock is coming from a viewpoint of wanting perfection (or as close to it as possible). We should certainly all strive for that, including Microsoft (and often it seems they fall short). But, that doesn’t change the fact that doing this is *difficult* to get right.

      Your choices are, trust that the system works, or learn deeply about it to gain a sense of confidence about what it does, and how it does it. If you don’t want to do that, then you will never have confidence in any system.

  23. March 4, 2014 8:36 am

    First of all, thanks for the thorough explanation of the pros and cons of ASP.NET identity. I’ve learned a lot by just reading your blog posts.

    I have one question though, and it’s about your statement that roles are claims. I feel the same way, and I do think that a role is just another claim. However, roles are just there to stay, and they do tend to mean more to people than the notion of ‘claims’. Moreover, a role is often easy to set up non-detailed authorization policies, e.g. a ‘user’ can only view, an ‘admin’ can view and edit. Now, some papers suggest to use attributes (I don’t see any differences between claims and attributes) to allow for more fine-grained authorization, to CONSTRAIN the policies imposed by the roles.

    A good paper in this regard can be found here: http://csrc.nist.gov/groups/SNS/rbac/documents/kuhn-coyne-weil-10.pdf table 1 is interesting there.

    Basically they speak of a user who has a role. The permissions linked to this role can be restricted depending on the attributes (claims) that user has. However, attributes cannot give a user more permissions than those allowed by the role that user has. Attributes thus allow for more fine-graining, but cannot overrule the permissions set by roles. I think this is a very clever thought, as we keep the simplicity of RBAC, and extend it with the flexibility of ABAC.

    Now my question: if MR looks at roles and claims the same way, is it possible to constitute such a role-context attribute based access control with MR?

    • March 4, 2014 10:33 am

      Thanks — I’ll go look at the paper you linked.

      As for roles vs. claims vs. here to stay :) — Far too often identity information is confused with permissions. Identity is about the user and permissions is what the user is allowed to do. They are technically separate but in smaller systems it’s easy/easier to conflate the two for implementing authorization. Neither MR nor ASP.NET Identity do anything for authorization. They simply model identity information for your users (as well as password validation, etc, etc). Your permission system should then be setup elsewhere to enforce your authorization requirements and sometimes this requires hitting a DB to load the permissions, but sometimes this is simply hard coded with a IsInRole check (or a claim check).

      • March 4, 2014 10:54 am

        Thanks for your reply. Your statement about identity – authorization is certainly correct. It basically comes down to the important difference between authentication and authorization. However, authorization cannot exist without authentication. If we want to use claims to set permissions, we need to know which claims can be linked to a certain user: which actually depends on authentication (i.e. the verification of the user allows us to check this user’s claims).

        Anyway, I’m really interested in the matter of roles and attributes, and if it would be possible to use roles as an encompassing set for attributes in MR. I suppose we would have to go back to the original MS model, with a IUserRoleStore and a IUserClaimsStore. Of course, this would be conceptually different from how MS meant it to be.

        • March 4, 2014 11:20 am

          Maybe I wasn’t clear — both MR and ASP.NET Identity don’t store permissions — they store identity.

          If you need a permissions database, then that’d be custom. And when I say permissions database, I mean a DB that contains something like “For customer 123, people in role ‘Foo’ can view, but people in role ‘Bar’ can update”. It sounds like you’re thinking of MR and ASP.NET Identity as stores for this kind of data, and they’re not.

          Have you looked into the ClaimsAuthroizationManager class? It models the permission check with claims (roles or otherwise).

          • March 4, 2014 12:01 pm

            I see your point about permissions. So let me get this straight. Storing claims is about the fact that I need to know that user A has the following claims: role = admin; name=michael; colorofeyes=blue.

            Then I would have a permissions table which would say: everybody with blue eyes can view (authorization)

            During authentication, we need to verify the user (being Michael), and we need to retrieve all claims that are linked to this user (role admin, name michael, color of eyes blue). This IS part of MR and ASP.NET, right? These are the actual claims.

            Now, if I want role-context attribute based access control, you are saying that I need to implement my own methods/permissions table which takes into account that claims, other than the role claim, can only constrain authorization rights.

            Ok I’m seeing things more clearly now. Only problem is that to my knowledge there are no real RABAC implementations yet.

          • March 4, 2014 12:04 pm

            Yes, you got it.

  24. March 5, 2014 7:18 am

    After more closely examining MembershipReboot (SingleTenant app), I’m wondering why there is an entity ‘group’, and where it is used in the application?

    Isn’t a group just another claim, same as a role?

    • March 5, 2014 8:09 am

      The Group and GroupService classes are there to allow you to define the groups/roles for your app. It also supports defining a hierarchy of groups.

      • March 5, 2014 8:10 am

        So conceptually, you feel that a group is not a normal claim?

        • March 5, 2014 8:13 am

          There’s a difference between a role (or group in this case) definition and who is in the role. The GroupService is for defining the list of available roles and how they form a hierarchy. The UserAccountService allows you to give a user a role claim.

          The GroupService isn’t mandatory for using the identity management features of MR — it’s just icing on the cake.

  25. Haythem Tlili permalink
    April 8, 2014 7:03 pm

    Great article ! I’ve been following the development of the ASP.NET identity and i think v1.0 was catastrophic (poor documentation, etc). But they already released the 2.0 finally with a lot of improvements (email confirmation, two factor authentication, password reset, account lockout, etc). I suggest that you take a look at it and maybe you want to write a 2.0 review.

    • April 8, 2014 7:47 pm

      Yea, perhaps I should. v2 is better, but is still problematic for many reasons — many of which I have already mentioned elsewhere.

      • May 9, 2014 2:09 am

        I am looking forward to this. While I will probably continue to use ASP.NET Identity (officially supported, will accumulate know-how on the internet) it really helps to know the specific problems and strengths when using it.

  26. April 10, 2014 7:37 am

    Some of your comments related to roles, claims and custom user data (eg: here Bad: Wait, there’s also an IUserRoleStore?) made me smile in sympathy. Just recently, at one small financial company with an in-house .NET team, I was working on the general design for further development there and trying to introduce claims as a concept. It was actually much harder than I could have anticipated. It kept leading to philosophical confusion in the team, with questions such as ‘well where do I do the authorization? in the claims token provider? or in the app?’ and a lot of unnecessary debate. I can see that some teams would simply not be able to make the change to claims, even though it might seem simple enough to many.

    • April 10, 2014 11:51 am

      Yea, I wish I had an easy answer. I think the only way is to continue the discussion and to educate people. This is an area that Microsoft has never been good at (when something is recondite or complicated).

  27. April 12, 2014 3:20 am

    I’m trying to create a new website using the ASP.Net security, simple question …is it worth using the Microsoft.ASPNet.Identity and implement the IdentityUser interface? Or should I just wait until the ASP.Net Identity matures much like Entity Framework?

  28. April 16, 2014 11:13 pm

    I’ve been banging my head against the new ASP.NET Identity 2.0.0 for a few days. I was beginning to think I was stupid.

    I agree: Where’s the hard and complicated security stuff?

    Why would I implement ASP.NET Identity 2 when it doesn’t seem to do any of the hard stuff for me???

  29. May 19, 2014 9:36 pm

    Hi, I’m beginner with ASP.NET identity
    I need to create a single sign on, could you give me an advice to start?, I mean, Is Windows Identity Foundation the correct way? Could you give a link to some article?
    I want to create it with the best technology.
    Thanks

  30. November 18, 2014 1:30 pm

    This was extremely thorough…thank you.

  31. November 18, 2014 1:46 pm

    You did forget to mention that Identity WOULD be a good solution if you are using EF and your application uses Roles.

    • November 18, 2014 2:15 pm

      ASP.NET Identity v2.1 has finally provided enough features to be viable.

      • tafs7 permalink
        December 3, 2014 11:26 am

        @Brockallen if you think it has matured enough, then perhaps you should put a little update note at the top of this post and let folks know that as of Identity v2.1+ most of your concerns are somewhat addressed. And also blog about it and link to the new post from this one. Another bonus would be to let folks know whether your IdentityReboot project is still relevant for v2.1+.

        I ran into this blog post last year when it was published and had some bias against Identity, when recently I had to implement it for the first time. After digging around and spending a lot of research/learning time on it I realize that the team has slowly but surely been addressing the big things you point in the design over the last year.

        Things they don’t quite have yet: auditing/tracing, better default implementation of the password hasher, and less complicated api for roles vs claims – it’s still not clear to most people which to use, since it provides both. Those are probably the biggies in my opinion. Thanks for the post and your opinions, as I believe they have helped bring awareness of these flaws and shape the product better!

        • December 5, 2014 5:40 am

          Yes, good point. I still have a distaste for the API, but it now has most of the features you’d need to build a secure system.

  32. John Lee permalink
    December 1, 2014 9:48 pm

    It’s very sad for lazy programmers like me that ASP.NET is losing its conciseness :)

    • December 5, 2014 5:39 am

      Well, the issue is that security is hard and that’s a problem for lazy developers :)

  33. Phil permalink
    December 13, 2014 2:02 pm

    This is a very interesting thread. Unfortunately, the limitation of the blog software makes deeper nested responses practically impossible to read. It’s too bad that such a trivial issue undercuts the value. I suggest trying to fix it.

  34. January 30, 2015 12:21 am

    Reblogged this on RyanLiu99.

  35. January 30, 2015 12:27 am

    Good post. I also feel it is to make SupportsUserClaim read only in UserManager

    public virtual bool SupportsUserClaim
    {
    get
    {
    this.ThrowIfDisposed();
    return this.Store is IUserClaimStore;
    }
    }

    and in ClaimsIdentityFactory.CreateAsync() depends on it
    if (manager.SupportsUserClaim)
    {
    ClaimsIdentity claimsIdentity2 = claimsIdentity;
    TaskExtensions.CultureAwaiter<IList> cultureAwaiter1 = manager.GetClaimsAsync(user.Id).WithCurrentCulture<IList>();
    claimsIdentity2.AddClaims(await cultureAwaiter1);
    }

    Make it looks like, to use claim, you must persist claim. This should not be the case. Information in Claim might in Tuser and already being persisted in User table.

    The purpose to add more info into claim, is to avoid go to db to fetch them, just to get them from Claim,which in turn , get from cookie.

  36. April 18, 2015 5:20 pm

    Hi Brock,

    One scenario I am desperately looking all over the Internet to implement is the two step authentication in Single Page Application. Username/Password authentication works great with OAuth. What about two step process?

    First Step: Username/Password verification
    Second Step: e.g Memorable word
    3rd Step: Issue the autorization token.
    This is possible if we are using forms based authenticaiton and store each step verification in user’s session on server and call token end point after second step.

    What if we truly want to implement OAuth without relying on forms/cookies based authentication?

    Anything to point to right direction will be helpful.

    • April 20, 2015 10:39 am

      If you want 2fa then you should use the implicit flow and not the resource owner password flow.

  37. June 26, 2015 12:52 am

    Thank you, you’ve really helped me wrap my head around any non-EF issues.

  38. June 26, 2015 4:35 pm

    I’m reading this while fighting to make Identity/OWIN work with stored procedures, Dapper and SimpleInjector for DI… Sucks. Makes me want to start writing my own identity system as well, as I did back in the days when I wrote my first PHP web app. I would skip all this M$ mess…

    I also hate EF (as well as NHibernate and the like). They suck in performance, they suck in design and the lack of DB dependency they claim to offer is like breaking of your two legs so that you can park your car in every handicap parking zone.

    M$ just goes were the wind blows. They saw NHibernate and they made EF. They saw Java and built .NET. I don’t consider this bad by it self, but it is VERY bad when you throw everything you had so far and invest everything left on a new adventure that might fail miserably.

    The templates in VS are 100% useless for someone who wants to do some serious job.
    Reading the above about Identity not following OWASP suggestions, I think that even Identity is 100% useless. Seeing that kind of stuff makes me want to team up with some crazy guy like Terri who built TempleOS (his own OS, with his own C compiler, his own 3D graphics engine, etc, etc) and built with him the computer world from scratch. I mean how bad can we do? That CAN’T be SO bad as compared to what my innocent eyes see right now…

    I will take a look at your alternative project out of pure curiosity.

    • Erik permalink
      June 27, 2015 4:39 pm

      First off, the above is very out of date. Written almost 2 years ago. I think almost everything in his complaint has largely been addressed in the meantime. Note: He did NOT say that PBKDF2 isn’t OWASP compliant, he said it didn’t, by default, generate as many iterations as recommended.

      Identity works fine, and is not “useless” for the vast majority of people. You have some specific requirements, and that’s fine. Your unfamiliarity with EF and .NET do not mean that Identity is useless, or bad. (note the terms “good” and “bad” used in this blog should really be “good” and “not as good” as there is really nothing “bad” in any of the complaints from a standpoint of “Unusable” or “insecure” or “Don’t ever do that”.

      As for stored procedures, its ridiculously simple in EF 6.1 to back queries to Stored Procedures. I don’t understand why you are having such difficulty. There are also literally dozens if not hundreds of implementations of stores for various technologies in NuGet. There’s even one for Dapper, out of the box.

      https://github.com/xgluxv/dapper-for-AspnetIdentity

  39. December 4, 2015 4:39 am

    @brockallen, as you mentioned “where are the claims?”

    The ASP.NET Identity sample shows how to set and get the claims..
    So what did you mean other than this????

    settings claims:

    public async override Task CreateAsync(UserManager manager, TUser user, string authenticationType)
    {
    // This is a standard place where you can register your ClaimsIdentityFactory.
    // This class generates a ClaimsIdentity for the given user
    // By default it adds Roles, UserName, UserId as Claims for the User
    // You can add more standard set of claims here if you want to.
    // The Following sample shows how you can add more claims in a centralized way.
    // This sample does not add Roles as Claims

    var id = new ClaimsIdentity(authenticationType, UserNameClaimType, null);
    id.AddClaim(new Claim(UserIdClaimType, user.Id.ToString(), ClaimValueTypes.String));
    id.AddClaim(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String));
    id.AddClaim(new Claim(IdentityProviderClaimType, DefaultIdentityProviderClaimValue, ClaimValueTypes.String));

    // Add the claims for the login time
    id.AddClaim(new Claim(LastLoginTimeType, DateTime.Now.ToString()));

    if (manager.SupportsUserClaim)
    {
    id.AddClaims(await manager.GetClaimsAsync(user.Id));
    }
    return id;
    }

    Reading user cliams:

    System.Security.Claims.ClaimsPrincipal claimsPrincipal = Context.User as System.Security.Claims.ClaimsPrincipal;
    System.Security.Claims.ClaimsIdentity id = claimsPrincipal.Identity as System.Security.Claims.ClaimsIdentity;
    foreach (var claim in id.Claims)
    {
    Claim: @claim.ToString()
    }

    • Erik permalink
      January 2, 2016 4:21 pm

      @Govardhan, this article was originally written over 2 years ago when the first version of Identity Framework was released, it has gone through numerous iterations since then and many of the issues raised in the article are no longer relevant. (other still are, of course, but don’t take the article to refer to todays Identity Framework.

      • January 2, 2016 5:16 pm

        Yep, Erik is right – many of the security complaints are now somewhat fixed in ASP.NET Identity 2.1/3.0. I say somewhat because you really have to know what you’re doing to use the library the right way — in short, you can still shoot yourself in the foot. This is my current complaint about the library.

  40. December 4, 2015 4:59 am

    @brockallen
    Here I’ve to take a decision asp.net identity or Thinktecture based on my usecases

    Here are my usecases:

    Credential store
    Does IDM provides its own credential store
    Authentication & authorization
    both should be supported by IDM
    LDAP integration
    How we can integrate LDAP with IDM for authentication
    Certificate based Authentication
    Does IDM supports certificate based authentication, if so how
    Deployment
    How IDM can be used for both cloud and on-premises

    Scalability & performance
    How much max concurrent requests does IDM supports
    Licensing
    If IDM is open source then how it is licensed or do we need to have commercial license

    Setting Token Duration
    How to set the expiry for token in IDM

    Making token invalid on an event
    How to invalidate token on demand

    Device authentication
    How we can achieve device authentication using same IDM

    • January 2, 2016 11:28 am

      For IdentityServer questions, please use the issue tracker on github.

  41. February 22, 2016 11:20 pm

    The number of trips to the database astonishes me!
    A simple call to the following method to sign in a user will hit the database a minimum of 7 times!

    Microsoft.AspNet.Identity.Owin.SignInManagerExtensions.PasswordSignIn()

    IncrementAccessFailedCountAsync (not counted)
    1) UpdateAsync
    SetLockoutEndDateAsync (not counted)
    2) UpdateAsync
    ResetAccessFailedCountAsync (not counted)
    3) UpdateAsync
    4) FindByNameAsync
    GetEmailAsync (not counted)
    5) FindByEmailAsync
    6) UpdateAsync
    7) FindByIdAsync
    GetLockoutEnabledAsync (not counted)

  42. September 19, 2016 11:25 am

    What is your take on multi-tenant user stores with asp.net identity 2/3? ? Is it better to use a different identity management system or customise ASP.Net identity to allow multi-tenant?

  43. Nick D permalink
    December 23, 2016 11:23 pm

    Nice piece – interested what your view on this is in 2016 – for .net – and for the new .net core.

    • January 4, 2017 11:14 pm

      ASP.NET Identity 3 is sufficient and surpasses (for the most part) what MembershipReboot provides.

  44. October 18, 2017 1:11 pm

    What is your take on multi-tenant user stores with asp.net identity 2/3? ? Is it better to use a different identity management system or customise ASP.Net identity to allow multi-tenant?
    bao hanh may nuoc nong ariston tai tphcm

    • December 5, 2017 5:11 pm

      Yes, you can make ASP.NET Identity do “multi-tenancy”, but it requires some work and knowledge of the internal workings.

Trackbacks

  1. codingfreaks » Microsoft.AspNet.Identity in bestender Anwendung einsetzen
  2. How MembershipReboot stores passwords properly | brockallen
  3. Identity Integers Using ASP.Net Identity On MVC 5 | 36 Chambers - The Legendary Journeys: Execution to the max!
  4. ASP.NET Identity - Tutorial Completo - Demos, Vídeo, Slides - Eduardo Pires - Microsoft MVPEduardo Pires – Microsoft MVP
  5. Setup ASP.NET Identity using StructureMap - The Blinking Caret

Leave a comment