Open Closed

Receiving an 'Unauthorized' error while testing client proxies in a tiered application through Swagger #9291


User avatar
0
Vipinthachinari created

I am working on an ABP-based tiered application (ABP v8.3.4) and facing an issue while testing client proxies through Swagger UI. I generated the client proxy using a local IIS app with the URL https://10.50.1.39:444/ (a non-tiered, single-layered ABP application).

Whenever I try to call an API via the client proxies, I receive a 401 Unauthorized error. However, API methods decorated with the [AllowAnonymous] attribute are working fine and returning the expected values.

I referred to the following documentation for client proxy generation: https://abp.io/docs/8.0/API/Static-CSharp-API-Clients and generated the client proxies in the Application project of the tiered application. Here I am attaching the request and response.


10 Answer(s)
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Can you check your application logs? There should be log that indicates which action fails for authentication. Then we can take action accordingly

  • User Avatar
    0
    Vipinthachinari created

    Can you check your application logs? There should be log that indicates which action fails for authentication. Then we can take action accordingly

    Application log :

    2025-05-07 15:34:51.830 +05:30 [INF] Request starting HTTP/2 GET https://localhost:44393/api/app/branches-client-proxy/10 - null null 2025-05-07 15:34:51.832 +05:30 [INF] Executing endpoint 'QueuingSystem.Branches.BranchesClientProxy.GetAsync (********App.Application)' 2025-05-07 15:34:51.834 +05:30 [INF] Route matched with {action = "Get", controller = "BranchesClientProxy", area = "", page = ""}. Executing controller action with signature System.Threading.Tasks.Task`1[QueuingSystem.Branches.BranchDto] GetAsync(Int32) on controller QueuingSystem.Branches.BranchesClientProxy (********App.Application). 2025-05-07 15:34:52.100 +05:30 [INF] Start processing HTTP request GET https://10.50.1.39:444/api/app/branches/10?api-version=1.0 2025-05-07 15:34:52.100 +05:30 [INF] Sending HTTP request GET https://10.50.1.39:444/api/app/branches/10?api-version=1.0 2025-05-07 15:34:52.197 +05:30 [INF] Received HTTP response headers after 97.5304ms - 401 2025-05-07 15:34:52.197 +05:30 [INF] End processing HTTP request after 97.708ms - 401 2025-05-07 15:34:52.209 +05:30 [ERR] ---------- RemoteServiceErrorInfo ---------- { "code": "Unauthorized", "message": "Unauthorized", "details": null, "data": null, "validationErrors": null }

    2025-05-07 15:34:52.209 +05:30 [ERR] Unauthorized Volo.Abp.Http.Client.AbpRemoteCallException: Unauthorized at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase1.ThrowExceptionForResponseAsync(HttpResponseMessage response) at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase1.RequestAsync(ClientProxyRequestContext requestContext) at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase1.RequestAsync[T](ClientProxyRequestContext requestContext) at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase1.RequestAsync[T](String methodName, ClientProxyRequestTypeValue arguments) at QueuingSystem.Branches.BranchesClientProxy.GetAsync(Int32 id) in F:\CodeBox\QueuingSystemNew**********App\src**********App.Application\ClientProxies\QueuingSystem\Branches\BranchesClientProxy.Generated.cs:line 40 at lambda_method3807(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.

    Code:

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Can you send a sample project that reproduces problem to my E-mail address with this issue number?

    enis.necipoglu@volosoft.com

  • User Avatar
    0
    Vipinthachinari created

    Can you send a sample project that reproduces problem to my E-mail address with this issue number?

    enis.necipoglu@volosoft.com

    https://we.tl/t-Q0QHOMB27Y

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi,

    Here is my first findings:

    Client Proxies is used for sending request by using AppService interfaces from Application.Contracts project they tehy should be generated in HttpApi.Client project. In case of need, you'll need to reference HttpApi.Client project of the related project.

    When you generate them in the application layer, it replaces the original implementation of the interfaces.

  • User Avatar
    0
    Vipinthachinari created

    Hi,

    Here is my first findings:

    Client Proxies is used for sending request by using AppService interfaces from Application.Contracts project they tehy should be generated in HttpApi.Client project. In case of need, you'll need to reference HttpApi.Client project of the related project.

    When you generate them in the application layer, it replaces the original implementation of the interfaces.

    Can you explain this in detail? Also, what changes can I make to this project?

  • User Avatar
    0
    Vipinthachinari created

    Dear,

    I haven’t received a response yet, and I wanted to kindly check if there is any update or if additional information is required from my side. Please let me know the status at your earliest convenience, as this issue is affecting our development timeline.

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi,

    You have to create client-proxies into HttpApi.Client project:

    Otherwise, you replace the original ApplicationService implementation and it cannot work. Whenever you need to consume by using client-proxies, you'll need to use HttpApi.Client and Application.Contracts project reference and use interfaces of your AppServices. Whenever you inject that interface, it'll use ClientProxy if the project has HttpApi.Client reference.

  • User Avatar
    0
    Vipinthachinari created

    Thank you for your reply.

    As mentioned earlier, I am working on an ABP (v8.3.4) Tiered application, and I need to connect it to another ABP (v8.3.4) Single-layer application hosted on my local IIS at the address: https://10.50.1.39:444/.

    Currently, the connection is established using an HttpClient request, where I generate an access token using the following parameters: ClientId, ClientSecret, Scope, GrantType, UserName, and Password.

    The main goal is to access the APIs of the client application (https://10.50.1.39:444/) from my server (Tiered) application.

    As you mentioned, I have created client proxies in the HttpApi.Client project. And the structure looks like below:

    Additionally, I have implemented the same AppServices in both applications, allowing them to operate in a server-client architecture and enabling seamless communication and functionality sharing between the two. However, I am not getting the expected output. Is there anything I might have missed in the configuration or setup? Also, is it possible to achieve the same result using Client Proxies alone, or is additional configuration required?

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hello @k-s-c,

    Thanks for reaching out and providing such a clear description of your setup and the issue you're facing. This "Unauthorized" error in a tiered application with an API Gateway is a classic scenario, and we can definitely help you debug it.

    Based on your description, the problem lies in the authentication flow between your Public Gateway and your Host API, specifically concerning JWT token validation when requests are proxied from HTTPS to HTTP.

    Let's break down the potential causes and how to diagnose them:

    1. RequireHttpsMetadata = false (Revisit this carefully!)

    You've correctly identified RequireHttpsMetadata = false on the JwtBearerOptions as a potential fix for the Host API. This setting is crucial when your IdentityServer (which is your Host API in this case, acting as the token issuer) issues tokens with an iss (issuer) claim that is an HTTPS URL, but the token is then validated by an API (your Host API, when accessed via the gateway) that receives the request over HTTP.

    Action:

    • Verify the iss claim: Inspect a JWT token issued by your Host API (you can get one from the working Swagger UI on the Host API, or by logging in from your MVC app). What is the value of the iss claim? If it's https://your-gateway-domain/, and your Host API is receiving requests over http://localhost:port/, then RequireHttpsMetadata = false is indeed necessary on the Host API's AddJwtBearer configuration.

    • Double-check placement: Ensure RequireHttpsMetadata = false is applied correctly within the ConfigureServices method of your Host API:

      C#

      context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddJwtBearer(options =>
          {
              options.Authority = "https://your-gateway-domain/"; // Or your Host API's public URL if it's directly accessible for discovery
              options.RequireHttpsMetadata = false; // <-- This is the key
              options.Audience = "YourProjectName_Host"; // Or the audience of your Host API
          });
      

      Note: options.Authority should point to the public URL where the IdentityServer discovery document can be found, which would typically be your Public Gateway's HTTPS URL.

    2. Audience Mismatch

    Both the Public Gateway (if it validates) and the Host API must be configured to accept the correct audience (aud claim) in the JWT token. The audience for your Host API is typically its own unique identifier (e.g., "YourProjectName_Host").

    Action:

    • Check OpenIddict configuration: In your Host API's PreConfigureServices, where you configure OpenIddict (ABP's default IdentityServer), ensure the client configuration for your Web MVC app (and any other clients) requests the correct scope/audience:

      C#

      PreConfigure<OpenIddictBuilder>(builder =>
      {
          builder.AddValidation(options =>
          {
              options.AddAudiences("YourApplicationName");
              options.UseLocalServer();
              options.UseAspNetCore();
          });
      });
      
    • Check client applications: Verify that your Web MVC application (or any client obtaining a token) is requesting the "YourProjectName_Host" scope.

    • Check appsettings.json in the DbMigrator: ABP layered template has data seeding logic with DbMigrator. Make sure your credentials is correct in the appsettings.json inside YourProjectName.DbMigrator folder and then execute DbMigrator once when your credentials ready to publish. ⚠️ The production database should be properly migrated

    • Check OpenIddictDataSeedContributor if any change requiremens: In the Domain project you'll see OpenIddict\OpenIddictDataSeedContributor.cs file that seeds all the openiddict configuration to the database. Check there and make sure all of your clients are added there.

    3. Swagger UI and Token Injection

    When using Swagger UI on the Public Gateway, the "Authorize" button injects the bearer token. The issue here might be how Swagger on the Gateway handles this, or if the token it's using is somehow different or malformed when forwarded.

    Action:

    • Inspect Network Calls: Using your browser's developer tools (F12), go to the Network tab on the Swagger UI page of your Public Gateway.
      • Check the request headers: When you try to execute an endpoint, look at the Authorization header. Is the bearer token present? Is it the correct token?
      • Check the response: What is the exact response from the gateway? Is it a 401 directly from the gateway, or is it a 401 relayed from the Host API? This distinction is critical for debugging. If the gateway sends 401, the token validation failed at the gateway. If the Host API sends 401, the token validation failed at the Host API after the gateway forwarded it.

    4. Logging (Your Best Friend!)

    Enable detailed logging on both your Public Gateway and your Host API. Look for logs related to authentication, JWT validation, and authorization.

    Action:

    • Configure Serilog (or default logging): Ensure appsettings.json has sufficient logging levels:JSON

      "Serilog": {
        "MinimumLevel": {
          "Default": "Information",
          "Override": {
            "Microsoft": "Warning",
            "System": "Warning",
            "OpenIddict": "Debug", // Very useful for token validation issues
            "Microsoft.AspNetCore.Authentication": "Debug", // Also very useful
            "Volo.Abp": "Information"
          }
        }
      }
      
    • Examine logs: Look for messages like "token validation failed," "issuer not found," "invalid audience," or "signature validation failed."

    Troubleshooting Steps (Order of operations I'd recommend):

    1. Isolate the Host API: Can you directly call an authenticated endpoint on your Host API (bypassing the Public Gateway) with a valid token obtained from the Host API's own Swagger or by logging in? If this works, the Host API's authentication is correct in isolation.
    2. Inspect Token from Gateway Swagger: Get a token via the Public Gateway's Swagger "Authorize" button. Paste this token into jwt.io.
      • What are the iss (issuer), aud (audience), and exp (expiration) claims?
      • Are the scopes correct?
    3. Network Trace: Use tools like Fiddler, Wireshark, or the browser's developer tools to trace the exact HTTP requests and responses between the Gateway and the Host API. This will show you exactly what headers are being sent (including Authorization).

    Example Scenario and Solution:

    Often, the problem is that the Host API is configured to expect Authority = "https://public-gateway-domain/" (because that's where the discovery document is publicly available), but it's receiving requests over HTTP internally (from the gateway). In this case, RequireHttpsMetadata = false is critical on the Host API's JwtBearerOptions.

    Let me know the results of these checks, especially the network tab analysis and any relevant log messages. With more details, we can narrow down the exact cause.

    Best regards,

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 v9.3.0-preview. Updated on June 13, 2025, 11:37