Runtime clean-up
This commit is contained in:
parent
3e7ac46d70
commit
8b41267e1a
|
|
@ -11,5 +11,6 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
IServiceCollection Services { get; }
|
||||
Type ApplicationType { get; }
|
||||
Type UserType { get; }
|
||||
Type RoleType { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SigningCredentials> SigningKeys { get; set; } = new List<SigningCredentials>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<TContext>(this IIdentityServiceBuilder builder)
|
||||
where TContext : DbContext
|
||||
{
|
||||
var identityBuilder = new IdentityBuilder(builder.UserType, builder.RoleType, builder.Services);
|
||||
identityBuilder.AddEntityFrameworkStores<TContext>();
|
||||
|
||||
var services = builder.Services;
|
||||
var applicationType = FindGenericBaseType(builder.ApplicationType, typeof(IdentityServiceApplication<,,,,>));
|
||||
var userType = FindGenericBaseType(builder.UserType, typeof(IdentityUser<>));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.AspNetCore.Identity.Service.IntegratedWebClient
|
||||
{
|
||||
public class IntegratedWebClientOpenIdConnectOptionsSetup : IConfigureOptions<OpenIdConnectOptions>
|
||||
public class IntegratedWebClientOpenIdConnectOptionsSetup : IConfigureNamedOptions<OpenIdConnectOptions>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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<IntegratedWebClientOptions> 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<IConfigureOptions<IntegratedWebClientOptions>, DefaultSetup>();
|
||||
services.WithIntegratedWebClient(_ => { });
|
||||
return services;
|
||||
}
|
||||
|
||||
private class DefaultSetup : ConfigureOptions<IntegratedWebClientOptions>
|
||||
{
|
||||
public DefaultSetup(IConfiguration configuration)
|
||||
: base(options => configuration.GetSection(OpenIdConnectDefaults.AuthenticationScheme).Bind(options))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ namespace Microsoft.AspNetCore.Identity.Service.Specification.Tests
|
|||
protected virtual void SetupIdentityServiceServices(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
||||
services.AddIdentityService<TUser, TApplication>(options =>
|
||||
{
|
||||
});
|
||||
new IdentityBuilder(typeof(TestUser), typeof(TestRole), services)
|
||||
.AddApplications<TUser, TApplication>(options => { });
|
||||
|
||||
AddApplicationStore(services, context);
|
||||
services.AddLogging();
|
||||
services.AddSingleton<ILogger<ApplicationManager<TApplication>>>(new TestLogger<ApplicationManager<TApplication>>());
|
||||
|
|
@ -215,5 +215,8 @@ namespace Microsoft.AspNetCore.Identity.Service.Specification.Tests
|
|||
|
||||
private IEnumerable<string> GenerateScopes(string prefix, int count) =>
|
||||
Enumerable.Range(0, count).Select(i => $"{prefix}_{count}");
|
||||
|
||||
private class TestUser { }
|
||||
private class TestRole { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,17 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
return await Store.CreateAsync(application, CancellationToken);
|
||||
}
|
||||
|
||||
public Task<string> GetApplicationNameAsync(TApplication application)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (application == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(application));
|
||||
}
|
||||
|
||||
return Store.GetApplicationNameAsync(application, CancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task<IdentityServiceResult> DeleteAsync(TApplication application)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -154,7 +165,7 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
|
||||
public Task<string> GenerateClientSecretAsync()
|
||||
{
|
||||
return Task.FromResult(Guid.NewGuid().ToString());
|
||||
return Task.FromResult(CryptographyHelpers.GenerateHighEntropyValue(byteLength: 32));
|
||||
}
|
||||
|
||||
public async Task<IdentityServiceResult> AddClientSecretAsync(TApplication application, string clientSecret)
|
||||
|
|
@ -199,6 +210,54 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
return await UpdateAsync(application);
|
||||
}
|
||||
|
||||
public async Task<IdentityServiceResult> 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<IdentityServiceResult> 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<IdentityServiceResult> 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<IdentityServiceResult> RemoveClientSecretAsync(TApplication application)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -229,6 +288,7 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
|
||||
public async Task<IdentityServiceResult> 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<IdentityServiceResult> 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<bool> HasClientSecretAsync(TApplication application)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (application == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(application));
|
||||
}
|
||||
|
||||
var store = GetClientSecretStore();
|
||||
return store.HasClientSecretAsync(application, CancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IdentityServiceResult> 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<IdentityServiceResult> 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<TApplication> GetApplicationClaimStore()
|
||||
{
|
||||
if (Store is IApplicationClaimStore<TApplication> cast)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
Task<TApplication> FindByNameAsync(string name, CancellationToken cancellationToken);
|
||||
Task<string> GetApplicationIdAsync(TApplication application, CancellationToken cancellationToken);
|
||||
Task<string> GetApplicationNameAsync(TApplication application, CancellationToken cancellationToken);
|
||||
Task SetApplicationNameAsync(TApplication application, string name, CancellationToken cancellationToken);
|
||||
Task<string> GetApplicationClientIdAsync(TApplication application, CancellationToken cancellationToken);
|
||||
Task<string> GetApplicationUserIdAsync(TApplication application, CancellationToken cancellationToken);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,19 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
|
||||
namespace Microsoft.AspNetCore.Identity.Service
|
||||
{
|
||||
internal class IdentityServiceBuilder<TUser,TApplication> : IIdentityServiceBuilder
|
||||
internal class IdentityServiceBuilder<TApplication> : 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
public static class IdentityServiceServiceCollectionExtensions
|
||||
{
|
||||
public static IIdentityServiceBuilder AddIdentityService<TUser, TApplication>(
|
||||
this IServiceCollection services,
|
||||
public static IIdentityServiceBuilder AddApplications<TUser, TApplication>(
|
||||
this IdentityBuilder builder,
|
||||
Action<IdentityServiceOptions> 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<TUser, TApplication>(services);
|
||||
return new IdentityServiceBuilder<TApplication>(builder);
|
||||
}
|
||||
|
||||
private static IEnumerable<ServiceDescriptor> CreateServices<TUser, TApplication>()
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ namespace Microsoft.AspNetCore.Identity.Service
|
|||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
||||
services.AddIdentity<IdentityUser, IdentityRole>();
|
||||
services.AddIdentityService<IdentityUser, IdentityServiceApplication>(o => { });
|
||||
services.AddIdentity<IdentityUser, IdentityRole>()
|
||||
.AddApplications<IdentityUser, IdentityServiceApplication>(o => { });
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
|
||||
var options = provider.GetRequiredService<IOptions<AuthorizationOptions>>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue