Aspnetcore: Blazor Webassembly Preview 5 throw AccessTokenNotAvailableException for [AllowAnonymous]

Created on 25 Apr 2020  路  12Comments  路  Source: dotnet/aspnetcore

I updated an existing Preview 4 project.
I added:
builder.Services.AddHttpClient("BlazorApp5.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to the server project builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("BlazorApp5.ServerAPI"));

And i removed
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

The Fetch Data example is now running with
try { forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); } catch (AccessTokenNotAvailableException exception) { exception.Redirect(); }

But the razor Components that not have [Authorize] and the Controller methods without [Authorize] run now in an AccessTokenNotAvailableException.

area-blazor blazor-wasm

Most helpful comment

Using a separate client for talking to public endpoints is still the right choice, and what we consider best practice. Using a typed client is an option here as Chriss suggests. I would say that if you go that route, you might as well just define methods to get the results you want within that class instead of just grabbing the client.

We'll add this guidance to the docs.

All 12 comments

I also have this problem. To try allow unprotected pages/api access.

@javiercn Any update on how to allow access to anonymous endpoints?

@mihaimyh I found the best way to achieve this currently is to inject a named instance of httpclient via IHttpClientFactory onto the page to create a new token free instance.
Here's my code:

Client program.cs

            builder.Services.AddHttpClient("CustomClient", client =>
            client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

Razor page:

@inject IHttpClientFactory Client
...
await Client.CreateClient("CustomClient").PostAsJsonAsync

Let me know if you need further assistance on this one.

@mihaimyh I found the best way to achieve this currently is to inject a named instance of httpclient via IHttpClientFactory onto the page to create a new token free instance.
Here's my code:

Client program.cs

            builder.Services.AddHttpClient("CustomClient", client =>
            client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

Razor page:

@inject IHttpClientFactory Client
...
await Client.CreateClient("CustomClient").PostAsJsonAsync

Let me know if you need further assistance on this one.

I am already doing this but currently the app is trying to authenticate the user on the first load of the page.
Is there a way to allow anonymous access?

Just make sure it doesn't have an @attribute and it should be fine I would've thought.
My pages don't ask for auth unless I put [Authorize] on the page or controller.

I did achieve this similar:
I created a class AuthHttpClient:

public class AuthHttpClient : HttpClient
{
}

And in Program.cs:

        builder.Services.AddHttpClient<AuthHttpClient>(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

           builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
        builder.Services.AddApiAuthorization();

I don't know if that is the best practices and the best way to have 2 clients, one with BaseAddressAuthorizationMessageHandler and one without.

@javiercn Any guidance on this issue, please?

I did achieve this similar:
I created a class AuthHttpClient:

public class AuthHttpClient : HttpClient
{
}

And in Program.cs:

        builder.Services.AddHttpClient<AuthHttpClient>(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

           builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
        builder.Services.AddApiAuthorization();

I don't know if that is the best practices and the best way to have 2 clients, one with BaseAddressAuthorizationMessageHandler and one without.

Following this worked for me on the final release which caused me the same issue. But same question: Is this the best practice? Some final answer to this?

@mihaimyh I found the best way to achieve this currently is to inject a named instance of httpclient via IHttpClientFactory onto the page to create a new token free instance.
Here's my code:

Client program.cs

            builder.Services.AddHttpClient("CustomClient", client =>
            client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

Razor page:

@inject IHttpClientFactory Client
...
await Client.CreateClient("CustomClient").PostAsJsonAsync

Let me know if you need further assistance on this one.

This worked for me

But still same question: Is this the best practice?

Using a separate client for talking to public endpoints is still the right choice, and what we consider best practice. Using a typed client is an option here as Chriss suggests. I would say that if you go that route, you might as well just define methods to get the results you want within that class instead of just grabbing the client.

We'll add this guidance to the docs.

Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!

Was this page helpful?
0 / 5 - 0 ratings