Closed
Description
Background and Motivation
Add alternative authentication scheme support a number of SignInManager
APIs that support features such as 2fa and lockout.
Proposed API
// Microsoft.AspNetCore.Identity.dll
namespace namespace Microsoft.AspNetCore.Identity;
public class SignInManager<TUser> where TUser : class
{
+ public string PrimaryAuthenticationScheme { get; set; } = IdentityConstants.ApplicationScheme;
}
Usage Examples
routeGroup.MapPost("/login", async Task<Results<Ok<AccessTokenResponse>, ProblemHttpResult, IResult>>
([FromBody] LoginRequest login, [FromQuery] bool? cookieMode, [FromQuery] bool? persistCookies, [FromServices] IServiceProvider sp) =>
{
var signInManager = sp.GetRequiredService<SignInManager<TUser>>();
signInManager.PrimaryAuthenticationScheme = cookieMode == true ? IdentityConstants.ApplicationScheme : IdentityConstants.BearerScheme;
var isPersistent = persistCookies ?? true;
var result = await signInManager.PasswordSignInAsync(login.Username, login.Password, isPersistent, lockoutOnFailure: true);
if (result.RequiresTwoFactor)
{
if (!string.IsNullOrEmpty(login.TwoFactorCode))
{
result = await signInManager.TwoFactorAuthenticatorSignInAsync(login.TwoFactorCode, isPersistent, rememberClient: isPersistent);
}
else if (!string.IsNullOrEmpty(login.TwoFactorRecoveryCode))
{
result = await signInManager.TwoFactorRecoveryCodeSignInAsync(login.TwoFactorRecoveryCode);
}
}
if (result.Succeeded)
{
// The signInManager already produced the needed response in the form of a cookie or bearer token.
return TypedResults.Empty;
}
return TypedResults.Problem(result.ToString(), statusCode: StatusCodes.Status401Unauthorized);
});
Alternative Designs
Add half a dozen or more overloads to PasswordSignInAsync
, TwoFactorAuthenticatorSignInAsync
, TwoFactorRecoveryCodeSignInAsync
, etc... that take the primary authentication scheme.
Maybe come up with a better name.
Risks
We have to add even more properties like this in the future and all the state becomes unweildy.