Browse Source

Refresh instead of returning dynamic claims.

pull/18064/head
maliming 3 years ago
parent
commit
e407754280
  1. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs
  2. 72
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs
  3. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs
  4. 12
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs
  5. 22
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheItem.cs
  6. 8
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs
  7. 17
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaim.cs
  8. 25
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimCacheItem.cs
  9. 4
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs
  10. 24
      framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs
  11. 2
      modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/IDynamicClaimsAppService.cs
  12. 33
      modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs
  13. 4
      modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs
  14. 20
      modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json
  15. 7
      modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs
  16. 6
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs
  17. 16
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs
  18. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs
  19. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs
  20. 5
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs
  21. 3
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs
  22. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
  23. 5
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs
  24. 9
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs
  25. 5
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs

19
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributor.cs

@ -1,6 +1,9 @@
using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Mvc.Client;
@ -22,8 +25,20 @@ public class RemoteDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincipal
}
var dynamicClaimsCache = context.GetRequiredService<RemoteDynamicClaimsPrincipalContributorCache>();
var dynamicClaims = await dynamicClaimsCache.GetAsync(userId.Value, identity.FindTenantId());
AbpDynamicClaimCacheItem dynamicClaims;
try
{
dynamicClaims = await dynamicClaimsCache.GetAsync(userId.Value, identity.FindTenantId());
}
catch (Exception e)
{
// In case if failed refresh remote dynamic cache, We force to clear the claims principal.
context.ClaimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity());
var logger = context.GetRequiredService<ILogger<RemoteDynamicClaimsPrincipalContributor>>();
logger.LogWarning(e, $"Failed to refresh remote dynamic claims cache for user: {userId.Value}");
return;
}
await AddDynamicClaimsAsync(context, identity, dynamicClaims);
await AddDynamicClaimsAsync(context, identity, dynamicClaims.Claims);
}
}

72
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs

@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
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;
@ -21,76 +19,58 @@ public class RemoteDynamicClaimsPrincipalContributorCache : ITransientDependency
public const string HttpClientName = nameof(RemoteDynamicClaimsPrincipalContributorCache);
public ILogger<RemoteDynamicClaimsPrincipalContributorCache> Logger { get; set; }
protected IDistributedCache<List<AbpClaimCacheItem>> Cache { get; }
protected IDistributedCache<AbpDynamicClaimCacheItem> Cache { get; }
protected IHttpClientFactory HttpClientFactory { get; }
protected IOptions<AbpClaimsPrincipalFactoryOptions> AbpClaimsPrincipalFactoryOptions { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; }
protected IOptions<RemoteDynamicClaimsPrincipalContributorCacheOptions> CacheOptions { get; }
public RemoteDynamicClaimsPrincipalContributorCache(
IDistributedCache<List<AbpClaimCacheItem>> cache,
IDistributedCache<AbpDynamicClaimCacheItem> cache,
IHttpClientFactory httpClientFactory,
IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions,
IJsonSerializer jsonSerializer,
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator,
IOptions<RemoteDynamicClaimsPrincipalContributorCacheOptions> cacheOptions)
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator)
{
Cache = cache;
HttpClientFactory = httpClientFactory;
AbpClaimsPrincipalFactoryOptions = abpClaimsPrincipalFactoryOptions;
JsonSerializer = jsonSerializer;
HttpClientAuthenticator = httpClientAuthenticator;
CacheOptions = cacheOptions;
Logger = NullLogger<RemoteDynamicClaimsPrincipalContributorCache>.Instance;
}
public virtual async Task<List<AbpClaimCacheItem>> GetAsync(Guid userId, Guid? tenantId = null)
public virtual async Task<AbpDynamicClaimCacheItem> 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())
var claims = await Cache.GetAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId));
if (claims != null && !claims.Claims.IsNullOrEmpty())
{
return claims!;
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 () =>
Logger.LogDebug($"Refresh dynamic claims for user: {userId} from remote service.");
try
{
var dynamicClaims = AbpClaimsPrincipalFactoryOptions.Value.DynamicClaims.Select(claimType => new AbpClaimCacheItem(claimType, null)).ToList();
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);
var remoteClaims = JsonSerializer.Deserialize<List<AbpClaimCacheItem>>(await response.Content.ReadAsStringAsync());
foreach (var claim in dynamicClaims)
{
claim.Value = remoteClaims.FirstOrDefault(c => c.Type == claim.Type)?.Value;
}
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
var client = HttpClientFactory.CreateClient(HttpClientName);
var requestMessage = new HttpRequestMessage(HttpMethod.Post, AbpClaimsPrincipalFactoryOptions.Value.RemoteRefreshUrl);
await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration("/"), string.Empty));
var response = await client.SendAsync(requestMessage);
response.EnsureSuccessStatusCode();
}
catch (Exception e)
{
AbsoluteExpirationRelativeToNow = CacheOptions.Value.CacheAbsoluteExpiration
}))!;
}
Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}");
throw;
}
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)}");
claims = await Cache.GetAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId));
if (claims == null || claims.Claims.IsNullOrEmpty())
{
throw new AbpException($"Failed to refresh remote claims for user: {userId}");
}
return claims!;
}
}

13
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCacheOptions.cs

@ -1,13 +0,0 @@
using System;
namespace Volo.Abp.AspNetCore.Mvc.Client;
public class RemoteDynamicClaimsPrincipalContributorCacheOptions
{
public TimeSpan CacheAbsoluteExpiration { get; set; }
public RemoteDynamicClaimsPrincipalContributorCacheOptions()
{
CacheAbsoluteExpiration = TimeSpan.FromSeconds(60);
}
}

12
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs

@ -1,9 +1,9 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Security.Claims;
@ -11,11 +11,13 @@ public class AbpDynamicClaimsMiddleware : IMiddleware, ITransientDependency
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var currentUser = context.RequestServices.GetRequiredService<ICurrentUser>();
if (currentUser.IsAuthenticated)
if (context.User.Identity?.IsAuthenticated == true)
{
var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>();
context.User = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User);
if (context.RequestServices.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value.IsDynamicClaimsEnabled)
{
var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>();
context.User = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User);
}
}
await next(context);

22
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimCacheItem.cs

@ -1,22 +0,0 @@
using System;
namespace Volo.Abp.Security.Claims;
[Serializable]
public class AbpClaimCacheItem
{
public string Type { get; set; }
public string? Value { get; set; }
public AbpClaimCacheItem(string type, string? value)
{
Type = type;
Value = value;
}
public static string CalculateCacheKey(Guid userId, Guid? tenantId)
{
return $"{tenantId}-{userId}";
}
}

8
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactoryOptions.cs

@ -12,10 +12,12 @@ public class AbpClaimsPrincipalFactoryOptions
public List<string> DynamicClaims { get; }
public string RemoteUrl { get; set; }
public string RemoteRefreshUrl { get; set; }
public Dictionary<string, List<string>> ClaimsMap { get; set; }
public bool IsDynamicClaimsEnabled { get; set; }
public AbpClaimsPrincipalFactoryOptions()
{
Contributors = new TypeList<IAbpClaimsPrincipalContributor>();
@ -33,7 +35,7 @@ public class AbpClaimsPrincipalFactoryOptions
AbpClaimTypes.PhoneNumberVerified
};
RemoteUrl = "/api/account/dynamic-claims";
RemoteRefreshUrl = "/api/account/dynamic-claims/refresh";
ClaimsMap = new Dictionary<string, List<string>>()
{
@ -43,5 +45,7 @@ public class AbpClaimsPrincipalFactoryOptions
{ AbpClaimTypes.Role, new List<string> { "role", "roles", ClaimTypes.Role }},
{ AbpClaimTypes.Email, new List<string> { "email", ClaimTypes.Email }},
};
IsDynamicClaimsEnabled = false;
}
}

17
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaim.cs

@ -0,0 +1,17 @@
using System;
namespace Volo.Abp.Security.Claims;
[Serializable]
public class AbpDynamicClaim
{
public string Type { get; set; }
public string? Value { get; set; }
public AbpDynamicClaim(string type, string? value)
{
Type = type;
Value = value;
}
}

25
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimCacheItem.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Security.Claims;
[Serializable]
public class AbpDynamicClaimCacheItem
{
public List<AbpDynamicClaim> Claims { get; set; }
public AbpDynamicClaimCacheItem()
{
Claims = new List<AbpDynamicClaim>();
}
public AbpDynamicClaimCacheItem(List<AbpDynamicClaim> claims)
{
Claims = claims;
}
public static string CalculateCacheKey(Guid userId, Guid? tenantId)
{
return $"{tenantId}-{userId}";
}
}

4
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase.cs

@ -12,7 +12,7 @@ public abstract class AbpDynamicClaimsPrincipalContributorBase : IAbpDynamicClai
{
public abstract Task ContributeAsync(AbpClaimsPrincipalContributorContext context);
protected virtual async Task AddDynamicClaimsAsync(AbpClaimsPrincipalContributorContext context, ClaimsIdentity identity, List<AbpClaimCacheItem> dynamicClaims)
protected virtual async Task AddDynamicClaimsAsync(AbpClaimsPrincipalContributorContext context, ClaimsIdentity identity, List<AbpDynamicClaim> dynamicClaims)
{
var options = context.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value;
foreach (var map in options.ClaimsMap)
@ -27,7 +27,7 @@ public abstract class AbpDynamicClaimsPrincipalContributorBase : IAbpDynamicClai
}
}
protected virtual Task MapClaimAsync(ClaimsIdentity identity, List<AbpClaimCacheItem> dynamicClaims, string targetClaimType, params string[] sourceClaimTypes)
protected virtual Task MapClaimAsync(ClaimsIdentity identity, List<AbpDynamicClaim> dynamicClaims, string targetClaimType, params string[] sourceClaimTypes)
{
var claims = dynamicClaims.Where(c => sourceClaimTypes.Contains(c.Type)).ToList();
if (claims.IsNullOrEmpty())

24
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpDynamicClaimsPrincipalContributorBase_Tests.cs

@ -16,7 +16,7 @@ class TestAbpDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincipalContri
var identity = context.ClaimsPrincipal.Identities.FirstOrDefault();
Check.NotNull(identity, nameof(identity));
await AddDynamicClaimsAsync(context, identity, AbpDynamicClaimsPrincipalContributorBase_Tests.DynamicClaims);
await AddDynamicClaimsAsync(context, identity, AbpDynamicClaimsPrincipalContributorBase_Tests.DynamicClaims.Claims);
}
}
@ -24,7 +24,7 @@ public class AbpDynamicClaimsPrincipalContributorBase_Tests : AbpIntegratedTest<
{
private readonly TestAbpDynamicClaimsPrincipalContributor _dynamicClaimsPrincipalContributorBase = new TestAbpDynamicClaimsPrincipalContributor();
public readonly static List<AbpClaimCacheItem> DynamicClaims = new List<AbpClaimCacheItem>();
public readonly static AbpDynamicClaimCacheItem DynamicClaims = new AbpDynamicClaimCacheItem();
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
@ -46,17 +46,17 @@ public class AbpDynamicClaimsPrincipalContributorBase_Tests : AbpIntegratedTest<
claimsPrincipal.Identities.First().AddClaim(new Claim(AbpClaimTypes.PhoneNumberVerified, "test-source-phoneNumberVerified"));
claimsPrincipal.Identities.First().AddClaim(new Claim("my-claim", "test-source-my-claim"));
DynamicClaims.AddRange(new []
DynamicClaims.Claims.AddRange(new []
{
new AbpClaimCacheItem("preferred_username", "test-preferred_username"),
new AbpClaimCacheItem(ClaimTypes.GivenName, "test-given_name"),
new AbpClaimCacheItem("family_name", "test-family_name"),
new AbpClaimCacheItem("role", "test-role1"),
new AbpClaimCacheItem("roles", "test-role2"),
new AbpClaimCacheItem(ClaimTypes.Role, "test-role3"),
new AbpClaimCacheItem("email", "test-email"),
new AbpClaimCacheItem(AbpClaimTypes.EmailVerified, "test-email-verified"),
new AbpClaimCacheItem(AbpClaimTypes.PhoneNumberVerified, null),
new AbpDynamicClaim("preferred_username", "test-preferred_username"),
new AbpDynamicClaim(ClaimTypes.GivenName, "test-given_name"),
new AbpDynamicClaim("family_name", "test-family_name"),
new AbpDynamicClaim("role", "test-role1"),
new AbpDynamicClaim("roles", "test-role2"),
new AbpDynamicClaim(ClaimTypes.Role, "test-role3"),
new AbpDynamicClaim("email", "test-email"),
new AbpDynamicClaim(AbpClaimTypes.EmailVerified, "test-email-verified"),
new AbpDynamicClaim(AbpClaimTypes.PhoneNumberVerified, null),
});
await _dynamicClaimsPrincipalContributorBase.ContributeAsync(new AbpClaimsPrincipalContributorContext(claimsPrincipal, GetRequiredService<IServiceProvider>()));

2
modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/IDynamicClaimsAppService.cs

@ -6,5 +6,5 @@ namespace Volo.Abp.Account;
public interface IDynamicClaimsAppService : IApplicationService
{
Task<List<DynamicClaimDto>> GetAsync();
Task RefreshAsync();
}

33
modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/DynamicClaimsAppService.cs

@ -1,48 +1,31 @@
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;
using Volo.Abp.Users;
namespace Volo.Abp.Account;
[Authorize]
public class DynamicClaimsAppService : IdentityAppServiceBase, IDynamicClaimsAppService
{
protected IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache { get; }
protected IAbpClaimsPrincipalFactory AbpClaimsPrincipalFactory { get; }
protected ICurrentPrincipalAccessor PrincipalAccessor { get; }
protected IOptions<AbpClaimsPrincipalFactoryOptions> AbpClaimsPrincipalFactoryOptions { get; }
public DynamicClaimsAppService(
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache,
IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory,
ICurrentPrincipalAccessor principalAccessor,
IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions)
ICurrentPrincipalAccessor principalAccessor)
{
IdentityDynamicClaimsPrincipalContributorCache = identityDynamicClaimsPrincipalContributorCache;
AbpClaimsPrincipalFactory = abpClaimsPrincipalFactory;
PrincipalAccessor = principalAccessor;
AbpClaimsPrincipalFactoryOptions = abpClaimsPrincipalFactoryOptions;
}
public virtual async Task<List<DynamicClaimDto>> GetAsync()
public virtual async Task RefreshAsync()
{
var principal = await AbpClaimsPrincipalFactory.CreateAsync(PrincipalAccessor.Principal);
var dynamicClaims = new List<DynamicClaimDto>();
foreach (var claimType in AbpClaimsPrincipalFactoryOptions.Value.DynamicClaims)
{
var claims = principal.Claims.Where(x => x.Type == claimType).ToList();
if (claims.Any())
{
dynamicClaims.AddRange(claims.Select(claim => new DynamicClaimDto(claimType, claim.Value)));
}
else
{
dynamicClaims.Add(new DynamicClaimDto(claimType, null));
}
}
return dynamicClaims;
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(CurrentUser.GetId(), CurrentUser.TenantId);
await AbpClaimsPrincipalFactory.CreateDynamicAsync(PrincipalAccessor.Principal);
}
}

4
modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/Volo/Abp/Account/DynamicClaimsClientProxy.Generated.cs

@ -17,8 +17,8 @@ namespace Volo.Abp.Account;
[ExposeServices(typeof(IDynamicClaimsAppService), typeof(DynamicClaimsClientProxy))]
public partial class DynamicClaimsClientProxy : ClientProxyBase<IDynamicClaimsAppService>, IDynamicClaimsAppService
{
public virtual async Task<List<DynamicClaimDto>> GetAsync()
public virtual async Task RefreshAsync()
{
return await RequestAsync<List<DynamicClaimDto>>(nameof(GetAsync));
await RequestAsync(nameof(RefreshAsync));
}
}

20
modules/account/src/Volo.Abp.Account.HttpApi.Client/ClientProxies/account-generate-proxy.json

@ -351,28 +351,28 @@
"name": "IDynamicClaimsAppService",
"methods": [
{
"name": "GetAsync",
"name": "RefreshAsync",
"parametersOnMethod": [],
"returnValue": {
"type": "System.Collections.Generic.List<Volo.Abp.Account.DynamicClaimDto>",
"typeSimple": "[Volo.Abp.Account.DynamicClaimDto]"
"type": "System.Void",
"typeSimple": "System.Void"
}
}
]
}
],
"actions": {
"GetAsync": {
"uniqueName": "GetAsync",
"name": "GetAsync",
"httpMethod": "GET",
"url": "api/account/dynamic-claims",
"RefreshAsync": {
"uniqueName": "RefreshAsync",
"name": "RefreshAsync",
"httpMethod": "POST",
"url": "api/account/dynamic-claims/refresh",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
"returnValue": {
"type": "System.Collections.Generic.List<Volo.Abp.Account.DynamicClaimDto>",
"typeSimple": "[Volo.Abp.Account.DynamicClaimDto]"
"type": "System.Void",
"typeSimple": "System.Void"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.Account.IDynamicClaimsAppService"

7
modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/DynamicClaimsController.cs

@ -18,9 +18,10 @@ public class DynamicClaimsController : AbpControllerBase, IDynamicClaimsAppServi
DynamicClaimsAppService = dynamicClaimsAppService;
}
[HttpGet]
public virtual Task<List<DynamicClaimDto>> GetAsync()
[HttpPost]
[Route("refresh")]
public virtual Task RefreshAsync()
{
return DynamicClaimsAppService.GetAsync();
return DynamicClaimsAppService.RefreshAsync();
}
}

6
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor.cs

@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
@ -22,7 +20,7 @@ public class IdentityDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincip
}
var dynamicClaimsCache = context.GetRequiredService<IdentityDynamicClaimsPrincipalContributorCache>();
List<AbpClaimCacheItem> dynamicClaims;
AbpDynamicClaimCacheItem dynamicClaims;
try
{
dynamicClaims = await dynamicClaimsCache.GetAsync(userId.Value, identity.FindTenantId());
@ -36,6 +34,6 @@ public class IdentityDynamicClaimsPrincipalContributor : AbpDynamicClaimsPrincip
return;
}
await AddDynamicClaimsAsync(context, identity, dynamicClaims);
await AddDynamicClaimsAsync(context, identity, dynamicClaims.Claims);
}
}

16
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs

@ -18,7 +18,7 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen
{
public ILogger<IdentityDynamicClaimsPrincipalContributorCache> Logger { get; set; }
protected IDistributedCache<List<AbpClaimCacheItem>> Cache { get; }
protected IDistributedCache<AbpDynamicClaimCacheItem> Cache { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IdentityUserManager UserManager { get; }
protected IUserClaimsPrincipalFactory<IdentityUser> UserClaimsPrincipalFactory { get; }
@ -26,7 +26,7 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen
protected IOptions<IdentityDynamicClaimsPrincipalContributorCacheOptions> CacheOptions { get; }
public IdentityDynamicClaimsPrincipalContributorCache(
IDistributedCache<List<AbpClaimCacheItem>> cache,
IDistributedCache<AbpDynamicClaimCacheItem> cache,
ICurrentTenant currentTenant,
IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> userClaimsPrincipalFactory,
@ -43,11 +43,11 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen
Logger = NullLogger<IdentityDynamicClaimsPrincipalContributorCache>.Instance;
}
public virtual async Task<List<AbpClaimCacheItem>> GetAsync(Guid userId, Guid? tenantId = null)
public virtual async Task<AbpDynamicClaimCacheItem> GetAsync(Guid userId, Guid? tenantId = null)
{
Logger.LogDebug($"Get dynamic claims cache for user: {userId}");
return await Cache.GetOrAddAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId), async () =>
return await Cache.GetOrAddAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId), async () =>
{
using (CurrentTenant.Change(tenantId))
{
@ -56,17 +56,17 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen
var user = await UserManager.GetByIdAsync(userId);
var principal = await UserClaimsPrincipalFactory.CreateAsync(user);
var dynamicClaims = new List<AbpClaimCacheItem>();
var dynamicClaims = new AbpDynamicClaimCacheItem();
foreach (var claimType in AbpClaimsPrincipalFactoryOptions.Value.DynamicClaims)
{
var claims = principal.Claims.Where(x => x.Type == claimType).ToList();
if (claims.Any())
{
dynamicClaims.AddRange(claims.Select(claim => new AbpClaimCacheItem(claimType, claim.Value)));
dynamicClaims.Claims.AddRange(claims.Select(claim => new AbpDynamicClaim(claimType, claim.Value)));
}
else
{
dynamicClaims.Add(new AbpClaimCacheItem(claimType, null));
dynamicClaims.Claims.Add(new AbpDynamicClaim(claimType, null));
}
}
@ -81,6 +81,6 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen
public virtual async Task ClearAsync(Guid userId, Guid? tenantId = null)
{
Logger.LogDebug($"Clearing dynamic claims cache for user: {userId}");
await Cache.RemoveAsync(AbpClaimCacheItem.CalculateCacheKey(userId, tenantId));
await Cache.RemoveAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId));
}
}

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs

@ -32,6 +32,7 @@ using Volo.Abp.DistributedLocking;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.OpenIddict;
using Volo.Abp.Security.Claims;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.UI;
using Volo.Abp.VirtualFileSystem;
@ -180,6 +181,11 @@ public class MyProjectNameAuthServerModule : AbpModule
.AllowCredentials();
});
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs

@ -231,7 +231,8 @@ public class MyProjectNameBlazorModule : AbpModule
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.RemoteUrl = configuration["AuthServer:Authority"] + options.RemoteUrl;
options.IsDynamicClaimsEnabled = true;
options.RemoteRefreshUrl = configuration["AuthServer:Authority"] + options.RemoteRefreshUrl;
});
}

5
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs

@ -34,6 +34,7 @@ using Volo.Abp.AutoMapper;
using Volo.Abp.Identity.Blazor.Server;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.Blazor.Server;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TenantManagement.Blazor.Server;
@ -122,6 +123,10 @@ public class MyProjectNameBlazorModule : AbpModule
private void ConfigureAuthentication(ServiceConfigurationContext context)
{
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureUrls(IConfiguration configuration)

3
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs

@ -84,7 +84,8 @@ public class MyProjectNameBlazorModule : AbpModule
builder.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.RemoteUrl = builder.Configuration["AuthServer:Authority"] + options.RemoteUrl;
options.IsDynamicClaimsEnabled = true;
options.RemoteRefreshUrl = builder.Configuration["AuthServer:Authority"] + options.RemoteRefreshUrl;
});
}

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs

@ -27,6 +27,7 @@ using Volo.Abp.DistributedLocking;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
@ -106,6 +107,11 @@ public class MyProjectNameHttpApiHostModule : AbpModule
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
options.Audience = "MyProjectName";
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)

5
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs

@ -25,6 +25,7 @@ using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Swashbuckle;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
@ -74,6 +75,10 @@ public class MyProjectNameHttpApiHostModule : AbpModule
private void ConfigureAuthentication(ServiceConfigurationContext context)
{
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureBundles()

9
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs

@ -211,10 +211,11 @@ public class MyProjectNameWebModule : AbpModule
});
}
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.RemoteUrl = configuration["AuthServer:Authority"] + options.RemoteUrl;
});
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
options.RemoteRefreshUrl = configuration["AuthServer:Authority"] + options.RemoteRefreshUrl;
});
}
private void ConfigureAutoMapper()

5
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs

@ -30,6 +30,7 @@ using Volo.Abp.Identity.Web;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.Web;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.Web;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TenantManagement.Web;
@ -115,6 +116,10 @@ public class MyProjectNameWebModule : AbpModule
private void ConfigureAuthentication(ServiceConfigurationContext context)
{
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
}
private void ConfigureUrls(IConfiguration configuration)

Loading…
Cancel
Save