Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Minimal APIs in Blazor with RequireAuthorization() using Individual Account

$
0
0

In my .NET 8 Blazor project, I added the "Individual Account" to manage users. The application has 2 projects.

Server

The server side contains the login part and the controllers/endpoints.

enter image description here

The controllers/endpoints are minimal APIs like this one

public static void MapClientEndpoints (this IEndpointRouteBuilder routes){    var group = routes.MapGroup("/api/Client").WithTags(nameof(Client));    group.MapGet("/", async (HypnoContext db) =>    {        return await db.Client.ToListAsync();    })    .RequireAuthorization()    .WithName("GetAllClients")    .WithOpenApi();}

in order to save in the database. Also, I added the configuration for HttpClient:

builder.Services.AddScoped<AuthenticationStateProvider,     PersistingRevalidatingAuthenticationStateProvider>();builder.Services.AddAuthentication(options =>    {        options.DefaultScheme = IdentityConstants.ApplicationScheme;        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;    })    .AddIdentityCookies();builder.Services.AddIdentityCore<ApplicationUser>(options =>     options.SignIn.RequireConfirmedAccount = true)        .AddRoles<IdentityRole>()        .AddEntityFrameworkStores<ApplicationDbContext>()        .AddSignInManager()        .AddDefaultTokenProviders();builder.Services    .AddScoped(sp => sp        .GetRequiredService<IHttpClientFactory>()        .CreateClient("ServerAPI"))        .AddHttpClient("ServerAPI", (provider, client) =>        {            client.BaseAddress = new Uri(builder. Configuration["FrontendUrl"]);        });

Client

The client project has all the views. The views call the APIs provided by the server.

enter image description here

In the Program.cs this configuration is added out of the box:

builder.Services.AddSingleton<AuthenticationStateProvider,     PersistentAuthenticationStateProvider>();

In order to connect to the APIs from the pages, I created a class to group all the calls in a single place. The constructor is this

string baseEndpoint;IHttpClientFactory ClientFactory;HttpClient? httpClient;public ApiService(string baseUrl, IHttpClientFactory clientFactory){    baseEndpoint = baseUrl;    ClientFactory = clientFactory;    httpClient = ClientFactory.CreateClient("ServerAPI");}

Although I log in to the application as a user, the calls to the APIs work only if no authorisation is required in the Minimal API. It is like that the IHttpClientFactory doesn't have the

How can I protect the APIs and use them from the client side?

What I tried

In the Program.cs of the server, I added this code for the HttpClient:

builder.Services.AddScoped<CustomAuthorizationMessageHandler>();builder.Services.AddHttpClient("ServerAPI", client => {        client.BaseAddress = new Uri(builder.Configuration["FrontendUrl"]);    })   .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();builder.Services.AddTransient(sp =>    sp.GetRequiredService<IHttpClientFactory>().CreateClient("ServerAPI"));

The CustomAuthorizationMessageHandler is as follows

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler{    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,        NavigationManager navigationManager)        : base(provider, navigationManager)    {        ConfigureHandler(           authorizedUrls: new[] { "https://localhost:7241" });    }}

I'm doing this because I want to make calls to the APIs exposed in the server project protected by the Individual Account. So, in a page

@inject HttpClient httpClientHttpRequestMessage request = new HttpRequestMessage(    HttpMethod.Get, "/api/Client");await httpClient.SendAsync(request);

When I run the application, I immediately get an error:

System.AggregateException: 'Some services are not able to beconstructed (Error while validating the service descriptor'ServiceType: MyApp.CustomAuthorizationMessageHandlerLifetime: Scoped ImplementationType:MyApp.CustomAuthorizationMessageHandler': Unable to resolveservice for type'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider'while attempting to activate'MyApp.CustomAuthorizationMessageHandler'.)'

enter image description here

Update

I added the configuration of IHttpClientFactory in the client project too.

builder.Services    .AddScoped(sp => sp        .GetRequiredService<IHttpClientFactory>()        .CreateClient("ServerAPI"))        .AddHttpClient("ServerAPI", (provider, client) =>        {            client.BaseAddress = new Uri(builder.Configuration["FrontendUrl"]);        });

But the result has not changed. When from the UI, there is a call to the API, I always get 200 as an HTTP code but the content of the result is a login page.

enter image description here

Just to give you more info, all the calls are in a different project and I reference this project in the client project.


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>