ASP.NET Core 3.1 - 2FA Cookie Schemes
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
Creation Series
- ASP.NET Core 3.1 - Users Without Identity
- ASP.NET Core 3.1 - User Entity
- ASP.NET Core 3.1 - Password Hasher
- ASP.NET Core 3.1 - User Management
- ASP.NET Core 3.1 - Admin Role
- ASP.NET Core 3.1 - Cookie Validator
- ASP.NET Core 3.1 - Concurrency Conflicts
- ASP.NET Core 3.1 - Must Change Password
- ASP.NET Core 3.1 - User Database Service
- ASP.NET Core 3.1 - Rename Related Entities
2FA Series
- ASP.NET Core 3.1 - 2FA Without Identity
- ASP.NET Core 3.1 - 2FA User Tokens
- ASP.NET Core 3.1 - 2FA Cookie Schemes
- ASP.NET Core 3.1 - 2FA Authenticating
- ASP.NET Core 3.1 - 2FA Sign In Service
- ASP.NET Core 3.1 - 2FA QR Code Generator
- ASP.NET Core 3.1 - Admin 2FA Requirement
- ASP.NET Core 3.1 - 2FA Admin Override
Enhanced User Series
- ASP.NET Core 3.1 - Enhanced User Without Identity
- ASP.NET Core 3.1 - 2FA Recovery Codes
- ASP.NET Core 3.1 - Login Lockout
- ASP.NET Core 3.1 - Created And Last Login Date
- ASP.NET Core 3.1 - Security Stamp
- ASP.NET Core 3.1 - Token Service
- ASP.NET Core 3.1 - Confirmed Email Address
- ASP.NET Core 3.1 - Password Recovery
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.
Update 02/23/2021
I added the Enhanced User Series' article links.
Comments(0)