Open Closed

Authorization in event handlers #1364


User avatar
0
Denis created

Hi

I have issue with distributed event handlers. I am using monoltih deloyment with RabbitMQ enabled. If event handler tryes to call application service, which have authorization attribute enabled, then it gets AbpAuthorizationException.

How this issue can be resolved in ABP?

  • ABP Framework version: v4.3rc1
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes
  • Exception message and stack trace:
  • Steps to reproduce the issue:

12 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Don't call application service in event handler. You can call the domain service that without the Authorization.

  • User Avatar
    0
    Denis created

    hi

    Don't call application service in event handler. You can call the domain service that without the Authorization.

    I can not move Application Service logic into Domain Service because endpoint is implemented by another Module. Event Handler in module A pulls some data from module B using its endpoint

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Can you share some code of your event handler?

  • User Avatar
    0
    Denis created

    Sure. There is simple example of BackgroundJob in my module

    public class UserStatBackgroundJob : IAsyncBackgroundJob<Object>
            {
                private readonly IUserLookupService<AppUser> _userLookupService;
    
                public UserStatBackgroundJob(IUserLookupService<AppUser> userLookupService)
                {
                    _userLookupService = userLookupService;
                }
    
                public async Task ExecuteAsync(Object args)
                {
                    long userCount = await _userLookupService.GetCountAsync();
    
                    //usage of userCount
                }
            }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi @Denis

    You can check the Dynamic-CSharp-API-Clients, It has built-in authentication.

    https://docs.abp.io/en/abp/latest/API/Dynamic-CSharp-API-Clients

    https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs#L22 https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs#L21 https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Volo/Abp/Http/Client/IdentityModel/Web/HttpContextIdentityModelRemoteServiceHttpClientAuthenticator.cs#L45

    https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/appsettings.json#L7 https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs#L19

  • User Avatar
    0
    Denis created

    Hi @maliming

    Can you please explain, how I can do authorization in event handler? I mean that I need to reach the same result as on endpoint execution. Before endpoint executed there is middleware doing authorization. I would like to make that in scope of event handlers

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    As you can see. There is a console app. that call the IProfileAppService which requires authentication and authorization,

    It will use the identity server to get the token, and then call the web api corresponding to IProfileAppService.

    https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/appsettings.json#L7

    You can call application services in a similar way in your event handler or background job/work.

  • User Avatar
    0
    Denis created

    Hi

    Sorriy, but I could not find what you wrote about on page provided by link. Can you please send link to source of project you talking about?

    Also I would want to give more details about by question. I would like to not bind to http client proxy implementation of application services, so calls will be done via HTTP always for any deployment: monolith or microservices. I want to keep event handlers without changes, but also implement Attribute for authentication and authorization, at same way as that done in middleware which is called before endpoint execution. This Attribute will use JWT token provided in app configuration. Execution authorization will be done before event handler call, in the way as it is done in ABP middleware before endpoint execution, so all application services in monolith will be called directly in runtime, as that would be done by another application service during endpoint execution.

    In short - I want CurrentUser and CurrentTenant will be provided before event handler execution

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Sorriy, but I could not find what you wrote about on page provided by link. Can you please send link to source of project you talking about?

    If you create an app project, you will find a HttpApi.Client.ConsoleTestApp project, which will call the application service that requires authorization. It is done automatically in the ConsoleTestApp project. You can think of it as event handler or background job/work.

    In a monolithic application, it will directly use application services, and in tiered or microservices, it will automatically call web api.

    In short - I want CurrentUser and CurrentTenant will be provided before event handler execution

    I don't fully understand, can you share some code?

  • User Avatar
    0
    Denis created

    Sure. The same as in endpoint. CurrentUser is materizled from JWT token which passed to event data or in appsettings

    public class UserStatBackgroundJob : IAsyncBackgroundJob<Object>
    {
        private readonly IUserLookupService<AppUser> _userLookupService;
        
        ICurrentUser _currentUser;     <<--------
    
        public UserStatBackgroundJob(IUserLookupService<AppUser> userLookupService, ICurrentUser currentUser)
        {
            _userLookupService = userLookupService;
            _currentUser = currentUser      <<-------
        }
    
        public async Task ExecuteAsync(Object args)
        {
            long userCount = await _userLookupService.GetCountAsync();
            
            var userName = currentUser.Name;         <<---------
    
            //usage of userCount
        }
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I think you can change the tenant, but change the user is currently impossible.

    using (CurrentTenant.Change(tenantId))
    {
        long userCount = await _userLookupService.GetCountAsync();
    }
    
  • User Avatar
    0
    ServiceBot created
    Support Team Automatic process manager

    This question has been automatically marked as stale because it has not had recent activity.

Made with ❤️ on ABP v9.1.0-preview. Updated on November 19, 2024, 12:56