ASP.NET Core - Write a Simple Cookie Authentication
Tags: dotnet, csharp, aspnet, authentication
Published: 2022-08-26 14:45:00

Here is a quick guide on writing cookie authentication without using ASP.NET Identity.

1. Add authentication service and `HttpContextAccessor`.

    ```cs
    builder.Services.AddAuthentication("MyAuthScheme")
        .AddCookie("MyAuthScheme", options => {
            options.LoginPath = "/Login";
            options.LogoutPath = "/Logout";        
            options.AccessDeniedPath = "/AccessDenied";
        });

    builder.Services.AddHttpContextAccessor();
    ```
    Note that `"MyAuthScheme"` will be used throughout.

2. Configure HTTP request pipeline.

    ```cs
    app.UseAuthentication();
    app.UseAuthorization();

    app.MapRazorPages();
    app.MapControllers();
    ```

3. In your login page, add:
    ```cs
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authorization;
    using System.Security.Claims;
    ```
    In your login page constructor, inject `_httpContextAccessor` like so:
    ```cs
    private readonly IHttpContextAccessor _httpContextAccessor;
    public Login(IHttpContextAccessor httpContextAccessor){ 
        _httpContextAccessor = httpContextAccessor;
    }
    ```
    Actual login:
    ```cs
    // Validate login credentials here and get user details.

    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id),
        new Claim(ClaimTypes.Name, user.Username),
        new Claim(ClaimTypes.Email, user.Email)
        // add or remove claims as necessary    
    };

    var claimsIdentity = new ClaimsIdentity(claims, "MyAuthScheme");

    await _httpContextAccessor.HttpContext
        .SignInAsync("MyAuthScheme",
            new ClaimsPrincipal(claimsIdentity),
            new AuthenticationProperties());

    // Redirect here
    ```
    This code creates a cookie with the name `.AspNetCore.MyAuthScheme`.

4. Sign out codes: 

    ```cs
    await _httpContextAccessor.HttpContext
                .SignOutAsync("MyAuthScheme");

    // Redirect to login or other page
    ```
    This removes the cookie `.AspNetCore.MyAuthScheme`
5. You can now put `Authorize` attribute on your pages, controllers or enpoints that require authenticated users.
    ```cs
    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class ProductsController : BaseController { ... } 
    ```
    Or you can specify scheme(s):
    ```cs
    [Authorize(AuthenticationSchemes = "MyAuthScheme,JwtScheme")]
    ```

6. To check manually or to access claims in Controller or Razor page:

    ```cs
    if(User.Identity.IsAuthenticated) {
        
        var username = User.Identity.Name;
        var email = User.Claims.Where(i => i.Type == "Email").FirstOrDefault().Value;
    }
    ```
    To access in `.cshtml`:
    ```cs
    @if(User.Identity.IsAuthenticated) {
        <p>@User.Identity.Name</p>
        <p>@User.Claims.Where(i => i.Type == "Email").FirstOrDefault().Value</p>
    }
    ```
    In other parts of the website, inject `IHttpContextAccessor`:
    ```cs
    if(_httpContextAccessor.HttpContext
        .User.Identity.IsAuthenticated) {
        //do something
    }
    ```
    
## Resource
[Microsoft Docs - Authentication](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-6.0)