Creates IBackOfficeSignInManager interface

This commit is contained in:
Shannon
2020-11-30 22:46:05 +11:00
parent 6176046053
commit efff96f711
10 changed files with 69 additions and 31 deletions

View File

@@ -14,11 +14,11 @@ namespace Umbraco.Tests.Integration.TestServerTest
{
public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly BackOfficeSignInManager _backOfficeSignInManager;
private readonly IBackOfficeSignInManager _backOfficeSignInManager;
private readonly BackOfficeIdentityUser _fakeUser;
public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, BackOfficeSignInManager backOfficeSignInManager, IUserService userService, UmbracoMapper umbracoMapper)
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IBackOfficeSignInManager backOfficeSignInManager, IUserService userService, UmbracoMapper umbracoMapper)
: base(options, logger, encoder, clock)
{
_backOfficeSignInManager = backOfficeSignInManager;

View File

@@ -51,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Controllers
{
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
private readonly IBackOfficeUserManager _userManager;
private readonly BackOfficeSignInManager _signInManager;
private readonly IBackOfficeSignInManager _signInManager;
private readonly IUserService _userService;
private readonly ILocalizedTextService _textService;
private readonly UmbracoMapper _umbracoMapper;
@@ -73,7 +73,7 @@ namespace Umbraco.Web.BackOffice.Controllers
public AuthenticationController(
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
IBackOfficeUserManager backOfficeUserManager,
BackOfficeSignInManager signInManager,
IBackOfficeSignInManager signInManager,
IUserService userService,
ILocalizedTextService textService,
UmbracoMapper umbracoMapper,

View File

@@ -52,7 +52,7 @@ namespace Umbraco.Web.BackOffice.Controllers
private readonly IGridConfig _gridConfig;
private readonly BackOfficeServerVariables _backOfficeServerVariables;
private readonly AppCaches _appCaches;
private readonly BackOfficeSignInManager _signInManager;
private readonly IBackOfficeSignInManager _signInManager;
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
private readonly ILogger<BackOfficeController> _logger;
private readonly IJsonSerializer _jsonSerializer;
@@ -68,7 +68,7 @@ namespace Umbraco.Web.BackOffice.Controllers
IGridConfig gridConfig,
BackOfficeServerVariables backOfficeServerVariables,
AppCaches appCaches,
BackOfficeSignInManager signInManager,
IBackOfficeSignInManager signInManager,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
ILogger<BackOfficeController> logger,
IJsonSerializer jsonSerializer,

View File

@@ -31,7 +31,7 @@ namespace Umbraco.Extensions
.AddDefaultTokenProviders()
.AddUserStore<BackOfficeUserStore>()
.AddUserManager<IBackOfficeUserManager, BackOfficeUserManager>()
.AddSignInManager<BackOfficeSignInManager>()
.AddSignInManager<IBackOfficeSignInManager, BackOfficeSignInManager>()
.AddClaimsPrincipalFactory<BackOfficeClaimsPrincipalFactory<BackOfficeIdentityUser>>();
// Configure the options specifically for the UmbracoBackOfficeIdentityOptions instance

View File

@@ -7,7 +7,7 @@ namespace Umbraco.Extensions
public static class IdentityBuilderExtensions
{
/// <summary>
/// Adds a <see cref="UserManager{TUser}"/> for the <seealso cref="UserType"/>.
/// Adds a <see cref="UserManager{TUser}"/> implementation for <seealso cref="BackOfficeIdentityUser"/>
/// </summary>
/// <typeparam name="TUserManager">The type of the user manager to add.</typeparam>
/// <typeparam name="TInterface"></typeparam>
@@ -18,5 +18,19 @@ namespace Umbraco.Extensions
identityBuilder.Services.AddScoped(typeof(TInterface), typeof(TUserManager));
return identityBuilder;
}
/// <summary>
/// Adds a <see cref="SignInManager{TUser}"/> implementation for <seealso cref="BackOfficeIdentityUser"/>
/// </summary>
/// <typeparam name="TInterface"></typeparam>
/// <typeparam name="TSignInManager"></typeparam>
/// <param name="identityBuilder"></param>
/// <returns></returns>
public static IdentityBuilder AddSignInManager<TInterface, TSignInManager>(this IdentityBuilder identityBuilder) where TSignInManager : SignInManager<BackOfficeIdentityUser>, TInterface
{
identityBuilder.AddSignInManager<TSignInManager>();
identityBuilder.Services.AddScoped(typeof(TInterface), typeof(TSignInManager));
return identityBuilder;
}
}
}

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Web.BackOffice.Filters
private readonly IEntityService _entityService;
private readonly ILocalizedTextService _localizedTextService;
private readonly IOptions<GlobalSettings> _globalSettings;
private readonly BackOfficeSignInManager _backOfficeSignInManager;
private readonly IBackOfficeSignInManager _backOfficeSignInManager;
private readonly IBackOfficeAntiforgery _backOfficeAntiforgery;
public CheckIfUserTicketDataIsStaleFilter(
@@ -44,7 +44,7 @@ namespace Umbraco.Web.BackOffice.Filters
IEntityService entityService,
ILocalizedTextService localizedTextService,
IOptions<GlobalSettings> globalSettings,
BackOfficeSignInManager backOfficeSignInManager,
IBackOfficeSignInManager backOfficeSignInManager,
IBackOfficeAntiforgery backOfficeAntiforgery)
{
_requestCache = requestCache;

View File

@@ -19,19 +19,17 @@ namespace Umbraco.Web.Common.Security
using Constants = Umbraco.Core.Constants;
// TODO: There's potential to extract an interface for this for only what we use and put that in Core without aspnetcore refs, but we need to wait till were done with it since there's a bit to implement
public class BackOfficeSignInManager : SignInManager<BackOfficeIdentityUser>
public class BackOfficeSignInManager : SignInManager<BackOfficeIdentityUser>, IBackOfficeSignInManager
{
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs
private const string UmbracoSignInMgrLoginProviderKey = "LoginProvider";
// borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs
private const string UmbracoSignInMgrXsrfKey = "XsrfId";
private const string UmbracoSignInMgrXsrfKey = "XsrfId";
private BackOfficeUserManager _userManager;
private readonly IBackOfficeExternalLoginProviders _externalLogins;
private readonly GlobalSettings _globalSettings;
public BackOfficeSignInManager(
BackOfficeUserManager userManager,
@@ -75,7 +73,7 @@ namespace Umbraco.Web.Common.Security
return await HandleSignIn(null, userName, SignInResult.Failed);
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
}
/// <inheritdoc />
public override async Task<BackOfficeIdentityUser> GetTwoFactorAuthenticationUserAsync()
{
@@ -122,7 +120,7 @@ namespace Umbraco.Web.Common.Security
return await HandleSignIn(user, user?.UserName, SignInResult.Failed);
}
/// <inheritdoc />
public override bool IsSignedIn(ClaimsPrincipal principal)
{
@@ -204,7 +202,7 @@ namespace Umbraco.Web.Common.Security
//await Context.SignOutAsync(Constants.Security.BackOfficeTwoFactorAuthenticationType);
}
/// <inheritdoc />
public override async Task<bool> IsTwoFactorClientRememberedAsync(BackOfficeIdentityUser user)
{
@@ -216,7 +214,7 @@ namespace Umbraco.Web.Common.Security
return (result?.Principal != null && result.Principal.FindFirstValue(ClaimTypes.Name) == userId);
}
/// <inheritdoc />
public override async Task RememberTwoFactorClientAsync(BackOfficeIdentityUser user)
{
@@ -229,7 +227,7 @@ namespace Umbraco.Web.Common.Security
new AuthenticationProperties { IsPersistent = true });
}
/// <inheritdoc />
public override Task ForgetTwoFactorClientAsync()
{
@@ -239,7 +237,7 @@ namespace Umbraco.Web.Common.Security
return Context.SignOutAsync(Constants.Security.BackOfficeTwoFactorRememberMeAuthenticationType);
}
/// <inheritdoc />
public override async Task<SignInResult> TwoFactorRecoveryCodeSignInAsync(string recoveryCode)
{
@@ -268,7 +266,7 @@ namespace Umbraco.Web.Common.Security
return SignInResult.Failed;
}
/// <inheritdoc />
public override async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
{
@@ -328,9 +326,9 @@ namespace Umbraco.Web.Common.Security
if (user == null)
{
// user doesn't exist so see if we can auto link
return await AutoLinkAndSignInExternalAccount(loginInfo, autoLinkOptions);
return await AutoLinkAndSignInExternalAccount(loginInfo, autoLinkOptions);
}
if (autoLinkOptions != null && autoLinkOptions.OnExternalLogin != null)
{
var shouldSignIn = autoLinkOptions.OnExternalLogin(user, loginInfo);
@@ -422,7 +420,7 @@ namespace Umbraco.Web.Common.Security
if (username.IsNullOrWhiteSpace())
{
username = "UNKNOWN"; // could happen in 2fa or something else weird
}
}
if (result.Succeeded)
{
@@ -432,14 +430,14 @@ namespace Umbraco.Web.Common.Security
{
//we have successfully logged in, reset the AccessFailedCount
user.AccessFailedCount = 0;
}
}
await UserManager.UpdateAsync(user);
Logger.LogInformation("User: {UserName} logged in from IP address {IpAddress}", username, Context.Connection.RemoteIpAddress);
if (user != null)
{
_userManager.RaiseLoginSuccessEvent(user, user.Id);
}
}
}
else if (result.IsLockedOut)
{
@@ -449,7 +447,7 @@ namespace Umbraco.Web.Common.Security
else if (result.RequiresTwoFactor)
{
Logger.LogInformation("Login attempt requires verification for username {UserName} from IP address {IpAddress}", username, Context.Connection.RemoteIpAddress);
}
}
else if (!result.Succeeded || result.IsNotAllowed)
{
Logger.LogInformation("Login attempt failed for username {UserName} from IP address {IpAddress}", username, Context.Connection.RemoteIpAddress);
@@ -560,7 +558,7 @@ namespace Umbraco.Web.Common.Security
if (autoLinkOptions == null || !autoLinkOptions.AutoLinkExternalAccount)
{
return SignInResult.Failed;
}
}
var email = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);

View File

@@ -125,7 +125,7 @@ namespace Umbraco.Web.BackOffice.Security
// We need to resolve the BackOfficeSecurityStampValidator per request as a requirement (even in aspnetcore they do this)
var securityStampValidator = ctx.HttpContext.RequestServices.GetRequiredService<BackOfficeSecurityStampValidator>();
// Same goes for the signinmanager
var signInManager = ctx.HttpContext.RequestServices.GetRequiredService<BackOfficeSignInManager>();
var signInManager = ctx.HttpContext.RequestServices.GetRequiredService<IBackOfficeSignInManager>();
var backOfficeIdentity = ctx.Principal.GetUmbracoIdentity();
if (backOfficeIdentity == null)

View File

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Common.Security
{
/// <summary>
/// A <see cref="SignInManager{BackOfficeIdentityUser}"/> for the back office with a <seealso cref="BackOfficeIdentityUser"/>
/// </summary>
public interface IBackOfficeSignInManager
{
AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string userId = null);
Task<SignInResult> ExternalLoginSignInAsync(ExternalLoginInfo loginInfo, bool isPersistent, bool bypassTwoFactor = false);
Task<IEnumerable<AuthenticationScheme>> GetExternalAuthenticationSchemesAsync();
Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null);
Task<BackOfficeIdentityUser> GetTwoFactorAuthenticationUserAsync();
Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure);
Task SignOutAsync();
Task SignInAsync(BackOfficeIdentityUser user, bool isPersistent, string authenticationMethod = null);
Task<ClaimsPrincipal> CreateUserPrincipalAsync(BackOfficeIdentityUser user);
Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient);
}
}

View File

@@ -8,7 +8,7 @@
@using Umbraco.Extensions
@using Umbraco.Core.Logging
@using Umbraco.Web.BackOffice.Controllers
@inject BackOfficeSignInManager SignInManager
@inject IBackOfficeSignInManager SignInManager
@inject BackOfficeServerVariables BackOfficeServerVariables
@inject IUmbracoVersion UmbracoVersion
@inject IHostingEnvironment HostingEnvironment