Open Closed

IntegrationService throws unauthorized error when accessed via another backend service #9992


User avatar
0
tapmui created

Documentation read: https://github.com/abpframework/abp/blob/dev/docs/en/framework/api-development/integration-services.md https://abp.io/community/articles/integration-services-explained-what-they-are-when-to-use-them-and-how-they-behave-lienmsy8#gsc.tab=0 Support notes: https://abp.io/support/questions/8012/Service-to-Service-communication

Problem description:

  • backend service A has and endpoint from where the another module integrationservice is accessed. If the the endpoint in integration service is protected by permission it fails on unauthorized exception (401).
  • the integration endpoint can be accessed directly ie. with postman, no issues.
  • if IotPermissions.IotCombinedDatas.Default permission is removed then this works. But then also this endpoint can be accessed without token. And that is not acceptable.
  • if I add [Authorize] at the service level, again same 401 error. I can add permission IotPermissions.IotCombinedDatas.Default in the backend service A endpoint; user can access this nicely--> this validates that he has the permission allowed.

My excpectation is that the same permissions are to be used also when integrationservice is accessed. What might be the reaso for this; and what is the solution to overcome ? Please advice.

Integrationservice example below:

` [Authorize] // If this is removed then access without token possible, fatal security risk. public class IotintegrationAppService: IotAppService, IIotIntegrationApiService { protected IDistributedCache<IotCombinedDataDownloadTokenCacheItem, string> _downloadTokenCache; protected IIotCombinedDataRepository _iotCombinedDataRepository; protected IotCombinedDataManager _iotCombinedDataManager;

    public IotintegrationAppService(IIotCombinedDataRepository iotCombinedDataRepository, IotCombinedDataManager iotCombinedDataManager, IDistributedCache<IotCombinedDataDownloadTokenCacheItem, string> downloadTokenCache)
    {
        _downloadTokenCache = downloadTokenCache;
        _iotCombinedDataRepository = iotCombinedDataRepository;
        _iotCombinedDataManager = iotCombinedDataManager;

    }

    [Authorize(IotPermissions.IotCombinedDatas.Default)] // If this is removed then I can call this API point.
    public virtual async Task<PagedResultDto<IotCombinedDataDto>> GetListAsync(GetIotCombinedDatasInput input)
    {
        var totalCount = await _iotCombinedDataRepository.GetCountAsync(input.FilterText, input.Status, input.StorageTimeMin, input.StorageTimeMax, input.WorkPhaseOn);
        var items = await _iotCombinedDataRepository.GetListAsync(input.FilterText, input.Status, nput.StorageTimeMin, input.StorageTimeMax, input.WorkPhaseOn, input.Sorting, input.MaxResultCount, input.SkipCount);

        return new PagedResultDto<IotCombinedDataDto>
        {
            TotalCount = totalCount,
            Items = ObjectMapper.Map<List<IotCombinedData>, List<IotCombinedDataDto>>(items)
        };
    }
}


[IntegrationService]
public interface IIotIntegrationApiService : IApplicationService
{
    Task<PagedResultDto<IotCombinedDataDto>> GetListAsync(GetIotCombinedDatasInput input);
}

`


2 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • When you access an ABP Integration Service endpoint from another backend service, the request must include a valid authentication token with the required permissions. If the endpoint is protected by [Authorize] or a permission attribute, and the calling service does not forward the user's access token or does not use a valid service-to-service token with the necessary claims, you will get a 401 Unauthorized error.

    • Integration Services are not exposed by default and typically do not require authorization, but if you add [Authorize] or permission attributes, you must ensure the caller is authenticated and authorized. When you call the endpoint directly (e.g., via Postman), you provide a valid token, so it works. When called from another backend service, unless you explicitly forward the user's token or use a client credentials flow, the call is unauthenticated.

    Solution:

    1. Forward the User's Access Token:

      • When backend service A calls the integration service, ensure it forwards the current user's access token in the Authorization header. This way, the integration service can perform authorization checks based on the user's permissions.
      • In ABP, you can use the IAccessTokenProvider or similar mechanism to retrieve and forward the token.
    2. Use Client Credentials (Service-to-Service):

      • If the call is not on behalf of a user, configure IdentityServer to allow client credentials for service A, and assign the required permissions to the client. The integration service will then authorize based on the client identity.
    3. Check Integration Service Exposure:

      • Make sure you have set AbpAspNetCoreMvcOptions.ExposeIntegrationServices = true in your module configuration to expose integration services.
    4. Security Note:

      • If you remove [Authorize], the endpoint is open to anyone, which is a security risk. Always require authentication and proper permissions.

    Example: Forwarding the Token

    // In backend service A, when calling the integration service:
    var client = _httpClientFactory.CreateClient("IntegrationService");
    client.DefaultRequestHeaders.Authorization = 
        new AuthenticationHeaderValue("Bearer", userAccessToken); // Forward user's token
    

    References:


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    tapmui created

    [AI-Bot] said:

    • When you access an ABP Integration Service endpoint from another backend service, the request must include a valid authentication token with the required permissions. If the endpoint is protected by [Authorize] or a permission attribute, and the calling service does not forward the user's access token or does not use a valid service-to-service token with the necessary claims, you will get a 401 Unauthorized error.

    • Integration Services are not exposed by default and typically do not require authorization, but if you add [Authorize] or permission attributes, you must ensure the caller is authenticated and authorized. When you call the endpoint directly (e.g., via Postman), you provide a valid token, so it works. When called from another backend service, unless you explicitly forward the user's token or use a client credentials flow, the call is unauthenticated.

    Solution:

    1. Forward the User's Access Token:

      • When backend service A calls the integration service, ensure it forwards the current user's access token in the Authorization header. This way, the integration service can perform authorization checks based on the user's permissions.
      • In ABP, you can use the IAccessTokenProvider or similar mechanism to retrieve and forward the token.
    2. Use Client Credentials (Service-to-Service):

      • If the call is not on behalf of a user, configure IdentityServer to allow client credentials for service A, and assign the required permissions to the client. The integration service will then authorize based on the client identity.
    3. Check Integration Service Exposure:

      • Make sure you have set AbpAspNetCoreMvcOptions.ExposeIntegrationServices = true in your module configuration to expose integration services.
    4. Security Note:

      • If you remove [Authorize], the endpoint is open to anyone, which is a security risk. Always require authentication and proper permissions.

    Example: Forwarding the Token

    // In backend service A, when calling the integration service: 
    var client = _httpClientFactory.CreateClient("IntegrationService"); 
    client.DefaultRequestHeaders.Authorization =  
        new AuthenticationHeaderValue("Bearer", userAccessToken); // Forward user's token 
    

    References:


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Thanks for the fast initial response. Comments to it below. to point 1;2; Based on this document I understood that abp.io is doing the addtion of access token automatically: https://abp.io/docs/latest/framework/api-development/dynamic-csharp-clients --> Authenticates the HTTP Client by adding access token to the HTTP header. to point 3; yes already done. -I have also tried to use the dynamic http API directly without integrationservice model; same result (unauthorized). **To point 4: **that is clear as I already said. I'm a bit worried that this is not highlighed in the abp.io documentation clearly.

    Example usage of integration/dynamic proxy:

    `

            GetIotCombinedDatasInput combinedDatasInput = new GetIotCombinedDatasInput
            {
                MaxResultCount = 10,
                SkipCount = 0,
                // DeviceTime < 2025-09-29 12:51:35.394
                DeviceTimeMax = DateTime.Parse("2025-09-29T12:51:35.394", null, DateTimeStyles.AdjustToUniversal)
            };
            try
            {
                var ressu = await _iotCombinedDatasAppService.GetListAsync(combinedDatasInput);
            } catch(Exception e)
            {
                _logger.LogWarning("not working...", e.Message);
                throw;
            }
    

    `

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on October 14, 2025, 08:24