I have been playing with blazor with .net 5.0. I am stuck with a simple but annoying issue: I am trying to load data from API but every call to the Server blazor expects the user to be signed in.
I understood if we took out [Authorize] tag from the API controller and don't have @attribute [Authorize]
in the razor page, and that would be it. But I am struggling to understand why my API call still expects AccessToken in protected override async Task OnInitializedAsync()
the error messages don't say much around why.
Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessTokenNotAvailableException: ''
at Microsoft.AspNetCore.Components.WebAssembly.Authentication.AuthorizationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
I haven't touched the App. cs file of the web assembly..
Can anyone help please.
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
<Authorizing>
<h4>Authentication in progress...</h4>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
I figured the solution ... should have looked at it first.
it was actually the App.CS fill in the Client Project. Http endpoint is initiated there, and by default the code-gen adds BaseAddressAuthorizationMessageHandler to the httpclient.
builder.Services.AddHttpClient("private", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
how I solved it was using named clients one for Private and one for Public like so
builder.Services.AddHttpClient("private", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddHttpClient("public", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));
and in pages inject IHttpClientFactory
@inject IHttpClientFactory ClientFactory
and create a named client from the factory.
var client = ClientFactory.CreateClient("public");
This worked.