A Taste of ASP.NET Identity

Reference:
https://channel9.msdn.com/Series/Customizing-ASPNET-Authentication-with-Identity/01
https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity

ASP.NET identity is a big topic. It’s quite complicated and sometimes hard to understand. Here is just a taste of ASP.NET identity.

The ASP.NET identity core system is made up of Mangers and Stores. The Managers are high-level classes, and they can make some advanced operations such as create users. Just like the service layer in the previous post, they talk to stores via interface. And Stores talk to data access layer and they can store users, roles and claims. In addition, they can only provide limited functionality of the data operation (like the repository layer). Here is the diagram:

Usually we use UserManager and the higher level class SignInManager, or the overridden version  ApplicationUserManager or ApplicationSignInManager. The user model of the identity system is IdentityUser, which corresponding to the dbo.AspNetUsers table in database. Here is the more detailed diagram for user part:

Let’s begin with Startup.cs, which is the application entrance:

namespace AucklandHighSchool
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

Then go further into ConfigureAuth:

namespace AucklandHighSchool
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context, user manager and signin manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

            // Configure the sign in cookie
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    // Enables the application to validate the security stamp when the user logs in.
                    // This is a security feature which is used when you change a password or add an external login to your account.  
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });            
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
            app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
        }
    }
}

You can configure almost everything here or in IdentityConfig.cs about the identity system. And in IdentityModels.cs, you can also change you connection string of the database:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("AucklandHighSchoolEntities2", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

Creating A User

Launch the application and then click on the Register link to create a user. The following image shows the Register page which collects the user name and password.

When the user clicks the Register button, the Register action of the Account controller creates the user by calling the ASP.NET Identity API, as in line 8-9:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

Log In

If the user was successfully created, she is logged in by the SignInAsync method. In SignInAsync method:

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

    var identity = await UserManager.CreateIdentityAsync(
       user, DefaultAuthenticationTypes.ApplicationCookie);

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

The code line 5 above in the SignInAsync method generates a ClaimsIdentity. Since ASP.NET Identity and OWIN Cookie Authentication are claims-based system, the framework requires the app to generate a ClaimsIdentity for the user. ClaimsIdentity has information about all the claims for the user, such as what roles the user belongs to. You can also add more claims for the user at this stage.

The code line 8 above in the SignInAsync method signs in the user by using the AuthenticationManager from OWIN and calling SignIn and passing in the ClaimsIdentity.

Log Off

Clicking the Log off link calls the LogOff action in the account controller.

// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    AuthenticationManager.SignOut();
    return RedirectToAction("Index", "Home");
}

The code line 6 above shows the OWIN AuthenticationManager.SignOut method. This is analogous to FormsAuthentication.SignOut method used by the FormsAuthentication module in Web Forms.

 

1 comment

  1. birds says:

    Hi! I could have sworn I’ve been to this website before but after browsing through some of the post I
    realized it’s new to me. Nonetheless, I’m definitely delighted I found it and I’ll be bookmarking and checking back frequently!

Leave a Reply

Your email address will not be published. Required fields are marked *