Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor WebAssembly 401 Unauthorized even when I am authorized

I am using Blazor WebAssembly Asp.Net Core hosted PWAand integrated the AspNetCore.Identity into it. I created the AuthenticationStateProvider in the Client-Side and now I want to allow the user access to a controller where he needs to be authorized.

I have tested via postman, the users were been created and stored in DB as aspnetusers with the right credentials. The Login/Account Controller work as I wanted it.

When the user is authorized it tells this exception in the browser when accessing the authorized controller request:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized). System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).

Startup.cs (ConfigureServices-Method):

...
    serviceCollection.AddDbContext<SQLiteTestDbContext>(options =>
                {
                    options.UseSqlite(config["ConnectionStrings:SQLiteTestConnection"]);
                });
                serviceCollection.AddDefaultIdentity<IdentityUser>()
                    .AddEntityFrameworkStores<SQLiteTestDbContext>()
                    .AddDefaultTokenProviders();

    services.AddAuthentication(x =>
                    {
                        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    })
                    .AddJwtBearer(options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = Configuration["JwtIssuer"],
                            ValidAudience = Configuration["JwtAudience"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
                        };
                    });

    services.AddHttpContextAccessor();
                services.Configure<IdentityOptions>(options =>
                    options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);
...

 

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      
    ...
        app.UseAuthentication();
        app.UseAuthorization();
    ...
    }

Program.cs Client-Side


    public static async Task Main(string[] args)
            {
                var builder = WebAssemblyHostBuilder.CreateDefault(args);
                builder.RootComponents.Add<App>("app");
                builder.Logging.SetMinimumLevel(LogLevel.Warning);
    
                //Registering Shared-Library models
                builder.Services.AddScoped<ObjectModel>();

                builder.Services.AddBlazoredLocalStorage();
                builder.Services.AddAuthorizationCore();
                builder.Services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();
                builder.Services.AddScoped<IAuthService, AuthService>();
    
                //Registered BlazorContextMenu Service
                builder.Services.AddBlazorContextMenu();
    
                //Registering FileReader service, for image upload -> Azure
                builder.Services.AddFileReaderService(options => options.UseWasmSharedBuffer = true);
                builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    
                await builder.Build().RunAsync();
            }

My Controller with authorize attribute:


    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        [Route("api/[controller]")]
        [ApiController]
        public class ObjectController : ControllerBase
        {
....
    
like image 404
brstkr Avatar asked Oct 21 '25 03:10

brstkr


1 Answers

Note:

  1. When your user tries to access a protected (annotated with the Authorize attribute) page on the client he should login first or register.

  2. In order to register, he should be redirected to an Account Controller where you should create a new user, and add it to the database (You said you " integrated the AspNetCore.Identity into it"), which is fine...and should be used to authenticate and verify the user's identity. You account controller should also produce a Jwt Token that should be passed to the client app, and stored in the local storage.

  3. Now, whenever your user tries to access protected resources on your Web Api endpoints, you should retrieve the Jwt Token from the local storage, and add it to the request header. If you do so, the Unauthorized response would be something of the past.

  4. Custom AuthenticationStateProvider can be a good place from which you can manage storing the Jwt Token in the local storage and retrieving it for outbound HTTP request calls.

Here's some sample code to clarify what you should do:

@code {
    WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        var token = await TokenProvider.GetTokenAsync();
        forecasts = await Http.GetJsonAsync<WeatherForecast[]>(
            "api/WeatherForecast",
            new AuthenticationHeaderValue("Bearer", token));
    }
}

Note: TokenProvider is a custom AuthenticationStateProvider that defines a method called GetTokenAsync that provides (reading the Jwt Token from the local storage and passing it to the calling code) the Jwt Token

Hope this helps...

like image 195
enet Avatar answered Oct 23 '25 20:10

enet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!