using System;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Umbraco.Core;
using Umbraco.Core.BackOffice;
using Umbraco.Core.Security;
using Umbraco.Core.Serialization;
using Umbraco.Infrastructure.BackOffice;
using Umbraco.Net;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.BackOffice.Security;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Security;
namespace Umbraco.Extensions
{
public static class BackOfficeServiceCollectionExtensions
{
///
/// Adds the services required for using Umbraco back office Identity
///
///
public static void AddUmbracoBackOfficeIdentity(this IServiceCollection services)
{
services.AddDataProtection();
services.BuildUmbracoBackOfficeIdentity()
.AddDefaultTokenProviders()
.AddUserStore()
.AddUserManager()
.AddSignInManager()
.AddClaimsPrincipalFactory>();
// Configure the options specifically for the UmbracoBackOfficeIdentityOptions instance
services.ConfigureOptions();
services.ConfigureOptions();
}
private static BackOfficeIdentityBuilder BuildUmbracoBackOfficeIdentity(this IServiceCollection services)
{
// Borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Extensions.Core/src/IdentityServiceCollectionExtensions.cs#L33
// The reason we need our own is because the Identity system doesn't cater easily for multiple identity systems and particularly being
// able to configure IdentityOptions to a specific provider since there is no named options. So we have strongly typed options
// and strongly typed ILookupNormalizer and IdentityErrorDescriber since those are 'global' and we need to be unintrusive.
// TODO: Could move all of this to BackOfficeComposer?
// Services used by identity
services.TryAddScoped, UserValidator>();
services.TryAddScoped, PasswordValidator>();
services.TryAddScoped>(
services => new BackOfficePasswordHasher(
new LegacyPasswordSecurity(),
services.GetRequiredService()));
services.TryAddScoped, DefaultUserConfirmation>();
services.TryAddScoped, UserClaimsPrincipalFactory>();
// CUSTOM:
services.TryAddScoped();
services.TryAddScoped();
services.TryAddScoped();
services.TryAddSingleton();
/*
* IdentityBuilderExtensions.AddUserManager adds UserManager to service collection
* To validate the container the following registrations are required (dependencies of UserManager)
* Perhaps we shouldn't be registering UserManager at all and only registering/depending the UmbracoBackOffice prefixed types.
*/
services.TryAddScoped();
services.TryAddScoped();
return new BackOfficeIdentityBuilder(services);
}
}
}