.NET 8 Blazor WebAssembly集成Google登录时出现Correlation failed错误排查
我正在使用.NET 8 Blazor WebAssembly,单独使用Identity认证或Google认证均能正常工作,但将二者集成时出现了Correlation failed错误。
错误日志
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
Microsoft.AspNetCore.Authentication.AuthenticationFailureException: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.AuthenticationFailureException: Correlation failed.
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context).
项目配置代码
using DNAiWeb.Client.Pages; using DNAiWeb.Components; using MudBlazor.Services; using DNAiBase.Services; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Identity; using DNAiWeb.Components.Account; using DNAiBase.Data; using DNAiBase.Models; using Npgsql.EntityFrameworkCore.PostgreSQL; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Google; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; var configuration = builder.Configuration; // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped<IdentityUserAccessor>(); builder.Services.AddScoped<IdentityRedirectManager>(); builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>(); /*builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; //options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme; }).AddCookie() .AddIdentityCookies(); services.AddAuthentication(options => { options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }).AddGoogle(googleOptions =>{ googleOptions.ClientId = ""; // Replace with your Google client ID googleOptions.ClientSecret = ""; // Replace with your Google client secret googleOptions.CallbackPath = "/signin-google"; // Set the redirect URI }).AddCookie() .AddIdentityCookies(); */ services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; // Set Google as default challenge scheme }).AddCookie(IdentityConstants.ApplicationScheme) // Add cookie authentication with IdentityConstants.ApplicationScheme .AddCookie(IdentityConstants.ExternalScheme);// Add cookie authentication with IdentityConstants.ExternalScheme services.AddAuthentication().AddGoogle(googleOptions =>{ googleOptions.ClientId = ""; googleOptions.ClientSecret = ""; googleOptions.CallbackPath = "/signin-google"; }); /*builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; //options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }).AddCookie().AddIdentityCookies(); // Configure services for Google authentication services.AddAuthentication() .AddGoogle(options => { options.ClientId = ""; // Replace with your Google client ID options.ClientSecret = ""; // Replace with your Google client secret options.CallbackPath = "/signin-google"; // Set the redirect URI }); */ var connectionString = builder.Configuration.GetConnectionString("postgresConnection"); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(connectionString, b => b.MigrationsAssembly("DNAiWeb"))); builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>() .AddSignInManager() .AddDefaultTokenProviders(); builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>(); builder.Services.AddMudServices(); builder.Services.AddScoped<UserScopedService>(); builder.Services.AddScoped<DNAiOpenAI>(); 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.UseStaticFiles(); app.UseAntiforgery(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware<BlazorCookieLoginMiddleware>(); app.MapAdditionalIdentityEndpoints(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Counter).Assembly); app.MapGet("/signin-google", () => new GoogleAuthController()); app.Run();
问题原因与修复方案
问题原因
- 重复注册Authentication服务:代码中多次调用
services.AddAuthentication(),导致认证配置被覆盖,第三方登录所需的关联Cookie无法正常生成或读取。 - Scheme配置混乱:默认Scheme、SignInScheme的设置逻辑冲突,Identity外部登录需要依赖
IdentityConstants.ExternalScheme处理临时凭证,当前配置未正确关联。 - 错误的回调路由映射:手动添加的
/signin-google路由覆盖了Google认证中间件的默认回调处理,导致关联验证流程中断。
修复步骤
1. 统一认证服务配置
替换所有认证注册代码为以下内容,确保只初始化一次认证服务:
services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }) .AddIdentityCookies() // 自动配置Identity所需的Cookie Scheme .AddGoogle(googleOptions => { googleOptions.ClientId = ""; // 替换为你的Google Client ID googleOptions.ClientSecret = ""; // 替换为你的Google Client Secret googleOptions.CallbackPath = "/signin-google"; });
AddIdentityCookies()会自动注册IdentityConstants.ApplicationScheme和IdentityConstants.ExternalScheme,无需手动添加AddCookie。- 明确设置
DefaultChallengeScheme为Google,确保触发第三方登录时使用正确的认证流程。
2. 移除错误的路由映射
删除以下代码行,Google认证中间件会自动处理回调请求:
app.MapGet("/signin-google", () => new GoogleAuthController());
3. 验证中间件顺序
确保中间件顺序遵循以下逻辑:
app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); app.UseAuthentication(); // 认证必须在授权之前 app.UseAuthorization(); app.UseMiddleware<BlazorCookieLoginMiddleware>();
4. 检查Google控制台配置
确认Google开发者控制台中授权重定向URI与项目CallbackPath一致,格式为https://<你的域名>/signin-google(开发环境使用https://localhost:<端口>/signin-google)。
5. 强制使用HTTPS
开发环境中必须启用HTTPS,第三方认证服务要求回调地址使用HTTPS,否则关联Cookie无法正确传递。
内容的提问来源于stack exchange,提问作者Priyanka Nataraj356

