Duende Server无法生成含令牌的Cookie问题求助
问题描述
我在https://localhost:5001部署了IdentityServer,使用React自定义登录页(测试阶段采用简易HTML文件)。点击登录按钮跳转至携带ReturnUrl的登录页后,通过axios发送的请求能正常到达Login控制器,但返回Ok(context.RedirectUri)后,浏览器仅生成aspnet cookie,未包含access_token、refresh_token、id_token及用户信息。
Login控制器代码
[HttpPost("login")] public async Task<IActionResult> Login(string username, string password, string returnUrl) { // check if we are in the context of an authorization request var context = await _interaction.GetAuthorizationContextAsync(returnUrl); if (context == null) { return Redirect("~/"); } var user = await _userManager.FindByNameAsync(username); if(await _userManager.CheckPasswordAsync(user, password)) { var claims = new List<Claim> { new("Sub", user.Id), new(ClaimTypes.Name, user.Email), new("FullName", user.Name), new(ClaimTypes.Role, "User") }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { AllowRefresh = true, ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(20), IsPersistent = true, IssuedUtc = DateTimeOffset.UtcNow, }; await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); return Ok(context.RedirectUri); } return BadRequest("Something went wrong"); }
HostingExtensions.cs代码
public static WebApplication ConfigureServices(this WebApplicationBuilder builder) { var migrationsAssembly = typeof(Program).Assembly.GetName().Name; var connectionString = builder.Configuration.GetConnectionString("EFConn"); builder.Services.AddControllers(); builder.Services.AddDbContext<DbContext>(opt => { opt.UseNpgsql(connectionString, opt => opt.MigrationsAssembly(migrationsAssembly)); }); builder.Services.AddIdentity<User, IdentityRole>() .AddEntityFrameworkStores<DbContext>() .AddDefaultTokenProviders(); builder.Services.AddIdentityServer(options => { // I had to override the IReturnUrlParser class options.UserInteraction.LoginUrl = "https://localhost:5003/login.html"; options.UserInteraction.ErrorUrl = "http://localhost:5001/error.html"; options.UserInteraction.LogoutUrl = "http://localhost:8082/logout.html"; options.EmitStaticAudienceClaim = true; options.Events.RaiseErrorEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseSuccessEvents = true; }) .AddConfigurationStore(options => { options.ConfigureDbContext = b => b.UseNpgsql(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddOperationalStore(options => { options.ConfigureDbContext = b => b.UseNpgsql(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddAspNetIdentity<User>(); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.ExpireTimeSpan = TimeSpan.FromMinutes(20); options.SlidingExpiration = true; options.AccessDeniedPath = "/Forbidden/"; }); var cors = new DefaultCorsPolicyService(new LoggerFactory().CreateLogger<DefaultCorsPolicyService>()){ AllowAll = true }; builder.Services.AddSingleton<ICorsPolicyService>(cors); builder.Services.AddTransient<IReturnUrlParser, ReturnUrlParser>(); builder.Services.AddCors(options => { // this defines a CORS policy called "default" options.AddPolicy("default", policy => { policy .WithMethods("GET", "POST", "PATCH", "DELETE", "OPTIONS") .AllowAnyHeader() .WithOrigins("https://localhost:5003"); }); }); return builder.Build(); } public static WebApplication ConfigurePipeline(this WebApplication app) { app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } InitializeDatabase(app); app.UseCors("default"); app.UseStaticFiles(); app.UseRouting(); app.UseIdentityServer(); app.MapControllers(); return app; }
解决方案
问题核心:仅完成了用户本地Cookie登录,但未让IdentityServer继续执行授权流程生成令牌;跨域场景下Cookie未正确携带,导致IdentityServer无法识别已认证用户。
修正步骤
前端axios请求开启Cookie携带
在登录请求中配置withCredentials: true,确保跨域请求时携带IdentityServer的认证Cookie:axios.post('https://localhost:5001/login', { username: 'xxx', password: 'xxx', returnUrl: 'xxx' }, { withCredentials: true } )修改登录控制器的返回逻辑
替换return Ok(context.RedirectUri)为直接重定向,让浏览器跳转至IdentityServer授权端点,触发令牌颁发流程:return Redirect(context.RedirectUri);调整Cookie的跨域配置
在AddCookie中设置Cookie的SameSite和Secure属性,适配跨域场景:builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.ExpireTimeSpan = TimeSpan.FromMinutes(20); options.SlidingExpiration = true; options.AccessDeniedPath = "/Forbidden/"; options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.HttpOnly = true; });验证ReturnUrl解析正确性
确保自定义的IReturnUrlParser能正确解析ReturnUrl,保证context.RedirectUri是合法的IdentityServer授权回调地址。
内容的提问来源于stack exchange,提问作者Vil
相关产品推荐
相关产品推荐

