Continue of Dynamic permissions question but with more complex scenario.
I have the entities Risk
, Plan
, and Task
with 1-n
relation between them (Risk
1-n Plan
) and (Plan
1-n Task
). each entity has a property OwnerId
which is related to users entity. Now regarding permission: if I assign the RisksPermission
to some user, he should see all risks, but if another user is assigned as owner for a task or plan, he should see the related risks only (not the ones he is not part of). I managed to make this work in a monolith project as follows:
DynamicPermissionValueProvider
with ProviderName = "D"
RisksPermission
using this dynamic provider (using IPermissionManager.SetAsync
method)RolePermissionValueProvider
or UserPermissionValueProvider
return all risks, if the permission is granted with DynamicPermissionValueProvider
, filter the risks.Now this approach is good for frontend (angular) when using requiredPolicy
for RoutesService
(if the user has the permission with any provider, he can see the risks menu item).
The problem of this approach with microservice project is that IPermissionManager
is only provided in administration service and can't be used in other services.
How can I achieve this scenario in a microservice project.
Thanks in advance
Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, and please first use the search on the homepage. Provide us with the following info:
Hi, I have a custom requirement with permissions and would like to hear a suggested solution for it if possible.
Let's say I have an entity (ex: product
) with a property OwnerId
which is a relation to user entity. Now I need to set permissions for products. If I give a user (user1
) the permissions from the permissions dialog, he should be able to list all products (normal and straight-forward behaviour). My custom requirement is that any user that was assigned as OwnerId
for some products, should be able to see only the products that he was assigned for (not all products in the system).
Example:
I have 2 products (p1
and p2
) and 2 users user1
with products permission and user2
assigned as owner for p1
=> user1
should see the 2 products, user2
should see only p1
I'm working on a micro-service solution and built some services. In one service I have Classificaitons
and Services
App services and some other services. Each one has its permissions and it was working fine. Now my business changed and need to move these 2 app services to another micro-service (called BaseService). When I moved them they stopped working and I'm having AuthorizationException
when I try to access them. Here is the logs from the service:
2024-08-01 18:18:43.034 +03:00 [INF] CORS policy execution failed.
2024-08-01 18:18:43.035 +03:00 [INF] Request origin https://angular.ajwad-sa.com does not have permission to access the resource.
2024-08-01 18:18:45.067 +03:00 [INF] Failed to validate the token.
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty.
at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuerAsync(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuer(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
at Microsoft.IdentityModel.Tokens.InternalValidators.ValidateAfterSignatureFailed(SecurityToken securityToken, Nullable1 notBefore, Nullable
1 expires, IEnumerable1 audiences, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) 2024-08-01 18:18:45.068 +03:00 [INF] Bearer was not authenticated. Failure message: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty. 2024-08-01 18:18:45.070 +03:00 [INF] Executing endpoint 'RMG.Iso20.BaseService.Services.ServiceController.GetListAsync (RMG.Iso20.BaseService.HttpApi)' 2024-08-01 18:18:45.070 +03:00 [INF] Route matched with {area = "BaseService", controller = "Service", action = "GetList"}. Executing controller action with signature System.Threading.Tasks.Task
1[Volo.Abp.Application.Dtos.PagedResultDto`1[RMG.Iso20.BaseService.Services.ServiceWithNavigationPropertiesDto]] GetListAsync(RMG.Iso20.BaseService.Services.GetServicesInput) on controller RMG.Iso20.BaseService.Services.ServiceController (RMG.Iso20.BaseService.HttpApi).
2024-08-01 18:18:45.075 +03:00 [INF] Authorization failed. These requirements were not met:
PermissionRequirement: BaseService.Services
2024-08-01 18:18:45.078 +03:00 [WRN] ---------- RemoteServiceErrorInfo ----------
{
"code": "Volo.Authorization:010001",
"message": "Ùشل التÙويض! لم ØªÙ…Ù†Ø Ø§Ù„Ø³ÙŠØ§Ø³Ø© المعينة.",
"details": null,
"data": {},
"validationErrors": null
}
2024-08-01 18:18:45.078 +03:00 [WRN] Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
Volo.Abp.Authorization.AbpAuthorizationException: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.CheckAsync(IAuthorizationService authorizationService, AuthorizationPolicy policy)
at Volo.Abp.Authorization.MethodInvocationAuthorizationService.CheckAsync(MethodInvocationAuthorizationContext context)
at Volo.Abp.Authorization.AuthorizationInterceptor.AuthorizeAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope) at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter
1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed)
at lambda_method1572(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.
2024-08-01 18:27:42.854 +03:00 [WRN] Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
Volo.Abp.Authorization.AbpAuthorizationException: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.CheckAsync(IAuthorizationService authorizationService, AuthorizationPolicy policy)
at Volo.Abp.Authorization.MethodInvocationAuthorizationService.CheckAsync(MethodInvocationAuthorizationContext context)
at Volo.Abp.Authorization.AuthorizationInterceptor.AuthorizeAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope) at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter
1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed)
at lambda_method1572(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.
I have 2 concerns regarding the logs:
1- Why I'm getting Failed to validate the token. Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty
for this specific microservice only (other microservices work fine)?
2- Logs say that Authorization failed. These requirements were not met: PermissionRequirement: BaseService.Services
but in the frontend this requirement is set on the menu item and it's granted (I can assure this from AbpPermissionGrants database table and from the endpoint of GetPermissions)
P.S: https://angular.ajwad-sa.com
is my frontend site URL (even though I'm sending the requests to the gateway https://gateway.ajwad-sa.com
and yarp is responsible for redirecting to the correct service)
I'm using IIS to serve my services (sites) on the server.
Thanks
I have the micro-service architecture.
Follow the steps described in https://docs.abp.io/en/abp/latest/Distributed-Event-Bus#entity-synchronizer and try to synchronize OrganizationUnit (so I can have a replica of the table in my custom service)
Here is the synchronizer class
public class CssDepartmentSynchronizer :
EntitySynchronizer<CssDepartment, OrganizationUnitEto>
{
private readonly ILogger<CssDepartmentSynchronizer> _logger;
public CssDepartmentSynchronizer(
IObjectMapper objectMapper,
IRepository<CssDepartment> repository,
ILogger<CssDepartmentSynchronizer> logger) : base(objectMapper, repository)
{
_logger = logger;
}
public override Task HandleEventAsync(EntityCreatedEto<OrganizationUnitEto> eventData)
{
_logger.LogInformation("CssDepartmentSynchronizer EntityCreatedEto");
return base.HandleEventAsync(eventData);
}
public override Task HandleEventAsync(EntityDeletedEto<OrganizationUnitEto> eventData)
{
_logger.LogInformation("CssDepartmentSynchronizer EntityDeletedEto");
return base.HandleEventAsync(eventData);
}
public override Task HandleEventAsync(EntityUpdatedEto<OrganizationUnitEto> eventData)
{
_logger.LogInformation("CssDepartmentSynchronizer EntityUpdatedEto");
return base.HandleEventAsync(eventData);
}
protected override async Task<CssDepartment?> FindLocalEntityAsync(OrganizationUnitEto eto)
{
_logger.LogInformation("CssDepartmentSynchronizer FindLocalEntityAsync");
var entity = await Repository.FindAsync(d => d.Id == eto.Id);
if (entity == null)
_logger.LogInformation("CssDepartmentSynchronizer not found");
else
_logger.LogInformation("CssDepartmentSynchronizer found");
return entity;
}
}
This class is not being hit (no logs added to the logs file). Similar code for IdentityUser works fine
public class CssUserSynchronizer :
EntitySynchronizer<CssUser, UserEto>
I'm building an app using the micro-service template.
I have an entity called Service
in my microservice project, this entity has some navigation properties related to Identity entities (Owner
which should relate to IdentityUser
entity, and Department
which should relate to OrganizationUnit
entity).
What is the best way to define this relation?
I searched some topics and read the docs:
UserLookupService
(defined in Volo.Abp.Users
). OrganizationUnit
doesn't.