I am using Blazor web assembly bother server side and web assembly. I am trying to add JWT authentication but it is not working. When I route to InteractiveServer or InteractiveAssembly pages with [Authorize] attribute, I am seeing not found pages in the web browser. If I remove that attribute, everything works fine.
Goal: The goal is to authenticate using JWT. I am using CustomAuthenticationStateProvider which is returning nothing to mimic no user is authenticated. I have no problem with that. I think my configurations to add Authentication and Authorization is missing something.
Here are my Program.cs for both projects:
Server side Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;using Microsoft.AspNetCore.Components.Authorization;using Microsoft.FluentUI.AspNetCore.Components;using Microsoft.IdentityModel.Tokens;using OctuFit.Web.Client.ApiServices;using OctuFit.Web.Client.Services;using OctuFit.Web.Client.Utils;using OctuFit.Web.Components;using Refit;using System.Text;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents();builder.Services.AddFluentUIComponents();builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();builder.Services.AddAuthentication(options =>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{ options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "asdas", ValidAudience = "asdasd", IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("asdasdasd")) };});builder.Services.AddAuthorizationCore();builder.Services.AddCascadingAuthenticationState();builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();builder.Services.AddScoped<IAuthService, AuthService>();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){ app.UseWebAssemblyDebugging();}else{ app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();}app.UseHttpsRedirection();app.UseAntiforgery();app.MapStaticAssets();app.UseAuthentication();app.UseAuthorization();app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(OctuFit.Web.Client._Imports).Assembly);app.Run();Web assembly Program.cs
using Microsoft.AspNetCore.Components.Authorization;using Microsoft.AspNetCore.Components.WebAssembly.Hosting;using Microsoft.FluentUI.AspNetCore.Components;using OctuFit.Web.Client.ApiServices;using OctuFit.Web.Client.Services;using OctuFit.Web.Client.Utils;using Refit;var builder = WebAssemblyHostBuilder.CreateDefault(args);builder.Services.AddFluentUIComponents();builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();builder.Services.AddAuthorizationCore();builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();builder.Services.AddScoped<IAuthService, AuthService>();// Refit Servicesbuilder.Services.AddScoped<RefitInterceptor>();builder.Services.AddRefitClient<IApiAuthService>() .ConfigureHttpClient(c => { c.BaseAddress = new Uri(builder.Configuration["Api:BaseUrl"] ?? throw new ArgumentNullException("Api base url is null.")); }) .AddHttpMessageHandler<RefitInterceptor>();await builder.Build().RunAsync();If I don't specify AddJwtBearer so it says that the "Authentication scheme is not provided".
Question:
- Why we need to specify AddJwtBearer, although we don't need toverify the JWT as I am providing CustomAuthenticationStateProvider.
- Am I adding correct services to the container?
- Am I missing something?
Any help will be highly appreciated. Or any tutorial to see how authentication and authorization actually works.
Thank you
Update 1:So after reading and researching a lot. I came across some intresting things. The Blazor auth pipelines does not working like server.I am defining my own CustomAuthenticationStateProvider so I don't need "AddAuthentication" and "UseAuthentication, UseAuthorization" in the pipeline.So I have removed
builder.Services.AddAuthentication(options =>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{ options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "asdas", ValidAudience = "asdasd", IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("asdasdasd")) };});and
app.UseAuthentication();app.UseAuthorization();The new issue I am facing now is, when I use [Authorize], this exception is happening:
System.InvalidOperationException: Unable to find the required 'IAuthenticationService' service. Please add all the required services by calling 'IServiceCollection.AddAuthentication' in the application startup code.Any help here?