Another question I’ve been asked about Identity.

Part of Startup class for Owin can be this:

public void ConfigureAuth(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        Provider = new CookieAuthenticationProvider
        {
            OnValidateIdentity = SecurityStampValidator
                .OnValidateIdentity<UserManager, ApplicationUser, int>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                    getUserIdCallback: (id) => (Int32.Parse(id.GetUserId())))
        },
    });
}

The question was “How does SecurityValidator.OnValidateIdentity invalidate all existing cookies” and “I understand that getUserIdCallback delegate returns an id of a user, but I don’t quite see the usefulness of this parameter” and “why the need for regenerateIdentityCallback parameter“.

regenerateIdentityCallback is a delegate taking UserManager and ApplicationUser objects as parameters and returns a new ClaimsIdentity object. Seems strange to have a separate callback for that because default implementation of UserManager already has CreateIdentityAsync which does work for us. But signature of that method looks like this:

public virtual Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)

See the authentication type as a parameter? without having a global setting for what type of authentication we use, there is no way know what authentication we use. So part of that delegate somehow should be authentication type.

Regarding getUserIdCallback – things are simple here. UserId is stored in cookie as a claim. But it is stored as a string. All claims are stored as strings. If you use default type for the key (String), then no problem here. But if you use Guid or int for primary key type, things get more complex. So this peace of code needs to know how to convert String with id into Guid or int.

To answer very first question “How does SecurityValidator.OnValidateIdentity invalidate all existing cookies“. Well.. it does not really invalidates all the cookies. Cookie contains issued date. On every request SecurityValidator compares if enough time have passed from cookie issue (30 minutes in the sample code above). Then it gets a UserId (via getUserIdCallback delegate) and SecurityStamp values from the cookie. Reaches into the database, finds the user and checks if SecurityStamp have been changed since the cookie have been set.
If security stamp is not changed, fresh cookie is created with new issue date. If stamp have been changed, user is logged out.

And this happens on every request. So it could be that user have logged in Firefox, a minute after security stamp have been updated for that user. User will not be logged out from Firefox for another 29 minutes. And imagine that session in Chrome was started 29 minutes before change of security stamp, so cookie in Chrome will be invalidated in 1 minute.

UserManager registration

If you notice regenerateIdentityCallback is using UserManager and ApplicationUser as part of the callback:

regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager)

How does it get an instance of UserManager? OwinContext is used for that:

var manager = context.OwinContext.GetUserManager<TManager>();

How does OwinContext know about where to get an instance of UserManager? Good question!
You must tell OwinContext how to create UserManager:

app.CreatePerOwinContext(() => new UserManager(new MyDbContext()));

Or if you are using DI in your MVC application:

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<UserManager>());

Or if you are using standard MVC template from Visual Studio 2013:

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

CreatePerOwinContext function registers a callback in a dictionary. And once this call returns an instance, this instance is saved in a Dictionary<String, object> for later user. Basically OWIN has it’s own little DI-container where it keeps references to objects that should be singletons during the request.

If cookie validation function can’t get an instance of UserManager, it will not be able to compare the security stamp in cookie with security stamp in the database and the CookieValidator won’t be able to invalidate the cookie. So your code should look like this:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(() => new UserManager(new MyDbContext()));

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        Provider = new CookieAuthenticationProvider
        {
            OnValidateIdentity = SecurityStampValidator
                .OnValidateIdentity<UserManager, ApplicationUser, int>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                    getUserIdCallback: (id) => (Int32.Parse(id.GetUserId())))
        },
        // other configurations
    });

    // other stuff
}

I’ve been reached out by one of my readers with a list of questions about AspNet Identity. First I thought the questions will be easy and I’ll wing them, but turned out that every single question in the list is worth of a separate blog post. So I’ll do a mini-series of Q-A posts about Identity framework and related stuff.

First question is about security token in a Cookie and how it is computed: Identity Framework creates a token in the cookie, token containing the same information (User.Id, Security Stamp, etc.); if the same user loggen-in in Chrome and Firefox, why are the cookies different?

I did think about it for a while, I guessed that cookie creation and expiration is encoded in the cookie, along with some sort of signature of the cookie. My guess was not far from the real world.

Fortunately, the code that deals with cookies is in Katana Project and is open-sourced.

Here is the pipeline how cookie is created on user sign-in:

  1. Identity framework creates ClaimsPrincipal object from the record in your database (that is represented by ApplicationUser class)
  2. Identity adds list of default claims like ApplicationUser.Id and SecurityStamp to the claims on the principal.
  3. ClaimsPrincipal is passed to OWIN middleware: CookieAuthenticationHandler
  4. Authentication Handler is doing a lot of checking for different things, like should the cookie be marked as secure or persistent, sets the expiry date and many other things. Result of these checks is AuthenticationTicket which has ClaimsIdentity with list of claims and AuthenticationProperties which is a dictionary with load of data like cookie issue date, expiry date, is cookie persistent, etc.
  5. Auth ticket and claims principal is then passed down to SecureDataFormat class where data is serialised, encrypted and Base64 encoded.

The last step contains a lot of movements, let’s look deeper into it.

Authentication ticket is serialised via TicketSerializer. There ClaimsIdentity is written into memory stream: some properties and list of the claims. Then AuthenticationProperties (with cookie set, expiry dates) is also written to memory stream. Then this memory stream is GZipped and returned for further processing.

Next step in the pipeline is encryption. Encryption is borrowed from .Net class DpapiDataProtector. You can read documentation on MSDN. I’m not sure about the strength of the encryption. The documentation says that purpose parameters are effectively a list of passwords. And nowhere I’ve seen in OWIN where you can set your own encryption password and I can see that the main password is set to “Microsoft.Owin.Security.IDataProtector”. So my guess would be that no secure information should go into cookie, i.e. don’t put your connection strings into user claims!

After the encryption, stream of bytes is Base64-encoded to be transferable over the wire. And finally prepared to be set as a cookie header on HTTP Response.

Overall the process will look like this great drawing:

Cookie_Path

Anyway, the answer to the original question why the cookies are different in different browsers would be as follows: because part of the signature contains cookie creation and expiry dates, these would be different in different browsers. So data encrypted in cookie turns out to be different, the value of the cookie will be different.

Recently I have found an excellent question on Stackoverflow. The OP asks why does claim added to Idenetity after calling AuthenticationManager.SignIn still persist to the cookie.

The sample code was like this:

ClaimsIdentity identity = UserManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie );

var claim1 = new Claim(ClaimTypes.Country, "Arctica");
identity.AddClaim(claim1);

AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, identity );

var claim2 = new Claim(ClaimTypes.Country, "Antartica");
identity.AddClaim(claim2);

Yeah, why does claim2 is available after cookie is already set.

After much digging I have discovered that AspNet Identity framework does not set the cookie. OWIN does. And OWIN is part of Katana Project which has open source code. Having the source code available is always nice – you can find out yourself why things work or don’t work the way you expect.

In this case I have spent a few minutes navigating Katana project and how AuthenticationManager works. Turned out that SingIn method does not set a cookie. It saves Identity objects into memory until time comes to set response cookies. And then claims are converted to a cookie and everything magically works -)

This sparked another question. At the moment Identity is does not have open source, but what is the role of OWIN in Identity and how Claims work here?

Turns out that Identity framework deals only with user persistence, password hashing, validating if the password is correct, sending out email tokens for password reset, etc. But Identity does not actually authenticate users or create cookies. Cookies are handled by OWIN.

Take a look on this code for signing in:

public async Task SignInAsync(Microsoft.Owin.Security.IAuthenticationManager authenticationManager, ApplicationUser applicationUser, bool isPersistent)
{
    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

    ClaimsIdentity identity = await UserManager.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);

    authenticationManager.SignIn(new Microsoft.Owin.Security.AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

Identity only creates ClaimsIdentity which you can study on ReferenceSource site. And ClaimsIdentity is part of .Net framework, not some nuget-package from the interwebz. Then this claimsIdentity is passed to OWIN AuthenticationManager where a callback is set to assign cookies on when time comes to write headers on the response.

So far, so good, we have 3 parts here: Identity framework creating a ClaimsIdentity, OWIN creating a cookie from this ClaimsIdentity. And .Net framework which holds the class for ClaimsIdentity.

When in your classes you access ClaimsPrincipal.Current, you only use .Net framework, no other libraries are used. And this is very handy!

Default Claims

Identity framework does a nice thing for you. By default it adds a number of claims to a principal when user is logged in. Here is the list:

  • User.Id is added as claim type “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” or by ClaimTypes.NameIdentifier
  • Username is added as claim type “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” or by ClaimTypes.Name
  • “ASP.NET Identity” is saved as claim type “http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider“. This is useful if you are using OpenId to do the authentication. Not much use if you are using only users stored in our database. See this page for more details.
  • Guid containing User’s Security Stamp is persisted in claim with type “AspNet.Identity.SecurityStamp“. Security Stamp is basically a snapshot of user state. If password/method of authentication, email, etc. is changed, Security Stamp is changed. This allows to “logout everywhere” on credentials change. Read more about what is security stamp in Hao Kung’s answer.
  • The most useful claims added by default are role. All roles assigned to the user are saved as ClaimTypes.Role or by “http://schemas.microsoft.com/ws/2008/06/identity/claims/role“. So next time you need to check current user’s roles, check the claims. This does not hit the database and is very quick. And in fact, if you call .IsInRole("RoleName") on ClaimsPrincipal, the framework goes into claims and checks if Role claims with this value is assigned.

You can find the list of framework claim types on .Net Reference site. However, this list is not complete. You can make up your own claim types as you are pleased – this is just a string.

If you want to add your own claim types, I recommend to use your own notation for the claim types. Something like “MyAppplication:GroupId” and keep all the claim types in one class as constants:

public class MyApplicationClaimTypes
{
    public string const GroupId = "MyAppplication:GroupId";
    public string const PersonId = "MyAppplication:PersonId";
    // other claim types
} 

This way you can always find where the claims are used and will not clash with the framework claim types. Unless the claim you use matches framework claim types exactly, like ClaimTypes.Email.

Adding default claims

I always add user’s email to the list of claims. I do that on user sign-in, same way the first code snippet adds claim1 and claim2:

public async Task SignInAsync(IAuthenticationManager authenticationManager, ApplicationUser applicationUser, bool isPersistent)
{
    authenticationManager.SignOut(
        DefaultAuthenticationTypes.ExternalCookie,
        DefaultAuthenticationTypes.ApplicationCookie);

    var identity = await this.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);

    // using default claim type from the framework
    identity.AddClaim(new Claim(ClaimTypes.Email, applicationUser.Email));

    authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

You can add your default claims to all users here as well. But there is IClaimsIdentityFactory class that is assigned in UserManager. There is only one method there:

public interface IClaimsIdentityFactory<TUser, TKey> where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
    /// <summary>
    /// Create a ClaimsIdentity from an user using a UserManager
    /// </summary>
    Task<ClaimsIdentity> CreateAsync(UserManager<TUser, TKey> manager, TUser user, string authenticationType);
}

Default AspNet Identity implementation creates ClaimsIdentity, adds the default claims described above, adds claims stored in the database for the user: IdentityUserClaims. You can override this implementation and slip-in your own logic/claims:

public class MyClaimsIdentityFactory : ClaimsIdentityFactory<ApplicationUser, string>
{
    public override async Task<ClaimsIdentity> CreateAsync(UserManager<ApplicationUser, string> userManager, ApplicationUser user, string authenticationType)
    {
        var claimsIdentity = await base.CreateAsync(userManager, user, authenticationType);

        claimsIdentity.AddClaim(new Claim("MyApplication:GroupId", "42"));

        return claimsIdentity;
    }
}

and assign it in UserManager:

public UserManager(MyDbContext dbContext)
    : base(new UserStore<ApplicationUser>(dbContext))
{
    // other configurations

    // Alternatively you can have DI container to provide this class for better application flexebility
    this.ClaimsIdentityFactory = new MyClaimsIdentityFactory();
}

When I’d like to find out about technologies used on the site, I look on HTTP header, then on cookies. Usually combination of these can give me a pretty detailed information about underlying technology used. Cookie names are very bad for that – search for any cookie name and you’ll get a lot of information about the technology.

To hide yourself, you can rename cookies from standard to something random. In Asp.Net Identity you can do that via CookieName property on CookieAuthenticationOptions class in configuration:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<UserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(0),
            regenerateIdentity: (manager, user) => manager.GenerateUserIdentityAsync(user))
    },
    CookieName = "jumpingjacks",
});

See the jumpingjacks string? that will be the cookie name when users login. You can find the full project source code in my Github repository

There are plenty of articles about how to deploy a solution to Azure Web-Sites. I’ll just leave this here for myself:

msbuild .\SolutionName.sln /p:DeployOnBuild=true /p:PublishProfile=ProfileName /p:Password=passwordForAzurePublishing /p:AllowUntrustedCertificate=true

This builds solution according to previously configured Publish Profile.

  • Good thing that all the configurations parameters are stored within Profile, where you can tell the thing to pre-compile the views and publish to folder where you need it.

  • Bad thing – you can’t specify where deploy to, as that is specified in the Publishing Profile. But you can configure different profiles to publish to testing and to production.

  • Another very bad thing – you can’t provide it with a pre-built web-deploy package, this builds the solution again every time you execute it. And this breaks the rule of Continuous Integration and Deployment: “Build once, deploy everywhere”. Suppose you have a Build Server with process that looks like this: Build => Run Unit Tests => Run Integration Tests => Deploy to Testing => Deploy to Production. And if for deployment you use the line I quoted above, you will be compiling your sources 3 times: first time to run tests, then every time to deploy. In some sense this is OK, because you are building from the same sources, but this is a waste of time. If I build my application with pre-compiled views, this can take a while. One of the applications I work on has 800 views and compilation of all these views takes about 7 minutes. If I compile them once, and re-use that, I don’t need to wait another 7 minutes for deployment to production. Well, OK, OK! Msbuild has got some clever stuff in it and probably will not re-compile all the views if nothing have changed and second time it’ll take less time to do compilation, but that still bothers me. Hopefully new Asp vNext will do something to make my life easier in this sense.

Last week I was updating one of applications I work on to ASP.NET Identity. For a specific reasons I could not deploy to Azure for a while. But I did run all the tests locally and everything worked just fine.

When I mostly finished with Identity conversion, I finally managed to deploy the application to Azure Web-Sites. And it worked fine.. until I tried registering a user.

At that point I had an exception exploding in my face:

System.Security.Cryptography.CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.

A bit of digging online did not give me any results. Everything single solution in google was talking about Windows Identity Foundation, but I was not using it. I only have ASP.NET Identity.

After a bit of digging turned out that my application could not generate a token for email confirmation. And that was handled like this:

public class UserManager : UserManager<ApplicationUser>
{
    public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext()))
    {
        // this does not work on azure!!!
        var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ASP.NET IDENTITY");
        this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))
        {
            TokenLifespan = TimeSpan.FromHours(24),
        };
    }
}

I have found this snippet somewhere online, but mostly had no idea what it does – cargo culting. My bad! And this very piece was causing issues when run on Azure Web-Sites.

When I replaced that snippet with more simple one, everything started to work as expected:

public class UserManager : UserManager<ApplicationUser>
{
    public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext()))
    {
        this.UserTokenProvider = new EmailTokenProvider<ApplicationUser, string>();
    }
}

Basically, if you use ASP.NET Identity and get CryptographicException when running your site on Microsoft Azure Web-Sites, most likely that is your token generation code. Replace it by framework provided EmailTokenProvider.

Email testing is always a pain. One of the “OOOPS” moments I had with email was when on testing instance of the application I started resetting user password. And the application started sending out actual emails to users. People did get “Your password reset link is here” and pointing to the testing instance of the application.

At that point I started wondering how can I isolate the emailing in production and emailing in dev and test environments. Production system must send out real emails to real users. Emails issued by testing and development installation must not send out emails to users, but rather have them collected somewhere. For a long time I had very basic configuration that checks if we are not in production environment, do not send emails at all. That worked fine for some time, but I lacked ability to check if emails were sent out or not.

There are many solutions for fake SMTP servers for dev-machines: you set up SMTP server on your machine, point your smpt credentials to this server and all emails are collected on that fake server. That works if you are just a one-man developer. If you have a team of devs, every single one of them must install this server, and for their home machines. A bit too much work for my liking. Also this approach does not work for testing environment – when the application is deployed to a web-server identical to production. And actual users are having a go on the system. Where do you install that fake server now? How can you show email messages to the user, without sending them?

Recently I came across Mailtrap.io. Mailtrap is hosted fake SMTP server. When you send email to their SMTP, it is not sent out anywhere, it is collected in inbox and can be validated against. Because this service is hosted, you don’t have to install anything, just re-point your SMTP credentials. And this works for developers on their local machines, for testers, for customers checking out testing environment.

Mailtrap has a descent free tier that allows me to have one fake inbox and one user to access the inbox. That is good enough just now. I’m not building email-heavy application and the only emails I’m sending are for password reset and for email confirmations. I’ve used this service for a month now and pretty happy with the way it works. As soon as I need more than a few emails per day, I’ll subscribe to their paid tier.

We use SendGrid for all our emailing needs and it works great for us: official C# client is provided via nuget, emails are sent out via API requests, not via SMTP (we had issues with network ports in our firewall).

We isolate all email sending into EmailService class which looks similar to this:

public class EmailService : IEmailService
{
    private readonly ITransport transportSmtp;

    public EmailService(ITransport transportSmtp)
    {
        this.transportSmtp = transportSmtp;
    }


    public Task SendEmail(MailAddress source, MailAddress destination, string htmlContent, string subject)
    {
        var message = new SendGridMessage();
        message.Html = htmlContent;
        message.From = source;
        message.To = new[] { destination };
        message.Subject = subject;

        return await transportSmtp.DeliverAsync(message);
    }        
}

Note that ITransport object is injected into this service. ITransport is SendGrid interface for email delivery service. It has 2 methods: Deliver(SendGrid message) and DeliverAsync(SendGrid message). And it does what it says on the tin – delivers email messages.

Now, for a long time my DI container (Autofac) was configured to create native SendGrid transport and pass it down to EmailService class, and if not in production environment, replace ITransport with NullTransport that does not do anything.

public class SmtpModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // Create an SMTP transport for sending email.
        builder.Register(c => GetTransport())
            .As<ITransport>()
            .InstancePerLifetimeScope();

        builder.Register<EmailService>().As<IEmailService>();

        base.Load(builder);
    }


    public static ITransport GetTransport()
    {
        if (/* check if not production. Usually a flag in web.config */)
        {
            return new NullTransport();
        }
        var networkCredential = new NetworkCredential("username", "password");

        var transportWeb = new SendGrid.Web(networkCredential);

        return transportWeb;
    }
}    

public class NullTransport : ITransport
{
    public void Deliver(SendGrid message)
    {
        // do nothing
    }

    public Task DeliverAsync(SendGrid message)
    {
        // do nothing
        return Task.FromResult(0);
    }
}

Now with MailTrap.io I can replace NullTransport for MailtrapTransport:

public class MailtrapTransport : ITransport
{
    public void Deliver(ISendGrid sendGridMessage)
    {
        var client = new SmtpClient
                     {
                         Host = "mailtrap.io",
                         Port = 123456,
                         Credentials = new NetworkCredential("user", "pass"),
                         EnableSsl = true,
                     };

        var mail = new MailMessage(sendGridMessage.From, sendGridMessage.To.First())
                   {
                       Subject = sendGridMessage.Subject,
                       Body = sendGridMessage.Html,
                       IsBodyHtml = true,
                   };

        client.Send(mail);
    }


    public Task DeliverAsync(ISendGrid message)
    {
        return Task.Factory.StartNew(() => Deliver(message));
    }
}

If you are not using DI, similar result can be achieved just in your EmailService:

    public void SendEmail(MailAddress source, MailAddress destination, string htmlContent, string subject)
    {
        var message = new SendGridMessage();
        message.Html = htmlContent;
        message.From = source;
        message.To = new[] { destination };
        message.Subject = subject;

        if(/*check if production */)
        {
            transportSmtp.Deliver(message);
            return;
        }
        // not in production, use mailtrap
        var client = new SmtpClient
                     {
                         Host = "mailtrap.io",
                         Port = 2525, // check port with Mailtrap settings
                         Credentials = new NetworkCredential("user", "pass"), // credentials for mailtrap inbox
                         EnableSsl = true,
                     };

        var mail = new MailMessage(sendGridMessage.From, sendGridMessage.To.First())
                   {
                       Subject = sendGridMessage.Subject,
                       Body = sendGridMessage.Html,
                       IsBodyHtml = true,
                   };

        client.Send(mail);
    }     

And now all my emails from dev and test environments are delivered to Mailtrap inbox. Pretty cool and now I don’t have to think about where emails should go and if I’m sending a test email to a real person.

Mailtrap provides a pretty elaborate API and I’ve managed to build a basic user interface for admin users of my application. Meaning my users will be able to see/read emails going out without emails reaching real people.

In addition to all this, you can write automated tests against their API to check if sent out emails were in correct format. But all my existing tests were using mock objects to mock-out ITransport and I did validate emails against mocks. However, I can see the appeal of testing actual emails. I’ll do that next time I need to validate the correctness of sent-out email.

I’ve spent a few hours trying to figure out why my code does not work, and I have not found any explanations to the issue, so might just write it down here.

In ASP.NET Identity there is a concept for user locking out. You can specify how many attempts user can gets before the lock-out kicks in and for how long the lockout is enabled. This is a widely known, from all the articles online. But what these articles don’t say is that users can be opted-in and opted-out from this process.

If you look on IdentityUser class, there are 2 fields that relate to lockout: LockoutEnabled and LockoutEndDateUtc. My first reaction was that LockoutEnabled says that user is locked-out and LockoutEndDateUtc is time when the lockout expires.

Turned out that I was wrong. LockoutEnabled is a flag saying that user can (or can not) be locked in principle. I.e. opt-in flag for locking. So if we have an admin user who we don’t want to lockout ever, we’ll set this flag to be false. And for the rest of user-base this should be set to true.

To check if user is locked-out use UserManager.IsLockedOutAsync(user.Id). Function UserManager.GetLockoutEnabledAsync() checks if user is opted in for lock-out, it does not check if user is actually locked-out.

And fields on IdentityUser – don’t use them to detect is user is locked out, they are lies! Use UserManager functions to detect user state.

Hope this will save some people a head-banging, cause that caused me some stress!

Update 27 Aug 2014

To enable locking-out UserManager should have these flags set:

//lockout users for 10 minutes
UserManager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);

// takes 6 incorrect attempts to lockout 
this.MaxFailedAccessAttemptsBeforeLockout = 6;

// when new user is created, they will be "lockable". 
this.UserLockoutEnabledByDefault = true;

To lockout user you can do this:

user.LockoutEnabled = true;
user.LockoutEndDateUtc = DateTime.UtcNow.AddMinutes(42);
await userManager.UpdateAsync(user);

This will set the user to be locked out for 42 minutes from now. However, this is not recommended way to lock-out user, this is what the framework does in the background. There are ways users can lock themselves out.

If you are updated to AspNet Identity 2.1 (which has been released recently). You should use SignInManager:

var signInManager = new SignInManager(userManager, authenticationManager);
var signInStatus = await signInManager.PasswordSignInAsync(username, password, isPersistent, shouldLockout);

If shouldLockout is true, user is getting locked out after a number of failed attempts to login.

PasswordSignInAsync method does the following steps:

  • checks if user with given username exists;
  • then checks if this user is not locked out;
  • if password is correct, redirects logic to 2FA (if it is enabled);
  • if shouldLockout is true, then on incorrect password increases number of failed log-ins on user record.

If you have not updated and still using Identity v2.0 do the following. On every failed attempt to login, call the following

await userManager.AccessFailedAsync(user.Id); 

IdentityUser class have property AccessFailedCount. The method above increases count on this property. If count is greater than UserManager.MaxFailedAccessAttemptsBeforeLockout, then user is getting locked out: user.LockoutEndDateUtc is set to a date in the future and resets AccessFailedCount to zero.

When user is signed-in successfully, you need to reset AccessFailedCount to zero. Do it by calling:

await userManager.ResetAccessFailedCountAsync(user.Id);

Recently I’ve migrated my project to ASP.NET Identity. One of the features I had in the project is “Impersonation”. Administrators could impersonate any other user in the system. This is a strange requirement, but business behind the project wanted it.

This is the old impersonation way:

  1. When admin wanted impersonation, system would serialise information about admin account (mostly username).
  2. Find account for impersonated user
  3. Create a new authentication cookie for impersonated user
  4. As data add serialised information about admin account to the cookie
  5. Set the cookie
  6. Redirect admin to client page.
  7. Bingo, admin logged in as a client user.

To de-impersonate repeate the process in reverse. Get data about admin from cookie data (if it is present), delete cookie for client-user, login admin user again. Bingo, admin is logged in as admin again.

Here is the article how the old way is implemented

This exact code did not work with Identity framework. I tried finding the solution online, but nothing was available. My question on Stackoverslow immediately got 4 up-votes, but no answers. So people are interested in doing it, but nobody published any material on this. So here I am -)

Claims

New Identity framework works with Claims. Claim is a bit of information (think string key-value pair) that is attached to a user. You can store a claim in database and it is restored every time when you get a user from a storage. Or you can assign claims to a user before signing them in. Later on you can easily check if a user has a claim. Think of this like checking a dictionary of strings if there is a required key with a required value, or extract a value from dictionary by a key. Probably this is clear as mud, but bear with me, I’ll get to a code and it’ll become all clear.

Impersonation

To get admin user logged in as somebody else – not a problem. Delete old auth-cookie, create a new one for another user, redirect. The problem is to detect that admin is impersonating. And then to de-impersonte the admin, but don’t allow other users to de-impersonate. So here I’m creating a new user identity and add extra claims to the user, saying impersonation is going on and who is impersonating. So here is the code:

public async Task ImpersonateUserAsync(string userName)
{
    var context = HttpContext.Current;

    var originalUsername = context.User.Identity.Name;

    var impersonatedUser = await userManager.FindByNameAsync(userName);

    var impersonatedIdentity = await userManager.CreateIdentityAsync(impersonatedUser, DefaultAuthenticationTypes.ApplicationCookie);
    impersonatedIdentity.AddClaim(new Claim("UserImpersonation", "true"));
    impersonatedIdentity.AddClaim(new Claim("OriginalUsername", originalUsername));

    var authenticationManager = context.GetOwinContext().Authentication;
    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, impersonatedIdentity);
}

This is pretty standard way Identity framework is logging in users. Only here we add extra claims – one for “Yes, impersonation is happening” and another one for “Original username is admin”.

First is used to detect if we are impersonating, second is to de-impersonate the user back into admin rights.

To detect if impersonation happens here is an extension method:

public static bool IsImpersonating(this ClaimsPrincipal principal)
{
    if (principal == null)
    {
        return false;
    }

    return principal.HasClaim("UserImpersonation", "true");
}

And this would be used like this:

if(ClaimsPrincipal.Current.IsImpersonating())
{
    // do my stuff for admins
}

To get original username, use this extension method:

public static String GetOriginalUsername(this ClaimsPrincipal principal)
{
    if (principal == null)
    {
        return String.Empty;
    }

    if (!principal.IsImpersonating())
    {
        return String.Empty;
    }

    var originalUsernameClaim = principal.Claims.SingleOrDefault(c => c.Type == "OriginalUsername");

    if (originalUsernameClaim == null)
    {
        return String.Empty;
    }

    return originalUsernameClaim.Value;
}

And this is how de-impersonation happens:

public async Task RevertImpersonationAsync()
{
    var context = HttpContext.Current;

    if (!ClaimsPrincipal.Current.IsImpersonating())
    {
        throw new Exception("Unable to remove impersonation because there is no impersonation");
    }


    var originalUsername = ClaimsPrincipal.Current.GetOriginalUsername();

    var originalUser = await userManager.FindByNameAsync(originalUsername);

    var impersonatedIdentity = await userManager.CreateIdentityAsync(originalUser, DefaultAuthenticationTypes.ApplicationCookie);
    var authenticationManager = context.GetOwinContext().Authentication;

    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, impersonatedIdentity);
}

This is the basics of my process. I have a bit more checks and validations in place, mostly for null references. Also as a claim I store return url, where admin have started impersonation, so admin can be redirected to the original location where they started from. Also userManager is an instance of UserManager<User> that was injected by a constructor. I skipped that for brevity.

I’m pretty sure there is a better way to handle this. If you know it, please let me know in comments.

In the office we use StyleCop to make sure everyone writes code in the same style. And all of us have StyleCop installed coupled with Resharper. So whenever you have a violation of StyleCop rule, Resharper highlights the issue via squiggly line. And all our projects do conform to our StyleCop settings.

But I do look on code of many other projects – I have source code for most of the dependencies we use, like Entity Framework, Nlog, etc. And looking on other people projects is painful because of StyleCop:

See these lines – they annoy me. And just make code unreadable. And there is no simple way to turn off StyleCop in R# or VS, you’ll have to suck it up.

Or follow instructions in this post: http://stylecop.codeplex.com/discussions/285902
Basically there people say create Settings.Stylecop file with the following contents:

<StyleCopSettings Version="105">
  <GlobalSettings>
    <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
  </GlobalSettings>
</StyleCopSettings>

and place it in the folder next to *.sln file. This disables all the StyleCop rules for the solution.

For my own convenience, I’ll place this file here: settings.StyleCop
You’ll have to remove .txt extension to make things work. Otherwise your antivirus might not like the file.

settings.StyleCop
Title: settings.StyleCop (0 click)
Caption:
Filename: settings.StyleCop.txt
Size: 169 B