ASP.NET Core 3.1 - 2FA Cookie Schemes

Ken Haggerty
Created 08/20/2020 - Updated 02/24/2021 00:01

This article will demonstrate the implementation of multiple cookie schemes like ASP.NET Core Identity. I will assume you have downloaded the ASP.NET Core 3.1 - Users Without Identity Project or created a new ASP.NET Core 3.1 Razor Pages project. See Tutorial: Get started with Razor Pages in ASP.NET Core. You should review the earlier articles of the Users Without Identity Project series.

Users Without Identity Project and Article Series

The UWIP used the single CookieAuthenticationDefaults. AuthenticationScheme before I implemented 2FA cookie schemes like ASP.NET Core Identity. The UWIP now employs the multiple cookie schemes with ApplicationScheme and 2 additional 2FA schemes TwoFactorUserIdScheme, and TwoFactorRememberMeScheme. I developed a UWIPConstants class to represent the cookie scheme and claim names.

Entities > UWIPConstants.cs:
//
// Summary:
//     Represents values used to configure the cookies and claims.
public class UWIPConstants
{
    //
    // Summary:
    //     The scheme used to identify application authentication cookies.
    public static readonly string ApplicationScheme = "UWIP.ApplicationScheme";
    //
    // Summary:
    //     The scheme used to identify Two Factor authentication cookies for saving the Remember Me state.
    public static readonly string TwoFactorRememberMeScheme = "UWIP.TwoFactorRememberMeScheme";
    //
    // Summary:
    //     The scheme used to identify Two Factor authentication cookies for round tripping user identities.
    public static readonly string TwoFactorUserIdScheme = "UWIP.TwoFactorUserIdScheme";
    //
    // Summary:
    //     The claim type used to hold the user's TwoFactorEnabled state.
    public static readonly string TwoFactorEnabledClaimType = "UWIP.TwoFactorEnabledClaimType";
    //
    // Summary:
    //     The claim type used to redirect a user to the change password page.
    public static readonly string MustChangePasswordClaimType = "UWIP.MustChangePasswordClaimType";
    //
    // Summary:
    //     The value used to identify the source of the Two Factor authentication key.
    public static readonly string TwoFactorLoginProvider = "AppUserTokens";
    //
    // Summary:
    //     The value used to identify the MultiFactor authentication method.
    public static readonly string MultiFactorAuthentication = "MultiFactor";
    //
    // Summary:
    //     The value used to identify the Password only authentication method.
    public static readonly string PasswordAuthentication = "Password";
    //
    // Summary:
    //     The value used to identify the Admins policy.
    public static readonly string AdminsPolicy = "Admins";
    //
    // Summary:
    //     The value used to identify the Admin role.
    public static readonly string AdminRole = "Admin";        

    public UWIPConstants() { }
}

The CookieAuthenticationDefaults .AuthenticationScheme provides default paths for Login, Logout, and AccessDenied.

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.Events = new CookieAuthenticationEvents
        {
            OnValidatePrincipal = CookieValidator.ValidateAsync
        };
    });

With multiple schemes, you configure the options for each scheme and declare the default scheme with the AddAuthentication parameter.

Edit Startup.cs > ConfigureServices:
services.AddAuthentication(UWIPConstants.ApplicationScheme)
    .AddCookie(UWIPConstants.ApplicationScheme, options =>
    {
        options.LoginPath = "/Account/Login";
        options.LogoutPath = "/Account/Logout";
        options.AccessDeniedPath = "/Account/AccessDenied";
        options.SlidingExpiration = true;
        options.Events = new CookieAuthenticationEvents
        {
            OnValidatePrincipal = CookieValidator.ValidateAsync
        };
    })
    .AddCookie(UWIPConstants.TwoFactorUserIdScheme, options =>
    {
        options.Cookie.Name = UWIPConstants.TwoFactorUserIdScheme;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
    })
    .AddCookie(UWIPConstants.TwoFactorRememberMeScheme, options =>
    {
        options.Cookie.Name = UWIPConstants.TwoFactorRememberMeScheme;
    });

The ApplicationScheme cookie is applied when the user is authenticated. The TwoFactorUserIdScheme cookie is applied when a user who has 2FA enabled, successfully signs in with a username and password. The TwoFactorUserIdScheme cookie has a 5 minute ExpireTimeSpan and is used to transfer the user id from the log in page and the 2FA log in page.

The TwoFactorRememberMeScheme cookie is used to optionally remember the browser used with 2FA authentication. This cookie will persist on the browser after the user signs out. Future sign ins by the same user on the same browser will authenticate the user without 2FA verification until the browser is forgotten.

2FA Remember Machine
2FA Forget Browser
Update 02/23/2021

I added the Enhanced User Series' article links.

Article Tags:

2FA Authorization

Comment Count = 0

Please log in to comment.

Login Register
Logged in users receive web notifications.
Web Notifications