Cookie authentication in ASP.NET CORE

Posted by leeharvey09 on Mon, 08 Jul 2019 20:08:57 +0200

Original: Cookie authentication in ASP.NET CORE

Everyone must have used FormsAuthentication to authenticate the login user when using ASP.NET. The core of FormsAuthentication is Cookie, ASP.NET stores the user name in Cookie.

Now is the era of ASP.NET CORE, but ASP.NET CORE does not have FormsAuthentication, so how do I authenticate?The answer is that ASP.NET CORE has built-in Cookie authentication for us and is very convenient to use. Note that this article is based on ASP.NET CORE version 2.0 to illustrate the Cookie authentication method.

 

1. Enable Cookie authentication from the ASP.NET CORE OWIN framework

To use Cookie authentication in ASP.NET CORE, the first step is to enable the Cookie authentication Middleware in the project's OWIN framework file Startup.cs.

First, we use services.AddAuthentication in the ConfigureServices method in Startup to register the Cookie Certification Service, as shown in the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    //register Cookie Certification Services
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}

Then use app.UseAuthentication in the Configure method in Startup to enable Cookie-certified middleware (note that app.UseAuthentication and app.UseMvc cannot be invoked in reverse order), as shown in the following code:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    //Be careful app.UseAuthentication Method must be placed below app.UseMvc Method is called before or after HttpContext.SignInAsync After the user logs in, use
    //HttpContext.User Or it will show that the user is not logged in, and HttpContext.User.Claims No information was read from the logged-in user.
    //This explanation Asp.Net OWIN In Frame MiddleWare The order in which calls are made can have a significant impact on system functionality. MiddleWare The invocation order must not be reversed
    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });

            
}

By the way, what app.UseAuthentication does? App.UseAuthentication enables Authentication middleware, which sets the HttpContext.User property based on the Cookie information in the current Http request (used later), so only middleware registered after the app.UseAuthentication methodThe value can only be read from HttpContext.User, which is why it is emphasized above that the app.UseAuthentication method must precede the app.UseMvc method below, because only then can the value of HttpContext.User be read from the MVC middleware of ASP.NET Core.

 

 

2. Logged-in users

The method of using Cookie authentication to log in users in ASP.NET CORE is different from traditional FormsAuthentication, with the following general steps:

  • Create an array of Claim types that stores all information about the logged-in user, such as the user name, in a string key pair of Claim types
  • Pass an array of ClaimsIdentity types created above into ClaimsIdentity to construct a ClaimsIdentity object
  • Pass the ClaimsIdentity object created above into ClaimsPrincipal to construct a ClaimsPrincipal object
  • Call the HttpContext.SignInAsync method, pass in the laimsPrincipal object created above, and complete the user login

So we can see that the whole Cookie authentication login process for ASP.NET CORE is much more complicated than FormsAuthentication for ASP.NET, since a FormsAuthentication.SetAuthCookie method was developed before.

 

In this example, we created an Acion method Login in the project's default HomeController to implement user login code.Of course, here we implement the simplest Cookie login. In the code below, you can actually set whether or not the cookie is persisted, how long the cookie expires, what is the name of the cookie that stores the login user information, etc. We won't do much about it. You can read the last two official documents recommended in this article to learn more.

The code for the Login method is as follows:

/// <summary>
/// this Action log on user Wangdacui reach Asp.Net Core
/// </summary>
public IActionResult Login()
{
    //The following variables claims yes Claim An array of types, Claim yes string Key-value pairs of types, so claims Any user-related information can be stored in the array.
    //Note, however, that this information is encrypted and stored in the client browser cookie , so it's best not to store too much particularly sensitive information, where we only store user names to claims array,
    //Indicates who is currently logged in
    var claims = new[] { new Claim("UserName", "Wangdacui") };

    var claimsIdentity = new ClaimsIdentity(
    claims,
    CookieAuthenticationDefaults.AuthenticationScheme);

    ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity);

    Task.Run(async () =>
    {
        //Login user, equivalent to ASP.NET In FormsAuthentication.SetAuthCookie
        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);

        //have access to HttpContext.SignInAsync Method overload to define persistence cookie Storing user authentication information, such as the code below, defines the 60 minutes after a user logs in cookie Will remain on the client computer's hard drive,
        //Even if the user closes the browser, re-visiting the site within 60 minutes is still logged in unless called Logout Method Logoff.
        //Notice the AllowRefresh Property, if AllowRefresh by true,Indicates if the user has logged in more than 50%Of ExpiresUtc By visiting the site again within the interval, you increase the user's login time (which is really an extension) cookie The retention time on the hard disk of the client computer,
        //For example, in this example, we set the following ExpiresUtc After 60 minutes, when a user visits the site within 30 minutes or less after logging in, the user's login status is extended to 60 minutes after the current time.However, a user's access to the site within 30 minutes of login does not extend the login time.
        //because ASP.NET Core There is a hard requirement that users exceed 50%Of ExpiresUtc The site is visited again within the interval to extend the user's login time.
        //If AllowRefresh by false,Indicates that within 60 minutes of a user's login, whether they have visited the site or not, they will be non-logged in as soon as 60 minutes arrive (no extension) cookie Retention time on client computer hard disk, automatically deleted by client computer in 60 minutes cookie)
        /*
        await HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,
        user, new AuthenticationProperties()
        {
            IsPersistent = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
            AllowRefresh = true
        });
        */

    }).Wait();

    return View();
}

If the current Http request originally logged in to User A and now calls the HttpContext.SignInAsync method to log in to User B, that would be equivalent to logging out of User A and Logging in to User B

 

 

3. Read login user information

So how can users read the information (such as user name) of the logged-in user after they log in?We demonstrate how to determine if the current user is logged in and read out the user name of the logged in user in the Index method of HomeController. The code for the Index method is as follows:

/// <summary>
/// this Action Determine if the user is already logged in and, if so, read the user name of the logged in user
/// </summary>
public IActionResult Index()
{
    //If HttpContext.User.Identity.IsAuthenticated by true,
    //perhaps HttpContext.User.Claims.Count()A greater than 0 indicates that the user is logged in
    if (HttpContext.User.Identity.IsAuthenticated)
    {
        //Through here HttpContext.User.Claims Can we Login this Action Stored in cookie All in
        //claims Read out the key-value pairs, like the one we just defined UserName Value of Wangdacui It's here that I read it
        var userName = HttpContext.User.Claims.First().Value;
    }

    return View();
}

Note that it is better to use HttpContext.User.Identity.IsAuthenticated to determine if a user is logged in

 

 

4. Log off users

So how do I log out after logging in?We demonstrated how to log off a logged-in user in the Logout method of the HomeController with the following code:

/// <summary>
/// this Action from Asp.Net Core Logged-off users in
/// </summary>
public IActionResult Logout()
{
    Task.Run(async () =>
    {
        //Log off user, equivalent to ASP.NET In FormsAuthentication.SignOut  
        await HttpContext.SignOutAsync();
    }).Wait();

    return View();
}

If there is no logon user for the current Http request, there will be no error calling the HttpContext.SignOutAsync method

 

 

5. Load Balancing

 

Warning:
ASP.NET Core uses ASP.NET Core data protection stack Implement Cookie authentication.If ASP.NET Core Data Protection must be configured in a server cluster, see Configuring data protection .If your ASP.NET Core site uses load balancing to deploy multiple instances, configure ASP.NET Core Data Protection or ASP.NET CORE will fail Cookie authentication across multiple instances.

You can also refer to: Host ASP.NET Core in a web farm

How to manage expired key s for ASP.NET Core Data Protection can be seen: Data Protection - how to manage expired key? 

 

 

As mentioned earlier, Cookie authentication in ASP.NET CORE actually allows you to set the name of the cookie, persist the storage, etc. You can refer to the following two official documents for information:

Using Cookie Authentication without ASP.NET Core Identity

Cutting Edge - Cookies, Claims and Authentication in ASP.NET Core

Topics: PHP less