From 8b41267e1aa52e1b4678903b7e6d627ff8d02138 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 26 May 2017 17:33:23 -0700 Subject: [PATCH] Runtime clean-up --- .../IIdentityServiceBuilder.cs | 1 + .../CryptographyHelpers.cs | 9 ++ ...dentityServiceAuthorizationOptionsSetup.cs | 2 + .../Options/IdentityServiceOptions.cs | 2 + .../IdentityServiceOptionsDefaultSetup.cs | 5 + .../ApplicationStore.cs | 13 ++ .../IdentityServiceBuilderExtensions.cs | 5 + ...ratedWebClientOpenIdConnectOptionsSetup.cs | 14 ++- .../IntegratedWebClientOptions.cs | 2 +- ...tedWebClientServiceCollectionExtensions.cs | 21 +++- .../IdentityServiceSpecificationTestBase.cs | 9 +- .../ApplicationManager.cs | 115 +++++++++++++++++- .../IApplicationStore.cs | 1 + .../IdentityServiceBuilder.cs | 13 +- ...ntityServiceServiceCollectionExtensions.cs | 12 +- ...yOptionsServiceCollectionExtensionsTest.cs | 5 +- 16 files changed, 206 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.AspNetCore.Identity.Service.Abstractions/IIdentityServiceBuilder.cs b/src/Microsoft.AspNetCore.Identity.Service.Abstractions/IIdentityServiceBuilder.cs index 409a69ff81..dd7f543d01 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Abstractions/IIdentityServiceBuilder.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Abstractions/IIdentityServiceBuilder.cs @@ -11,5 +11,6 @@ namespace Microsoft.AspNetCore.Identity.Service IServiceCollection Services { get; } Type ApplicationType { get; } Type UserType { get; } + Type RoleType { get; } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service.Core/CryptographyHelpers.cs b/src/Microsoft.AspNetCore.Identity.Service.Core/CryptographyHelpers.cs index 043cd5c926..7f997d9ccb 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Core/CryptographyHelpers.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Core/CryptographyHelpers.cs @@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore.Identity.Service { internal static class CryptographyHelpers { + private static readonly RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create(); + public static string FindAlgorithm(X509Certificate2 certificate) { var rsapk = certificate.GetRSAPublicKey(); @@ -110,5 +112,12 @@ namespace Microsoft.AspNetCore.Identity.Service throw new NotSupportedException(); } + + internal static string GenerateHighEntropyValue(int byteLength) + { + var bytes = new byte[byteLength]; + randomNumberGenerator.GetBytes(bytes); + return Base64UrlEncoder.Encode(bytes); + } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceAuthorizationOptionsSetup.cs b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceAuthorizationOptionsSetup.cs index d32ec2216e..567cba5129 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceAuthorizationOptionsSetup.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceAuthorizationOptionsSetup.cs @@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Identity.Service public void Configure(AuthorizationOptions options) { options.AddPolicy(IdentityServiceOptions.LoginPolicyName, _identityServiceOptions.Value.LoginPolicy); + options.AddPolicy(IdentityServiceOptions.SessionPolicyName, _identityServiceOptions.Value.SessionPolicy); + options.AddPolicy(IdentityServiceOptions.ManagementPolicyName, _identityServiceOptions.Value.ManagementPolicy); } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptions.cs b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptions.cs index 76a8818445..a6a2ddfad2 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptions.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptions.cs @@ -12,6 +12,7 @@ namespace Microsoft.AspNetCore.Identity.Service { public const string LoginPolicyName = "Microsoft.AspNetCore.Identity.Service.Login"; public const string SessionPolicyName = "Microsoft.AspNetCore.Identity.Service.Session"; + public const string ManagementPolicyName = "Microsoft.AspNetCore.Identity.Service.Management"; public const string CookieAuthenticationScheme = "Microsoft.AspNetCore.Identity.Service.Session.Cookies"; public const string AuthenticationCookieName = "Microsoft.AspNetCore.Identity.Service"; @@ -19,6 +20,7 @@ namespace Microsoft.AspNetCore.Identity.Service public AuthorizationPolicy LoginPolicy { get; set; } public AuthorizationPolicy SessionPolicy { get; set; } + public AuthorizationPolicy ManagementPolicy { get; set; } public IList SigningKeys { get; set; } = new List(); diff --git a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptionsDefaultSetup.cs b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptionsDefaultSetup.cs index 3af76bcebc..3834f8b4d7 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptionsDefaultSetup.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Core/Options/IdentityServiceOptionsDefaultSetup.cs @@ -23,6 +23,11 @@ namespace Microsoft.AspNetCore.Identity.Service .RequireAuthenticatedUser() .Build(); + options.ManagementPolicy = new AuthorizationPolicyBuilder() + .AddAuthenticationSchemes(IdentityServiceOptions.CookieAuthenticationScheme) + .RequireAuthenticatedUser() + .Build(); + options.SerializationSettings = CreateDefault(); options.SerializationSettings.Converters.Insert(0, new AuthorizationCodeConverter()); options.SerializationSettings.Converters.Insert(0, new RefreshTokenConverter()); diff --git a/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/ApplicationStore.cs b/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/ApplicationStore.cs index 1a04850b81..f2690e73b8 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/ApplicationStore.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/ApplicationStore.cs @@ -446,6 +446,19 @@ namespace Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore return (TUserKey)TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(id); } + public Task SetApplicationNameAsync(TApplication application, string name, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + application.Name = name; + return Task.CompletedTask; + } + public Task SetClientSecretHashAsync(TApplication application, string clientSecretHash, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/IdentityServiceBuilderExtensions.cs b/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/IdentityServiceBuilderExtensions.cs index c0d5c91e48..b44aceac18 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/IdentityServiceBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore/IdentityServiceBuilderExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore @@ -11,7 +12,11 @@ namespace Microsoft.AspNetCore.Identity.Service.EntityFrameworkCore public static class IdentityServiceBuilderExtensions { public static IIdentityServiceBuilder AddEntityFrameworkStores(this IIdentityServiceBuilder builder) + where TContext : DbContext { + var identityBuilder = new IdentityBuilder(builder.UserType, builder.RoleType, builder.Services); + identityBuilder.AddEntityFrameworkStores(); + var services = builder.Services; var applicationType = FindGenericBaseType(builder.ApplicationType, typeof(IdentityServiceApplication<,,,,>)); var userType = FindGenericBaseType(builder.UserType, typeof(IdentityUser<>)); diff --git a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOpenIdConnectOptionsSetup.cs b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOpenIdConnectOptionsSetup.cs index 8e46d61c70..9f6efa17d5 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOpenIdConnectOptionsSetup.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOpenIdConnectOptionsSetup.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient { - public class IntegratedWebClientOpenIdConnectOptionsSetup : IConfigureOptions + public class IntegratedWebClientOpenIdConnectOptionsSetup : IConfigureNamedOptions { private readonly IHttpContextAccessor _accessor; private readonly IKeySetMetadataProvider _keysProvider; @@ -24,8 +24,13 @@ namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient _keysProvider = keysProvider; } - public void Configure(OpenIdConnectOptions options) + public void Configure(string name, OpenIdConnectOptions options) { + if (name != OpenIdConnectDefaults.AuthenticationScheme) + { + return; + } + options.TokenValidationParameters.NameClaimType = "name"; options.SignInScheme = _webApplicationOptions.Value.CookieSignInScheme; options.ClientId = _webApplicationOptions.Value.ClientId; @@ -58,5 +63,10 @@ namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient options.TokenValidationParameters.IssuerSigningKeys = keys; } } + + public void Configure(OpenIdConnectOptions options) + { + Configure(OpenIdConnectDefaults.AuthenticationScheme, options); + } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOptions.cs b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOptions.cs index 01c3ff0e43..6c51e3ce0b 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOptions.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientOptions.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient public class IntegratedWebClientOptions { public string ClientId { get; set; } - public string TokenRedirectUrn { get; set; } + public string TokenRedirectUrn { get; set; } = "urn:self:aspnet:identity:integrated"; public string MetadataUri { get; set; } public string AuthorizationEndpoint { get; set; } public string TokenEndpoint { get; set; } diff --git a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientServiceCollectionExtensions.cs index 0c00cfef20..f3cba80b3e 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.IntegratedWebClient/IntegratedWebClientServiceCollectionExtensions.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient { public static class IntegratedWebClientServiceCollectionExtensions { - public static IServiceCollection AddIntegratedWebClient( + public static IServiceCollection WithIntegratedWebClient( this IServiceCollection services, Action action) { @@ -24,12 +24,27 @@ namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient return services; } - public static IServiceCollection AddIntegratedWebClient( + public static IServiceCollection WithIntegratedWebClient( this IServiceCollection services, IConfiguration configuration) { - services.AddIntegratedWebClient(options => configuration.Bind(options)); + services.WithIntegratedWebClient(options => configuration.Bind(options)); return services; } + + public static IServiceCollection WithIntegratedWebClient(this IServiceCollection services) + { + services.TryAddTransient, DefaultSetup>(); + services.WithIntegratedWebClient(_ => { }); + return services; + } + + private class DefaultSetup : ConfigureOptions + { + public DefaultSetup(IConfiguration configuration) + : base(options => configuration.GetSection(OpenIdConnectDefaults.AuthenticationScheme).Bind(options)) + { + } + } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service.Specification.Tests/IdentityServiceSpecificationTestBase.cs b/src/Microsoft.AspNetCore.Identity.Service.Specification.Tests/IdentityServiceSpecificationTestBase.cs index 3ecf960668..5408415257 100644 --- a/src/Microsoft.AspNetCore.Identity.Service.Specification.Tests/IdentityServiceSpecificationTestBase.cs +++ b/src/Microsoft.AspNetCore.Identity.Service.Specification.Tests/IdentityServiceSpecificationTestBase.cs @@ -50,9 +50,9 @@ namespace Microsoft.AspNetCore.Identity.Service.Specification.Tests protected virtual void SetupIdentityServiceServices(IServiceCollection services, object context = null) { services.AddSingleton(new ConfigurationBuilder().Build()); - services.AddIdentityService(options => - { - }); + new IdentityBuilder(typeof(TestUser), typeof(TestRole), services) + .AddApplications(options => { }); + AddApplicationStore(services, context); services.AddLogging(); services.AddSingleton>>(new TestLogger>()); @@ -215,5 +215,8 @@ namespace Microsoft.AspNetCore.Identity.Service.Specification.Tests private IEnumerable GenerateScopes(string prefix, int count) => Enumerable.Range(0, count).Select(i => $"{prefix}_{count}"); + + private class TestUser { } + private class TestRole { } } } diff --git a/src/Microsoft.AspNetCore.Identity.Service/ApplicationManager.cs b/src/Microsoft.AspNetCore.Identity.Service/ApplicationManager.cs index 5b6e031b2f..ca9ce8d12d 100644 --- a/src/Microsoft.AspNetCore.Identity.Service/ApplicationManager.cs +++ b/src/Microsoft.AspNetCore.Identity.Service/ApplicationManager.cs @@ -87,6 +87,17 @@ namespace Microsoft.AspNetCore.Identity.Service return await Store.CreateAsync(application, CancellationToken); } + public Task GetApplicationNameAsync(TApplication application) + { + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Store.GetApplicationNameAsync(application, CancellationToken); + } + public virtual async Task DeleteAsync(TApplication application) { ThrowIfDisposed(); @@ -154,7 +165,7 @@ namespace Microsoft.AspNetCore.Identity.Service public Task GenerateClientSecretAsync() { - return Task.FromResult(Guid.NewGuid().ToString()); + return Task.FromResult(CryptographyHelpers.GenerateHighEntropyValue(byteLength: 32)); } public async Task AddClientSecretAsync(TApplication application, string clientSecret) @@ -199,6 +210,54 @@ namespace Microsoft.AspNetCore.Identity.Service return await UpdateAsync(application); } + public async Task RegisterLogoutUriAsync(TApplication application, string logoutUri) + { + ThrowIfDisposed(); + var redirectStore = GetRedirectUriStore(); + var result = await redirectStore.RegisterLogoutRedirectUriAsync(application, logoutUri, CancellationToken); + if (!result.Succeeded) + { + return result; + } + + return await redirectStore.UpdateAsync(application, CancellationToken); + } + + public async Task UnregisterLogoutUriAsync(TApplication application, string logoutUri) + { + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + if (logoutUri == null) + { + throw new ArgumentNullException(nameof(logoutUri)); + } + + var redirectStore = GetRedirectUriStore(); + var result = await redirectStore.UnregisterLogoutRedirectUriAsync(application, logoutUri, CancellationToken); + if (!result.Succeeded) + { + return result; + } + + return await redirectStore.UpdateAsync(application, CancellationToken); + } + + public async Task SetApplicationNameAsync(TApplication application, string name) + { + ThrowIfDisposed(); + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + await Store.SetApplicationNameAsync(application, name, CancellationToken); + return await UpdateAsync(application); + } + public async Task RemoveClientSecretAsync(TApplication application) { ThrowIfDisposed(); @@ -229,6 +288,7 @@ namespace Microsoft.AspNetCore.Identity.Service public async Task RegisterRedirectUriAsync(TApplication application, string redirectUri) { + ThrowIfDisposed(); var redirectStore = GetRedirectUriStore(); var result = await redirectStore.RegisterRedirectUriAsync(application, redirectUri, CancellationToken); if (!result.Succeeded) @@ -253,6 +313,17 @@ namespace Microsoft.AspNetCore.Identity.Service public async Task UnregisterRedirectUriAsync(TApplication application, string redirectUri) { + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + if (redirectUri == null) + { + throw new ArgumentNullException(nameof(redirectUri)); + } + var redirectStore = GetRedirectUriStore(); var result = await redirectStore.UnregisterRedirectUriAsync(application, redirectUri, CancellationToken); if (!result.Succeeded) @@ -263,6 +334,18 @@ namespace Microsoft.AspNetCore.Identity.Service return await redirectStore.UpdateAsync(application, CancellationToken); } + public Task HasClientSecretAsync(TApplication application) + { + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + var store = GetClientSecretStore(); + return store.HasClientSecretAsync(application, CancellationToken); + } + public async Task UpdateRedirectUriAsync(TApplication application, string oldRedirectUri, string newRedirectUri) { var redirectStore = GetRedirectUriStore(); @@ -311,7 +394,7 @@ namespace Microsoft.AspNetCore.Identity.Service TApplication application, string clientSecret) { - var hash = PasswordHasher.HashPassword(application, clientSecret); + var hash = clientSecret == null ? null : PasswordHasher.HashPassword(application, clientSecret); await clientSecretStore.SetClientSecretHashAsync(application, hash, CancellationToken); return IdentityServiceResult.Success; } @@ -488,6 +571,34 @@ namespace Microsoft.AspNetCore.Identity.Service return await claimStore.GetClaimsAsync(application, CancellationToken); } + public async Task UpdateLogoutUriAsync(TApplication application, string oldLogoutUri, string newLogoutUri) + { + ThrowIfDisposed(); + if (application == null) + { + throw new ArgumentNullException(nameof(application)); + } + + if (oldLogoutUri == null) + { + throw new ArgumentNullException(nameof(oldLogoutUri)); + } + + if (newLogoutUri == null) + { + throw new ArgumentNullException(nameof(newLogoutUri)); + } + + var redirectUriStore = GetRedirectUriStore(); + var result = await redirectUriStore.UpdateLogoutRedirectUriAsync(application, oldLogoutUri, newLogoutUri, CancellationToken); + if (!result.Succeeded) + { + return result; + } + + return await UpdateAsync(application); + } + private IApplicationClaimStore GetApplicationClaimStore() { if (Store is IApplicationClaimStore cast) diff --git a/src/Microsoft.AspNetCore.Identity.Service/IApplicationStore.cs b/src/Microsoft.AspNetCore.Identity.Service/IApplicationStore.cs index 5d91e97fd8..46c44a594e 100644 --- a/src/Microsoft.AspNetCore.Identity.Service/IApplicationStore.cs +++ b/src/Microsoft.AspNetCore.Identity.Service/IApplicationStore.cs @@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Identity.Service Task FindByNameAsync(string name, CancellationToken cancellationToken); Task GetApplicationIdAsync(TApplication application, CancellationToken cancellationToken); Task GetApplicationNameAsync(TApplication application, CancellationToken cancellationToken); + Task SetApplicationNameAsync(TApplication application, string name, CancellationToken cancellationToken); Task GetApplicationClientIdAsync(TApplication application, CancellationToken cancellationToken); Task GetApplicationUserIdAsync(TApplication application, CancellationToken cancellationToken); diff --git a/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceBuilder.cs b/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceBuilder.cs index 35087642b1..1d5b221da4 100644 --- a/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceBuilder.cs +++ b/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceBuilder.cs @@ -6,16 +6,19 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Identity.Service { - internal class IdentityServiceBuilder : IIdentityServiceBuilder + internal class IdentityServiceBuilder : IIdentityServiceBuilder { - public IdentityServiceBuilder(IServiceCollection services) + private readonly IdentityBuilder _builder; + + public IdentityServiceBuilder(IdentityBuilder builder) { - Services = services; + _builder = builder; } - public IServiceCollection Services { get; } + public IServiceCollection Services => _builder.Services; public Type ApplicationType => typeof(TApplication); - public Type UserType => typeof(TUser); + public Type UserType => _builder.UserType; + public Type RoleType => _builder.RoleType; } } diff --git a/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceServiceCollectionExtensions.cs index b7c4209795..c483b47c76 100644 --- a/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.Identity.Service/IdentityServiceServiceCollectionExtensions.cs @@ -24,15 +24,15 @@ namespace Microsoft.Extensions.DependencyInjection { public static class IdentityServiceServiceCollectionExtensions { - public static IIdentityServiceBuilder AddIdentityService( - this IServiceCollection services, + public static IIdentityServiceBuilder AddApplications( + this IdentityBuilder builder, Action configure) where TUser : class where TApplication : class { - if (services == null) + if (builder == null) { - throw new NullReferenceException(nameof(services)); + throw new NullReferenceException(nameof(builder)); } if (configure == null) @@ -40,6 +40,8 @@ namespace Microsoft.Extensions.DependencyInjection throw new NullReferenceException(nameof(configure)); } + var services = builder.Services; + services.AddOptions(); services.AddWebEncoders(); services.AddDataProtection(); @@ -100,7 +102,7 @@ namespace Microsoft.Extensions.DependencyInjection services.Configure(configure); - return new IdentityServiceBuilder(services); + return new IdentityServiceBuilder(builder); } private static IEnumerable CreateServices() diff --git a/test/Microsoft.AspNetCore.Identity.Service.Test/IdentityOptionsServiceCollectionExtensionsTest.cs b/test/Microsoft.AspNetCore.Identity.Service.Test/IdentityOptionsServiceCollectionExtensionsTest.cs index ca6c3bb9be..2e1dcce865 100644 --- a/test/Microsoft.AspNetCore.Identity.Service.Test/IdentityOptionsServiceCollectionExtensionsTest.cs +++ b/test/Microsoft.AspNetCore.Identity.Service.Test/IdentityOptionsServiceCollectionExtensionsTest.cs @@ -17,8 +17,9 @@ namespace Microsoft.AspNetCore.Identity.Service { var services = new ServiceCollection(); services.AddSingleton(new ConfigurationBuilder().Build()); - services.AddIdentity(); - services.AddIdentityService(o => { }); + services.AddIdentity() + .AddApplications(o => { }); + var provider = services.BuildServiceProvider(); var options = provider.GetRequiredService>();