dotnet / AspNetCore.Docs

Documentation for ASP.NET Core
https://docs.microsoft.com/aspnet/core
Creative Commons Attribution 4.0 International
12.62k stars 25.3k forks source link

Example for "Attach Tokens to Outgoing Requests" does not work #31598

Closed jdh148 closed 2 months ago

jdh148 commented 9 months ago

Description

I followed the Attach Tokens to Outgoing Requests section of this page to setup BaseAddressAuthorizationMessageHandler but no Authorization token is being added to the header of the API requests. Authentication was setup using the "Standalone With Authentication Library" documentation; it redirects to the authentication service login page, and I have it displaying full name of the authenticated user to verify the token is working properly, and a token is being stored in the session storage. But HttpClient is not adding the Authorization token to the request header. I've followed this documentation very closely and cannot get this to work. Is there something missing from the documentation, or am I missing something?

My appsettings.json looks like this:

{
  "ApiServer": "https://localhost:7256/",
  "Local": {
    "Authority": "http://localhost:8080/realms/MyAppRealm",
    "ClientId": "myapp-webui"
  }
}

And my program.cs contains:

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

var apiServer = builder.Configuration["ApiServer"] ?? "http://0.0.0.0";

builder.Services.AddHttpClient("WebAPI",
        client => client.BaseAddress = new Uri(apiServer))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("WebAPI"));

builder.Services.AddOidcAuthentication(options =>
{
    options.ProviderOptions.DefaultScopes.Add(apiServer);
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

await builder.Build().RunAsync();

And my Blazor page contains:

@page "/myPage"
@attribute [Authorize]
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient http

<h3>My Page</h3>

@if (myList != null)
{
    @foreach (var myData in myList)
    {
        @myData.Field
        <br/>
    }    
}

@code {
    private IEnumerable<TestDto>? myList;

    protected override async Task OnInitializedAsync()
    {
        myList = await http.GetFromJsonAsync<IEnumerable<TestDto>>("/myEndpoint");
    }
}

The browser console doesn't seem to contain any clues as to why this isn't working:

invoke-js.ts:176 info: System.Net.Http.HttpClient.WebAPI.LogicalHandler[100]
      Start processing HTTP request GET https://localhost:7256/myEndpoint
invoke-js.ts:176 info: System.Net.Http.HttpClient.WebAPI.ClientHandler[100]
      Sending HTTP request GET https://localhost:7256/myEndpoint
polyfills.ts:120 GET https://localhost:7256/myEndpoint 401 (Unauthorized)
invoke-js.ts:176 info: System.Net.Http.HttpClient.WebAPI.ClientHandler[101]
      Received HTTP response headers after 58.3ms - 401
invoke-js.ts:176 info: System.Net.Http.HttpClient.WebAPI.LogicalHandler[101]
      End processing HTTP request after 75.8ms - 401
blazor.webassembly.js:1  crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized).

Page URL

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-8.0

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/security/webassembly/additional-scenarios.md

Document ID

cc8dfcd6-8d93-5aa3-c381-2b613e88cdbe

Article author

@guardrex

github-actions[bot] commented 9 months ago

πŸŽ‰πŸ₯³ Happy New Year! πŸ’ƒπŸ•Ί

A green dinosaur πŸ¦– will be along shortly to assist. Stand-by ........

guardrex commented 9 months ago

Hello @jdh148 ...

polyfills.ts:120 GET https://localhost:7256/myEndpoint 401 (Unauthorized)

... that seems rather strange πŸ‘½ to me. IIRC, polyfills were only used for some legacy browser scenarios.

Anyway, I'll see if I can repro a problem here. If I can't repro a problem, then we'll get some help from the product unit to figure out what's going on. Stand-by, I'll get back to you shortly ...................

guardrex commented 9 months ago

I don't see a problem here. Go ahead and open an issue on the product unit (PU) repo ...

https://github.com/dotnet/aspnetcore/issues

Indicate to Javier, who usually handles these sorts of issues, that you're following the guidance in the following articles. I'm formatting these links as a direct copy-paste for your issue ...

* [Secure an ASP.NET Core Blazor WebAssembly standalone app with the Authentication library](https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-authentication-library?view=aspnetcore-8.0&tabs=visual-studio) * [Attach tokens to outgoing requests](https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-8.0#attach-tokens-to-outgoing-requests)

Please add ...

cc: @guardrex https://github.com/dotnet/AspNetCore.Docs/issues/31598

... to the bottom of your opening comment. That will ping me and cross-link this issue.

You can copy-paste your OP comment into your PU issue ☝️ over there, but Javier will probably want to see a full minimal repro placed in GH with frontend and backend apps that demonstrates the problem. They prefer to see how you have everything set up, and they often pull down your sample and run it locally to troubleshoot a problem.

I'll close this for now, but I'll be πŸ‘€ on your PU issue and will re-open this for doc work depending on what the investigation uncovers.

jdh148 commented 8 months ago

Here is a repository I created with the sample Web API and Blazor WASM projects, modified to follow the instructions from the Blazor documentation for authentication. The commit history goes through the major steps.

I would appreciate at least a pointer to where I'm going wrong. I've read and follows this documentation as closely as possible and I cannot see where I'm going wrong.

The Web API authentication works when tested with Swagger, and Blazor WASM can authenticate to OIDC and stores a token, but Blazor will not send the token to the API.

guardrex commented 8 months ago

@jdh148 ... I just said what to do in my last remark ☝️.

guardrex commented 8 months ago

@jdh148 ... I'll re-open to take another look now that Stephen is saying that it's likely some kind of basic implementation problem. We don't document OIDC, as you know. However, I'm not opposed to adding an OIDC pivot to this article, and OIDC should work with Entra and a web API with fairly minimal changes. The problem is TIME ⏰. I'm kind'a swamped with work these days ... still trying to wrap up the 8.0 work AND now on to documenting new preview features for .NET 9. If you're able to figure it out on your own, perhaps with the assistance of the community, please let me know back here how it played out. Otherwise, I'll try to get back to this as soon as I can, but it might take me weeks to get back here ... possibly even months πŸ™ˆ ... that's how busy I am these days.

Here are the links to the usual community support channels that we recommend ...

guardrex commented 2 months ago

@jdh148 ... I finally made it here after a busy period of closing out issues for several months β›°οΈβ›οΈπŸ˜….

I understand from the product unit issue that Halter just referred you back to the article at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/standalone-with-authentication-library?view=aspnetcore-8.0&tabs=visual-studio

... and I haven't received any other issues about tokens not being attached to outgoing requests. Did you ever get it resolved? I'm wondering if I should take time to work through a test case given that your report is the only one in several years of this article's publication reporting a problem. If you're no longer experiencing a problem or ended up adopting a different app type (BWA, for example), then I think I'll close this and keep an πŸ‘‚ open for additional feedback. In spite of having worked through a lot of issues, I still have many more to address. I'd prefer not to perform testing unless you're sure that you followed the article and don't have some other client-server webAPI configuration/interaction problem.

guardrex commented 2 months ago

I haven't heard back, so I'm going to close this. I don't have anything actionable at the moment on it, and I still have quite a bit of work to do before the holidays hit πŸ¦ƒ. I'll be πŸ‘‚ as usual for further feedback.