我在使用 .NET 5.0.2 Blazor WebAssembly 和带有 IdentityServer4 的 OIDC 身份验证时遇到了一个非常令人沮丧的问题。在新标签页中加载页面按预期工作,但是当页面上发生错误或重新加载标签页时,应用程序陷入无限静默登录循环,依次向 /connect/authorize
、{ {1}}、/.well-known/openid-configuration
每秒多次通过隐藏的 iframe。正如问题所暗示的那样,它仅在用户登录时发生。
OIDC 身份验证配置
/connect/token
App.razor
builder.Services.AddOidcAuthentication(options => {
options.ProviderOptions.Authority = "https://localhost:5001/";
options.ProviderOptions.ClientId = "client-id";
options.ProviderOptions.DefaultScopes.Add("openid");
options.ProviderOptions.DefaultScopes.Add("profile");
options.ProviderOptions.DefaultScopes.Add("roles");
options.ProviderOptions.PostLogoutRedirectUri = "/";
options.ProviderOptions.ResponseType = "code";
options.UserOptions.RoleClaim = "role";
});
身份服务器配置
<CascadingAuthenticationState>
<CascadingBlazoredModal>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
<div class="screen-centred auth-spinner">
<Spinner />
</div>
</Authorizing>
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated) {
<RedirectToLogin />
} else {
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingBlazoredModal>
</CascadingAuthenticationState>
Image of the Initiatior Chain from Chrome
我已经检查了所有代码,问题不是由我对 AuthenticationStateProvider 服务的任何使用引起的,所以我认为这是配置错误的结果。我还没有在网上找到有关此问题的任何其他报告,我不确定我是否配置错误会导致此问题。
答案 0 :(得分:0)
在我尝试找出问题的所有客户端代码之后,我意识到当 WASM 客户端独立运行而不是在 ASP.NET 服务器上运行时,问题不会发生。服务器的 Startup.cs 类仍然包含来自个人用户帐户项目模板的代码,这似乎是根本原因。
从 Startup.cs 类中删除注释掉的行后,我无法重现该问题
namespace Server {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services) {
// services.AddDbContext<ApplicationDbContext>(options =>
// options.UseSqlServer(
// Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
// services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
// .AddEntityFrameworkStores<ApplicationDbContext>();
//
// services.AddIdentityServer()
// .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
//
// services.AddAuthentication()
// .AddIdentityServerJwt();
//services.AddServerSideBlazor();
//services.AddBlazoredModal();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
} else {
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
// app.UseIdentityServer();
// app.UseAuthentication();
// app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("/index.html");
});
}
}
}