diff --git a/PoweredSoft.DynamicJwtBearer.DynamicAuthority/DynamicAuthorityJwtBearerHandlerConfigurationResolver.cs b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/DynamicAuthorityJwtBearerHandlerConfigurationResolver.cs new file mode 100644 index 0000000..cc5a1e0 --- /dev/null +++ b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/DynamicAuthorityJwtBearerHandlerConfigurationResolver.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace PoweredSoft.DynamicJwtBearer.DynamicAuthority +{ + public class DynamicAuthorityJwtBearerHandlerConfigurationResolver : IDynamicJwtBearerHanderConfigurationResolver + { + private readonly IMemoryCache memoryCache; + private readonly IDynamicJwtBearerAuthorityResolver dynamicJwtAuthorityResolver; + + public DynamicAuthorityJwtBearerHandlerConfigurationResolver(IMemoryCache memoryCache, IDynamicJwtBearerAuthorityResolver dynamicJwtAuthorityResolver) + { + this.memoryCache = memoryCache; + this.dynamicJwtAuthorityResolver = dynamicJwtAuthorityResolver; + } + + public async Task ResolveCurrentOpenIdConfiguration(HttpContext context) + { + var authority = await dynamicJwtAuthorityResolver.ResolveAuthority(context); + var cacheKey = $"DynamicAuthorityJwtBearerHandlerConfigurationResolver__{authority}"; + var ret = await memoryCache.GetOrCreateAsync(cacheKey, async cacheEntry => + { + cacheEntry.AbsoluteExpirationRelativeToNow = dynamicJwtAuthorityResolver.ExpirationOfConfiguration; + var configurationManager = new ConfigurationManager($"{authority}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever()); + var authorityConfiguration = await configurationManager.GetConfigurationAsync(context.RequestAborted); + return authorityConfiguration; + }); + + return ret; + } + } +} diff --git a/PoweredSoft.DynamicJwtBearer.DynamicAuthority/IDynamicJwtBearerAuthorityResolver.cs b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/IDynamicJwtBearerAuthorityResolver.cs new file mode 100644 index 0000000..aa67196 --- /dev/null +++ b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/IDynamicJwtBearerAuthorityResolver.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Threading.Tasks; + +namespace PoweredSoft.DynamicJwtBearer.DynamicAuthority +{ + public interface IDynamicJwtBearerAuthorityResolver + { + public TimeSpan ExpirationOfConfiguration { get; } + + public Task ResolveAuthority(HttpContext httpContext); + } +} diff --git a/PoweredSoft.DynamicJwtBearer.DynamicAuthority/PoweredSoft.DynamicJwtBearer.DynamicAuthority.csproj b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/PoweredSoft.DynamicJwtBearer.DynamicAuthority.csproj new file mode 100644 index 0000000..34440b2 --- /dev/null +++ b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/PoweredSoft.DynamicJwtBearer.DynamicAuthority.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.0 + + + + + + + diff --git a/PoweredSoft.DynamicJwtBearer.DynamicAuthority/ServiceCollectionExtensions.cs b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..dfc391e --- /dev/null +++ b/PoweredSoft.DynamicJwtBearer.DynamicAuthority/ServiceCollectionExtensions.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PoweredSoft.DynamicJwtBearer.DynamicAuthority +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddDynamicAuthorityJwtBearerResolver(this IServiceCollection services) + where TAuthoritySolver : class, IDynamicJwtBearerAuthorityResolver + { + services.AddTransient(); + services.AddSingleton(); + return services; + } + + public static AuthenticationBuilder AddDynamicAuthorityJwtBearerResolver(this AuthenticationBuilder authenticationBuilder) + where TAuthoritySolver : class, IDynamicJwtBearerAuthorityResolver + { + authenticationBuilder.Services.AddDynamicAuthorityJwtBearerResolver(); + return authenticationBuilder; + } + } +} diff --git a/PoweredSoft.DynamicJwtBearer.sln b/PoweredSoft.DynamicJwtBearer.sln index cef476e..665922e 100644 --- a/PoweredSoft.DynamicJwtBearer.sln +++ b/PoweredSoft.DynamicJwtBearer.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29503.13 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicJwtBearer", "PoweredSoft.DynamicJwtBearer\PoweredSoft.DynamicJwtBearer.csproj", "{0A15F002-66C4-44D1-8162-563F860C49E4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoweredSoft.DynamicJwtBearer.DynamicAuthority", "PoweredSoft.DynamicJwtBearer.DynamicAuthority\PoweredSoft.DynamicJwtBearer.DynamicAuthority.csproj", "{61B13BD6-C86E-4698-8E3B-F26508E9658C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {0A15F002-66C4-44D1-8162-563F860C49E4}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A15F002-66C4-44D1-8162-563F860C49E4}.Release|Any CPU.ActiveCfg = Release|Any CPU {0A15F002-66C4-44D1-8162-563F860C49E4}.Release|Any CPU.Build.0 = Release|Any CPU + {61B13BD6-C86E-4698-8E3B-F26508E9658C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61B13BD6-C86E-4698-8E3B-F26508E9658C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61B13BD6-C86E-4698-8E3B-F26508E9658C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61B13BD6-C86E-4698-8E3B-F26508E9658C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE