From 02bd699c4d08644ca9b88b3dcfb70325b7461a28 Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 8 Nov 2023 20:49:15 +0800 Subject: [PATCH] Add `RemoteDynamicClaimsPrincipalContributor`. --- .../Web/Security/AbpComponentsClaimsCache.cs | 7 +- ...RemoteDynamicClaimsPrincipalContributor.cs | 30 ++++++ ...eDynamicClaimsPrincipalContributorCache.cs | 91 +++++++++++++++++++ ...cClaimsPrincipalContributorCacheOptions.cs | 13 +++ .../Volo/Abp/Security/AbpSecurityModule.cs | 38 ++++++++ .../Abp/Security/Claims/AbpClaimCacheIteam.cs | 7 ++ .../AbpClaimsPrincipalFactoryOptions.cs | 7 +- ...bpDynamicClaimsPrincipalContributorBase.cs | 74 +++++++++++++++ .../IAbpDynamicClaimsPrincipalContributor.cs | 6 ++ .../Claims/AbpClaimsPrincipalFactory_Test.cs | 75 ++++++++++----- .../Volo/Abp/Account/DynamicClaimDto.cs | 8 ++ .../Abp/Account/IDynamicClaimsAppService.cs | 10 ++ .../Abp/Account/DynamicClaimsAppService.cs | 42 +++++++++ .../DynamicClaimsClientProxy.Generated.cs | 24 +++++ .../Abp/Account/DynamicClaimsClientProxy.cs | 7 ++ .../ClientProxies/account-generate-proxy.json | 41 +++++++++ .../Abp/Account/DynamicClaimsController.cs | 26 ++++++ .../wwwroot/client-proxies/account-proxy.js | 15 +++ .../Abp/Identity/AbpIdentityDomainModule.cs | 5 - ...entityDynamicClaimsPrincipalContributor.cs | 17 ++-- ...yDynamicClaimsPrincipalContributorCache.cs | 65 ++++++++----- ...cClaimsPrincipalContributorCacheOptions.cs | 13 +++ .../AbpUserClaimsPrincipalFactory_Tests.cs | 8 +- .../MyProjectNameAuthServerModule.cs | 1 + .../MyProjectNameBlazorModule.cs | 10 +- .../MyProjectNameBlazorModule.cs | 2 +- .../MyProjectNameBlazorModule.cs | 6 ++ .../MyProjectNameHttpApiHostModule.cs | 3 +- .../MyProjectNameHttpApiHostModule.cs | 2 +- ...yCompanyName.MyProjectName.Web.Host.csproj | 1 + .../MyProjectNameWebModule.cs | 9 +- .../MyProjectNameWebModule.cs | 1 + 32 files changed, 590 insertions(+), 74 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs create mode 100644 framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs create mode 100644 framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpDynamicClaimsPrincipalContributor.cs create mode 100644 modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/DynamicClaimDto.cs create mode 100644 modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/IDynamicClaimsAppService.cs create mode 100644 modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs create mode 100644 modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs create mode 100644 modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.cs create mode 100644 modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCacheOptions.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs index 74cbd37e29..8df1824e81 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs @@ -1,9 +1,9 @@ using System.Security.Claims; using System.Threading.Tasks; -using JetBrains.Annotations; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.Components.Web.Security; @@ -12,16 +12,18 @@ public class AbpComponentsClaimsCache : IScopedDependency public ClaimsPrincipal Principal { get; private set; } = default!; private readonly AuthenticationStateProvider? _authenticationStateProvider; + private readonly IAbpClaimsPrincipalFactory _abpClaimsPrincipalFactory; public AbpComponentsClaimsCache( IClientScopeServiceProviderAccessor serviceProviderAccessor) { _authenticationStateProvider = serviceProviderAccessor.ServiceProvider.GetService(); + _abpClaimsPrincipalFactory = serviceProviderAccessor.ServiceProvider.GetRequiredService(); if (_authenticationStateProvider != null) { _authenticationStateProvider.AuthenticationStateChanged += async (task) => { - Principal = (await task).User; + Principal = await _abpClaimsPrincipalFactory.CreateDynamicAsync((await task).User); }; } } @@ -32,6 +34,7 @@ public class AbpComponentsClaimsCache : IScopedDependency { var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); Principal = authenticationState.User; + await _abpClaimsPrincipalFactory.CreateDynamicAsync(Principal); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs new file mode 100644 index 0000000000..38d3b7840a --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs @@ -0,0 +1,30 @@ +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincipalContributorBase +{ + public async override Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + { + var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); + if (identity == null) + { + return; + } + + var userId = identity.FindUserId(); + if (userId == null) + { + return; + } + + var dynamicClaimsCache = context.GetRequiredService(); + var dynamicClaims = await dynamicClaimsCache.GetAsync(userId.Value, identity.FindTenantId()); + + await MapCommonClaimsAsync(identity, dynamicClaims); + await AddDynamicClaims(identity, dynamicClaims); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs new file mode 100644 index 0000000000..33a1dfd5f6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.Authentication; +using Volo.Abp.Json; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteDynamicClaimsPrincipalContributorCache : ITransientDependency +{ + public const string HttpClientName = nameof(RemoteDynamicClaimsPrincipalContributorCache); + + public ILogger Logger { get; set; } + protected IDistributedCache> Cache { get; } + protected IHttpClientFactory HttpClientFactory { get; } + protected IOptions AbpClaimsPrincipalFactoryOptions { get; } + protected IJsonSerializer JsonSerializer { get; } + protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } + protected IOptions CacheOptions { get; } + + public RemoteDynamicClaimsPrincipalContributorCache( + IDistributedCache> cache, + IHttpClientFactory httpClientFactory, + IOptions abpClaimsPrincipalFactoryOptions, + IJsonSerializer jsonSerializer, + IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, + IOptions cacheOptions) + { + Cache = cache; + HttpClientFactory = httpClientFactory; + AbpClaimsPrincipalFactoryOptions = abpClaimsPrincipalFactoryOptions; + JsonSerializer = jsonSerializer; + HttpClientAuthenticator = httpClientAuthenticator; + CacheOptions = cacheOptions; + + Logger = NullLogger.Instance; + } + + public virtual async Task> GetAsync(Guid userId, Guid? tenantId = null) + { + Logger.LogDebug($"Get dynamic claims cache for user: {userId}"); + //The UI may use the same cache as AuthServer in the tiered application. + var claims = await Cache.GetAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId)); + if (!claims.IsNullOrEmpty()) + { + return claims!; + } + + Logger.LogDebug($"Get dynamic claims cache for user: {userId} from remote cache."); + // Use independent cache for remote claims. + return (await Cache.GetOrAddAsync($"{nameof(RemoteDynamicClaimsPrincipalContributorCache)}{AbpClaimCacheItem.CalculateCacheKey(userId, tenantId)}", async () => + { + var dynamicClaims = new List(); + Logger.LogDebug($"Get dynamic claims for user: {userId} from remote service."); + try + { + var client = HttpClientFactory.CreateClient(HttpClientName); + var requestMessage = new HttpRequestMessage(HttpMethod.Get, AbpClaimsPrincipalFactoryOptions.Value.RemoteUrl); + await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration("/"), string.Empty)); + var response = await client.SendAsync(requestMessage); + dynamicClaims = JsonSerializer.Deserialize>(await response.Content.ReadAsStringAsync()); + Logger.LogDebug($"Successfully got {dynamicClaims.Count} remote claims for user: {userId}"); + } + catch (Exception e) + { + Logger.LogWarning(e, $"Failed to get remote claims for user: {userId}"); + } + return dynamicClaims; + }, () => new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = CacheOptions.Value.CacheAbsoluteExpiration + }))!; + } + + public virtual async Task ClearAsync(Guid userId, Guid? tenantId = null) + { + Logger.LogDebug($"Clear dynamic claims cache for user: {userId}"); + Logger.LogDebug($"Clear dynamic claims cache from remote cache for user: {userId}"); + await Cache.RemoveAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId)); + await Cache.RemoveAsync($"{nameof(RemoteDynamicClaimsPrincipalContributorCache)}{AbpClaimCacheItem.CalculateCacheKey(userId, tenantId)}"); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs new file mode 100644 index 0000000000..c8e31b1269 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs @@ -0,0 +1,13 @@ +using System; + +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteDynamicClaimsPrincipalContributorCacheOptions +{ + public TimeSpan CacheAbsoluteExpiration { get; set; } + + public RemoteDynamicClaimsPrincipalContributorCacheOptions() + { + CacheAbsoluteExpiration = TimeSpan.FromSeconds(5); + } +} diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs index 5f3bf47997..9705c1e2e6 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.Text; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; using Volo.Abp.Security.Encryption; using Volo.Abp.SecurityLog; @@ -9,6 +11,11 @@ namespace Volo.Abp.Security; public class AbpSecurityModule : AbpModule { + public override void PostConfigureServices(ServiceConfigurationContext context) + { + AutoAddClaimsPrincipalContributors(context.Services); + } + public override void ConfigureServices(ServiceConfigurationContext context) { var applicationName = context.Services.GetApplicationName(); @@ -51,4 +58,35 @@ public class AbpSecurityModule : AbpModule } }); } + + + private static void AutoAddClaimsPrincipalContributors(IServiceCollection services) + { + var contributorTypes = new List(); + + services.OnRegistered(context => + { + if (typeof(IAbpClaimsPrincipalContributor).IsAssignableFrom(context.ImplementationType) && + !typeof(IAbpDynamicClaimsPrincipalContributor).IsAssignableFrom(context.ImplementationType)) + { + contributorTypes.Add(context.ImplementationType); + } + }); + + var dynamicContributorTypes = new List(); + + services.OnRegistered(context => + { + if (typeof(IAbpDynamicClaimsPrincipalContributor).IsAssignableFrom(context.ImplementationType)) + { + dynamicContributorTypes.Add(context.ImplementationType); + } + }); + + services.Configure(options => + { + options.Contributors.AddIfNotContains(contributorTypes); + options.DynamicContributors.AddIfNotContains(dynamicContributorTypes); + }); + } } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheIteam.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheIteam.cs index fa4850cb96..02f15e2478 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheIteam.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheIteam.cs @@ -14,4 +14,11 @@ public class AbpClaimCacheItem Type = type; Value = value; } + + + public static string CalculateCacheKey(Guid userId, Guid? tenantId) + { + return $"{tenantId}-{userId}"; + } + } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs index 3d96a32205..5f027f6862 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs @@ -11,7 +11,7 @@ public class AbpClaimsPrincipalFactoryOptions public List DynamicClaims { get; } - public string RemoteRefreshUrl { get; set; } + public string RemoteUrl { get; set; } public AbpClaimsPrincipalFactoryOptions() { @@ -21,12 +21,15 @@ public class AbpClaimsPrincipalFactoryOptions DynamicClaims = new List { AbpClaimTypes.UserName, + AbpClaimTypes.Name, + AbpClaimTypes.SurName, AbpClaimTypes.Role, AbpClaimTypes.Email, AbpClaimTypes.EmailVerified, AbpClaimTypes.PhoneNumber, AbpClaimTypes.PhoneNumberVerified }; - RemoteRefreshUrl = "/api/account/refresh-dynamic-claims"; + + RemoteUrl = "/api/account/dynamic-claims"; } } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs new file mode 100644 index 0000000000..55f2dc96a6 --- /dev/null +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Security.Principal; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Security.Claims; + +public abstract class AbpDynamicClaimsPrincipalContributorBase : IAbpDynamicClaimsPrincipalContributor, ITransientDependency +{ + public abstract Task ContributeAsync(AbpClaimsPrincipalContributorContext context); + + protected virtual async Task MapCommonClaimsAsync(ClaimsIdentity identity, List dynamicClaims) + { + await MapClaimsAsync(identity, dynamicClaims, identity.NameClaimType, "preferred_username"); + await MapClaimsAsync(identity, dynamicClaims, identity.NameClaimType, ClaimTypes.Name); + await MapClaimsAsync(identity, dynamicClaims, identity.RoleClaimType, "role"); + await MapClaimsAsync(identity, dynamicClaims, identity.RoleClaimType, ClaimTypes.Role); + await MapClaimsAsync(identity, dynamicClaims, "email", ClaimTypes.Email); + await MapClaimsAsync(identity, dynamicClaims, "family_name", ClaimTypes.Surname); + await MapClaimsAsync(identity, dynamicClaims, "given_name", ClaimTypes.GivenName); + } + + protected virtual Task MapClaimsAsync(ClaimsIdentity identity, List dynamicClaims, string sourceType, string targetType) + { + if (sourceType == targetType) + { + return Task.CompletedTask;; + } + + if (identity.Claims.Any(c => c.Type == sourceType) && dynamicClaims.All(c => c.Type != sourceType)) + { + var claims = dynamicClaims.Where(c => c.Type == targetType).ToList(); + if (!claims.IsNullOrEmpty()) + { + identity.RemoveAll(sourceType); + identity.AddClaims(claims.Select(c => new Claim(sourceType, c.Value))); + dynamicClaims.RemoveAll(c => c.Type == targetType); + } + } + + if (identity.Claims.Any(c => c.Type == targetType) && dynamicClaims.All(c => c.Type != targetType)) + { + var claims = dynamicClaims.Where(c => c.Type == sourceType).ToList(); + if (!claims.IsNullOrEmpty()) + { + identity.RemoveAll(targetType); + identity.AddClaims(claims.Select(c => new Claim(targetType, c.Value))); + dynamicClaims.RemoveAll(c => c.Type == sourceType); + } + } + + return Task.CompletedTask;; + } + + protected virtual Task AddDynamicClaims(ClaimsIdentity identity, List dynamicClaims) + { + foreach (var claims in dynamicClaims.GroupBy(x => x.Type)) + { + if (claims.Count() > 1) + { + identity.RemoveAll(claims.First().Type); + identity.AddClaims(claims.Select(c => new Claim(claims.First().Type, c.Value))); + } + else + { + identity.AddOrReplace(new Claim(claims.First().Type, claims.First().Value)); + } + } + + return Task.CompletedTask;; + } +} diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpDynamicClaimsPrincipalContributor.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpDynamicClaimsPrincipalContributor.cs new file mode 100644 index 0000000000..dde236c363 --- /dev/null +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpDynamicClaimsPrincipalContributor.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.Security.Claims; + +public interface IAbpDynamicClaimsPrincipalContributor : IAbpClaimsPrincipalContributor +{ + +} diff --git a/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs b/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs index b444fa3ded..7726c2fe12 100644 --- a/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs +++ b/framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs @@ -2,8 +2,8 @@ using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.DependencyInjection; using Volo.Abp.Testing; using Xunit; @@ -25,26 +25,6 @@ public class AbpClaimsPrincipalFactory_Test : AbpIntegratedTest(options => - { - options.Contributors.Add(); - options.Contributors.Add(); - options.Contributors.Add(); - - options.DynamicContributors.Add(); - options.DynamicContributors.Add(); - options.DynamicContributors.Add(); - options.DynamicContributors.Add(); - }); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - } - [Fact] public async Task CreateAsync() { @@ -99,7 +79,52 @@ public class AbpClaimsPrincipalFactory_Test : AbpIntegratedTest x.Type == ClaimTypes.Version && x.Value == "2.0"); } - class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor + class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency + { + public Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + { + var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType) + ?? new ClaimsIdentity(TestAuthenticationType); + + claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Email, "admin@abp.io")); + + context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity); + + return Task.CompletedTask; + } + } + + class Test2AbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency + { + public Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + { + var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType) + ?? new ClaimsIdentity(TestAuthenticationType); + + claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Email, "admin2@abp.io")); + + context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity); + + return Task.CompletedTask; + } + } + + class Test3AbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency + { + public Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + { + var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType) + ?? new ClaimsIdentity(TestAuthenticationType); + + claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Version, "2.0")); + + context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity); + + return Task.CompletedTask; + } + } + + class TestAbpDynamicClaimsPrincipalContributor : IAbpDynamicClaimsPrincipalContributor, ITransientDependency { public Task ContributeAsync(AbpClaimsPrincipalContributorContext context) { @@ -114,7 +139,7 @@ public class AbpClaimsPrincipalFactory_Test : AbpIntegratedTest> GetAsync(); +} diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs new file mode 100644 index 0000000000..ebe9e06cb7 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; +using Volo.Abp.Identity; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.Account; + +[Authorize] +public class DynamicClaimsAppService : IdentityAppServiceBase, IDynamicClaimsAppService +{ + protected IAbpClaimsPrincipalFactory AbpClaimsPrincipalFactory { get; } + protected ICurrentPrincipalAccessor PrincipalAccessor { get; } + protected IOptions AbpClaimsPrincipalFactoryOptions { get; } + + public DynamicClaimsAppService( + IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, + ICurrentPrincipalAccessor principalAccessor, + IOptions abpClaimsPrincipalFactoryOptions) + { + AbpClaimsPrincipalFactory = abpClaimsPrincipalFactory; + PrincipalAccessor = principalAccessor; + AbpClaimsPrincipalFactoryOptions = abpClaimsPrincipalFactoryOptions; + } + + public virtual async Task> GetAsync() + { + var principal = await AbpClaimsPrincipalFactory.CreateAsync(PrincipalAccessor.Principal); + + var dynamicClaims = principal.Claims + .Where(c => AbpClaimsPrincipalFactoryOptions.Value.DynamicClaims.Contains(c.Type)) + .Select(c => new DynamicClaimDto + { + Type = c.Type, + Value = c.Value + }); + + return dynamicClaims.ToList(); + } +} diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs new file mode 100644 index 0000000000..d460483a8d --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs @@ -0,0 +1,24 @@ +// This file is automatically generated by ABP framework to use MVC Controllers from CSharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Application.Dtos; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.ClientProxying; +using Volo.Abp.Http.Modeling; + +// ReSharper disable once CheckNamespace +namespace Volo.Abp.Account; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IDynamicClaimsAppService), typeof(DynamicClaimsClientProxy))] +public partial class DynamicClaimsClientProxy : ClientProxyBase, IDynamicClaimsAppService +{ + public virtual async Task> GetAsync() + { + return await RequestAsync>(nameof(GetAsync)); + } +} diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.cs b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.cs new file mode 100644 index 0000000000..da398d8951 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.cs @@ -0,0 +1,7 @@ +// This file is part of DynamicClaimsClientProxy, you can customize it here +// ReSharper disable once CheckNamespace +namespace Volo.Abp.Account; + +public partial class DynamicClaimsClientProxy +{ +} diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json index 24bd9c6079..857c27a3cd 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json +++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json @@ -338,6 +338,47 @@ } } }, + "Volo.Abp.Account.DynamicClaimsController": { + "controllerName": "DynamicClaims", + "controllerGroupName": "DynamicClaims", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.Abp.Account.DynamicClaimsController", + "interfaces": [ + { + "type": "Volo.Abp.Account.IDynamicClaimsAppService", + "name": "IDynamicClaimsAppService", + "methods": [ + { + "name": "GetAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Abp.Account.DynamicClaimDto]" + } + } + ] + } + ], + "actions": { + "GetAsync": { + "uniqueName": "GetAsync", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/account/dynamic-claims", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Abp.Account.DynamicClaimDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Abp.Account.IDynamicClaimsAppService" + } + } + }, "Volo.Abp.Account.ProfileController": { "controllerName": "Profile", "controllerGroupName": "Profile", diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs new file mode 100644 index 0000000000..85587478ed --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace Volo.Abp.Account; + +[RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)] +[Area(AccountRemoteServiceConsts.ModuleName)] +[ControllerName("DynamicClaims")] +[Route("/api/account/dynamic-claims")] +public class DynamicClaimsController : AbpControllerBase, IDynamicClaimsAppService +{ + protected IDynamicClaimsAppService DynamicClaimsAppService { get; } + + public DynamicClaimsController(IDynamicClaimsAppService dynamicClaimsAppService) + { + DynamicClaimsAppService = dynamicClaimsAppService; + } + + [HttpGet] + public virtual Task> GetAsync() + { + return DynamicClaimsAppService.GetAsync(); + } +} diff --git a/modules/account/src/Volo.Abp.Account.Web/wwwroot/client-proxies/account-proxy.js b/modules/account/src/Volo.Abp.Account.Web/wwwroot/client-proxies/account-proxy.js index 2e291710d5..d3c29354ef 100644 --- a/modules/account/src/Volo.Abp.Account.Web/wwwroot/client-proxies/account-proxy.js +++ b/modules/account/src/Volo.Abp.Account.Web/wwwroot/client-proxies/account-proxy.js @@ -79,6 +79,21 @@ })(); + // controller volo.abp.account.dynamicClaims + + (function(){ + + abp.utils.createNamespace(window, 'volo.abp.account.dynamicClaims'); + + volo.abp.account.dynamicClaims.get = function(ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/account/dynamic-claims', + type: 'GET' + }, ajaxParams)); + }; + + })(); + // controller volo.abp.account.profile (function(){ diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs index 536171837a..354e7e4586 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs @@ -62,11 +62,6 @@ public class AbpIdentityDomainModule : AbpModule }); context.Services.AddAbpDynamicOptions(); - - Configure(options => - { - options.DynamicContributors.Add(); - }); } public override void PostConfigureServices(ServiceConfigurationContext context) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs index 4556723fe9..6572c08b7a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs @@ -1,15 +1,13 @@ using System.Linq; -using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; namespace Volo.Abp.Identity; -public class IdentityDynamicClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency +public class IdentityDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincipalContributorBase { - public virtual async Task ContributeAsync(AbpClaimsPrincipalContributorContext context) + public async override Task ContributeAsync(AbpClaimsPrincipalContributorContext context) { var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); var userId = identity?.FindUserId(); @@ -18,11 +16,10 @@ public class IdentityDynamicClaimsPrincipalContributor : IAbpClaimsPrincipalCont return; } - var cache = context.GetRequiredService(); - var dynamicClaims = await cache.GetAsync(userId.Value, identity.FindTenantId()); - foreach (var claim in dynamicClaims) - { - identity.AddOrReplace(new Claim(claim.Type, claim.Value)); - } + var dynamicClaimsCache = context.GetRequiredService(); + var dynamicClaims = await dynamicClaimsCache.GetAsync(userId.Value, identity.FindTenantId()); + + await MapCommonClaimsAsync(identity, dynamicClaims); + await AddDynamicClaims(identity, dynamicClaims); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs index 9102be79c5..7006a97176 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; @@ -16,45 +16,64 @@ namespace Volo.Abp.Identity; public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependency { - protected IServiceProvider ServiceProvider { get; } + public ILogger Logger { get; set; } - public IdentityDynamicClaimsPrincipalContributorCache(IServiceProvider serviceProvider) + protected IDistributedCache> Cache { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IdentityUserManager UserManager { get; } + protected IUserClaimsPrincipalFactory UserClaimsPrincipalFactory { get; } + protected IOptions AbpClaimsPrincipalFactoryOptions { get; } + protected IOptions CacheOptions { get; } + + public IdentityDynamicClaimsPrincipalContributorCache( + IDistributedCache> cache, + ICurrentTenant currentTenant, + IdentityUserManager userManager, + IUserClaimsPrincipalFactory userClaimsPrincipalFactory, + IOptions abpClaimsPrincipalFactoryOptions, + IOptions cacheOptions) { - this.ServiceProvider = serviceProvider; + Cache = cache; + CurrentTenant = currentTenant; + UserManager = userManager; + UserClaimsPrincipalFactory = userClaimsPrincipalFactory; + AbpClaimsPrincipalFactoryOptions = abpClaimsPrincipalFactoryOptions; + CacheOptions = cacheOptions; + + Logger = NullLogger.Instance; } public virtual async Task> GetAsync(Guid userId, Guid? tenantId = null) { - var logger = ServiceProvider.GetRequiredService>(); - logger.LogDebug($"Get dynamic claims cache for user: {userId}"); - - var cache = ServiceProvider.GetRequiredService>>(); + Logger.LogDebug($"Get dynamic claims cache for user: {userId}"); - return await cache.GetOrAddAsync($"{nameof(IdentityDynamicClaimsPrincipalContributorCache)}_{tenantId}_{userId}", async () => + return await Cache.GetOrAddAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId), async () => { - using (ServiceProvider.GetRequiredService().Change(tenantId)) + using (CurrentTenant.Change(tenantId)) { - logger.LogDebug($"Filling dynamic claims cache for user: {userId}"); - var userManager = ServiceProvider.GetRequiredService(); - var user = await userManager.FindByIdAsync(userId.ToString()); + Logger.LogDebug($"Filling dynamic claims cache for user: {userId}"); + + var user = await UserManager.FindByIdAsync(userId.ToString()); if (user == null) { - logger.LogWarning($"User not found: {userId}"); + Logger.LogWarning($"User not found: {userId}"); return new List(); } - var factory = ServiceProvider.GetRequiredService>(); - var principal = await factory.CreateAsync(user); - var options = ServiceProvider.GetRequiredService>().Value; - return principal.Identities.FirstOrDefault()?.Claims.Where(c => options.DynamicClaims.Contains(c.Type)).Select(c => new AbpClaimCacheItem(c.Type, c.Value)).ToList(); + + var principal = await UserClaimsPrincipalFactory.CreateAsync(user); + return principal.Identities.FirstOrDefault()?.Claims + .Where(c => AbpClaimsPrincipalFactoryOptions.Value.DynamicClaims.Contains(c.Type)) + .Select(c => new AbpClaimCacheItem(c.Type, c.Value)).ToList(); } + }, () => new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = CacheOptions.Value.CacheAbsoluteExpiration }); } public virtual async Task ClearAsync(Guid userId, Guid? tenantId = null) { - var cache = ServiceProvider.GetRequiredService>>(); - var logger = ServiceProvider.GetRequiredService>(); - logger.LogDebug($"Clearing dynamic claims cache for user: {userId}"); - await cache.RemoveAsync($"{nameof(IdentityDynamicClaimsPrincipalContributorCache)}_{tenantId}_{userId}"); + Logger.LogDebug($"Clearing dynamic claims cache for user: {userId}"); + await Cache.RemoveAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId)); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCacheOptions.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCacheOptions.cs new file mode 100644 index 0000000000..3387f6cda5 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCacheOptions.cs @@ -0,0 +1,13 @@ +using System; + +namespace Volo.Abp.Identity; + +public class IdentityDynamicClaimsPrincipalContributorCacheOptions +{ + public TimeSpan CacheAbsoluteExpiration { get; set; } + + public IdentityDynamicClaimsPrincipalContributorCacheOptions() + { + CacheAbsoluteExpiration = TimeSpan.FromHours(1); + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs index 60a62cda1e..cf9b339cc1 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs @@ -2,6 +2,7 @@ using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; @@ -22,6 +23,11 @@ public class AbpUserClaimsPrincipalFactory_Tests : AbpIdentityDomainTestBase _testData = GetRequiredService(); } + protected override void AfterAddApplication(IServiceCollection services) + { + services.AddTransient(); + } + [Fact] public async Task Add_And_Replace_Claims_Test() { @@ -42,7 +48,7 @@ public class AbpUserClaimsPrincipalFactory_Tests : AbpIdentityDomainTestBase }); } - class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency + class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor { //https://github.com/dotnet/aspnetcore/blob/v5.0.0/src/Identity/Extensions.Core/src/UserClaimsPrincipalFactory.cs#L79 private static string IdentityAuthenticationType => "Identity.Application"; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs index 2a5a34c7e5..95b2563438 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs @@ -211,6 +211,7 @@ public class MyProjectNameAuthServerModule : AbpModule app.UseMultiTenancy(); } + app.UseDynamicClaims(); app.UseUnitOfWork(); app.UseAuthorization(); app.UseAuditing(); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs index 04ae40fea8..dd890d4dc6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs @@ -44,6 +44,7 @@ using Volo.Abp.Identity.Blazor.Server; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; +using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement.Blazor.Server; using Volo.Abp.Swashbuckle; using Volo.Abp.TenantManagement.Blazor.Server; @@ -188,7 +189,7 @@ public class MyProjectNameBlazorModule : AbpModule * This configuration is used when the AuthServer is running on the internal network such as docker or k8s. * Configuring the redirecting URLs for internal network and the web * The login and the logout URLs are configured to redirect to the AuthServer real DNS for browser. - * The token acquired and validated from the the internal network AuthServer URL. + * The token acquired and validated from the the internal network AuthServer URL. */ if (configuration.GetValue("AuthServer:IsContainerized")) { @@ -227,6 +228,11 @@ public class MyProjectNameBlazorModule : AbpModule }; }); } + + context.Services.Configure(options => + { + options.RemoteUrl = configuration["AuthServer:Authority"] + options.RemoteUrl; + }); } private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment) @@ -351,7 +357,7 @@ public class MyProjectNameBlazorModule : AbpModule { app.UseMultiTenancy(); } - + app.UseDynamicClaims(); app.UseAuthorization(); app.UseSwagger(); app.UseAbpSwaggerUI(options => diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs index e13c32cbf4..0bb20fa36e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs @@ -265,7 +265,7 @@ public class MyProjectNameBlazorModule : AbpModule { app.UseMultiTenancy(); } - + app.UseDynamicClaims(); app.UseUnitOfWork(); app.UseAuthorization(); app.UseSwagger(); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs index 84abc220c8..a323ff8dcd 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs @@ -15,6 +15,7 @@ using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; using Volo.Abp.Identity.Blazor.WebAssembly; +using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement.Blazor.WebAssembly; using Volo.Abp.TenantManagement.Blazor.WebAssembly; @@ -80,6 +81,11 @@ public class MyProjectNameBlazorModule : AbpModule options.ProviderOptions.DefaultScopes.Add("email"); options.ProviderOptions.DefaultScopes.Add("phone"); }); + + builder.Services.Configure(options => + { + options.RemoteUrl = builder.Configuration["AuthServer:Authority"] + options.RemoteUrl; + }); } private static void ConfigureUI(WebAssemblyHostBuilder builder) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 48a250aa4f..d277aa4039 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -24,6 +24,7 @@ using Volo.Abp.Autofac; using Volo.Abp.Caching; using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.DistributedLocking; +using Volo.Abp.Identity; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Swashbuckle; @@ -188,7 +189,7 @@ public class MyProjectNameHttpApiHostModule : AbpModule { app.UseMultiTenancy(); } - + app.UseDynamicClaims(); app.UseAuthorization(); app.UseSwagger(); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs index fe71a42e9a..238339b1cf 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs @@ -198,7 +198,7 @@ public class MyProjectNameHttpApiHostModule : AbpModule { app.UseMultiTenancy(); } - + app.UseDynamicClaims(); app.UseUnitOfWork(); app.UseAuthorization(); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index b59c0bcf08..55a5a4cfdb 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -20,6 +20,7 @@ + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs index fd20023627..01ed6034f8 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs @@ -38,6 +38,7 @@ using Volo.Abp.Identity.Web; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement.Web; +using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement.Web; using Volo.Abp.Swashbuckle; using Volo.Abp.TenantManagement.Web; @@ -170,7 +171,7 @@ public class MyProjectNameWebModule : AbpModule * This configuration is used when the AuthServer is running on the internal network such as docker or k8s. * Configuring the redirecting URLs for internal network and the web * The login and the logout URLs are configured to redirect to the AuthServer real DNS for browser. - * The token acquired and validated from the the internal network AuthServer URL. + * The token acquired and validated from the the internal network AuthServer URL. */ if (configuration.GetValue("AuthServer:IsContainerized")) { @@ -209,6 +210,11 @@ public class MyProjectNameWebModule : AbpModule }; }); } + + context.Services.Configure(options => + { + options.RemoteUrl = configuration["AuthServer:Authority"] + options.RemoteUrl; + }); } private void ConfigureAutoMapper() @@ -316,6 +322,7 @@ public class MyProjectNameWebModule : AbpModule app.UseMultiTenancy(); } + app.UseDynamicClaims(); app.UseAuthorization(); app.UseSwagger(); app.UseAbpSwaggerUI(options => diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index f9c8d6a1c2..a259540829 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -230,6 +230,7 @@ public class MyProjectNameWebModule : AbpModule app.UseMultiTenancy(); } + app.UseDynamicClaims(); app.UseUnitOfWork(); app.UseAuthorization(); app.UseSwagger();