I have two projects:
Notes.Server
- ASP.NET Core project,
Notes.Client
- Blazor WASM project
My Note App contain Client.cshtml
page which have:
<component type="typeof(PrettyNotes.Web.Client.App)" render-mode="WebAssemblyPrerendered"/>
It's preprenderes Blazor WASM. I implementing oidc authentification in this prerendered project.
Notes.Server's Startup.cs
file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PrettyNotes.Web.Server.Models;
using PrettyNotes.Web.Server.Models.Data;
namespace Notes.Web.Server
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddRazorPages().AddRazorRuntimeCompilation();
services.AddDbContext<PrettyNotesApplicationDBContext>(options =>
{
options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=ProjectDB;Trusted_Connection=True;");
});
services.AddIdentity<PNUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = true;
}).AddEntityFrameworkStores<PrettyNotesApplicationDBContext>();
services.AddAuthentication().AddIdentityServerJwt();
services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme,
opt =>
{
opt.LoginPath = "/auth/login";
opt.LogoutPath = "/auth/logout";
});
services.AddIdentityServer()
.AddInMemoryApiResources(new ApiResource[] { new ApiResource("API", "ServerAPI") }).AddInMemoryClients(
new[]
{
new IdentityServer4.Models.Client
{
ClientId = "PrettyNotesClient",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
AllowedCorsOrigins = { "https://localhost:5001" },
AllowedScopes = { "openid", "profile", "email" },
RedirectUris = { "https://localhost:5001/client/security/auth/login-callback" },
PostLogoutRedirectUris = { "http://localhost:5001/client" },
Enabled = true
}
})
.AddInMemoryIdentityResources(
new IdentityResource[]
{
new IdentityResources.Address(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.OpenId()
}).AddInMemoryApiScopes(new[] { new ApiScope("API") }).AddAspNetIdentity<PNUser>()
.AddDeveloperSigningCredential();
services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>().AddScoped<SignOutSessionStateManager>();
services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseStaticFiles();
app.UseBlazorFrameworkFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseIdentityServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapFallbackToController("/client/{**segment}", "Index", "Client");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
My Blazor WASM Project is prerendered in server. When I trying to reach Blazor WASM Project page that prerenders Blazor, I get next error:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidCastException: Unable to cast object of type 'Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider' to type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IRemoteAuthenticationService`1[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationState]'.
How to resolve this problem? Can you suggest some resources, repos about Authentification in Prerendered Blazor Webassembly?
The documentation here should help already a lot: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-6.0#support-prerendering-with-authentication
although they seem to ignore the fact that the callback-login url stays stuck on "loading" as you need to disable the div override for prerendering, still figuring that on out