Minimal APIs in Blazor with RequireAuthorization() using Individual Account

Enrico Rossini 196 Reputation points
2024-12-17T23:58:25.46+00:00

In my .NET8 Blazor project, I added the Individual Account to manage the users. Now, in order to save the data in the database, I added some minimal endpoints like

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();

}

Also, I added the configuration for the HttpClient

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"]);

        });

Then, in the pages, I inject the IHttpClientFactory

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. How can I protect the APIs and use them from the client side?

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,706 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,635 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Ruikai Feng - MSFT 2,586 Reputation points Microsoft Vendor
    2024-12-18T09:42:25.0933333+00:00

    Hi,@Enrico Rossini

    The Authentication Scheme IdentityConstants.ApplicationScheme is based on cookie ,to protect api endpoints, we usually use token based authentication scheme

    Based on the codes in this document:

    //replace the service
    builder.Services.AddIdentityApiEndpoints<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddSignInManager()
    .AddDefaultTokenProviders();
    
    
    //builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    //    .AddEntityFrameworkStores<ApplicationDbContext>()
    //    .AddSignInManager()
    //.AddDefaultTokenProviders()
    //.AddApiEndpoints();
    //builder.Services.AddIdentityApiEndpoints<ApplicationUser>();
    

    replace the route mapping middleware:

    app.MapIdentityApi<ApplicationUser>();
    //app.MapAdditionalIdentityEndpoints();
    

    modify the scheme for api endpoints:

    public static void MapClientEndpoints(this IEndpointRouteBuilder routes)
    {
        var group = routes.MapGroup("/api/Client").WithTags("Client");
        group.MapGet("/", async (HttpContext context) =>
        {
            return Results.Ok("apicontent");
        })
        .RequireAuthorization(p =>
        {
            p.AuthenticationSchemes = new List<string>() { IdentityConstants.BearerScheme };
            p.RequireAuthenticatedUser();
        })
        .WithName("GetAllClients")
        .WithOpenApi();
        
    }
    
    
    

    When you succeed login,acquire an access token and store it somewhere,(you could modify codes in Login Component to avoid sending httprequest):

    var loginItemJson = new StringContent(
    JsonSerializer.Serialize(new
    {
        email = Input.Email,
        password = Input.Password
    }),
    Encoding.UTF8,
    Application.Json); 
    var httpclient = factory.CreateClient("MyClient");
    using var httpResponseMessage =
        await httpclient.PostAsync("/login", loginItemJson);
    var tokenstr = await httpResponseMessage.Content.ReadAsStringAsync();
    var accesstoken = JsonSerializer.Deserialize<tokenModel>(tokenstr)?.accessToken;
    accesstokenContainer.SetToken(accesstoken);
    
    
    

    Append the Authorization Header when you send request to your api endpoints:

    var httpclient = httpclientfactory.CreateClient("MyClient");
    var accesstoken = accesstokenContainer.TryGetToken();
    httpclient.DefaultRequestHeaders.Add(
       "Authorization", "Bearer " + accesstoken);
    var responsemessage = await httpclient.GetAsync("/api/Client");
    var contenet = responsemessage.Content.ReadAsStringAsync();
    
    
    

    Now it succeed :

    User's image

    If you want to use cookie based authentication,you may follow this document


    Best regards,

    Ruikai Feng

    0 comments No comments

  2. Bruce (SqlWork.com) 68,716 Reputation points
    2024-12-18T19:00:42.5833333+00:00

    the individual account provider does not support bearer tokens, only the oauth provider does. the supported solution for individual accounts is to use an custom oauth server like identity server and msal (but identity server is no longer free):

    https://identityserver4.readthedocs.io/en/latest/

    you can google for examples to add jwt token generation to individual accounts. basically you add an endpoint that returns a token, and then add jwt token middleware and a security policy for jwt tokens. here is a simple sample:

    https://medium.com/@bruno-bernardes-tech/how-to-implement-jwt-authentication-in-asp-net-core-269f258f19be

    note: you will want to be sure your code is properly validating tokens. also individual account pages are razor pages. you will probably want to change the login page to blazor page that gets your custom token. you will also need to create a custom authentication state provider that uses your custom token.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.