OAuth2授权后重定向陷入循环问题求助
OAuth2授权完成后无法跳转到指定页面,始终重定向回授权流程
问题根源
你在OnCreatingTicket事件中直接调用context.Response.Redirect("/Home/Index")的做法是错误的。这个事件处于OAuth认证流程的中间环节,此时系统还未完成用户登录凭证(Cookie)的签发。直接修改响应重定向会跳过后续的认证收尾逻辑,导致用户没有有效的认证Cookie。当用户被临时重定向到Home/Index后,如果该页面需要认证(或全局有授权策略),系统会检测到用户未登录,触发DefaultChallengeScheme,再次跳转到授权页面,形成循环。
解决方案
方案一:通过回调路径的控制器动作处理重定向(推荐,符合MVC模式)
- 保留
OnCreatingTicket中获取用户信息、保存到数据库的逻辑,移除context.Response.Redirect调用 - 在
AuthController中新增回调动作,完成认证后再执行重定向
修改Program.cs的OAuth配置:
builder.Services .AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = "ExternalProvider"; }) .AddCookie() .AddOAuth("ExternalProvider", options => { // 原有配置... options.CallbackPath = new PathString("/auth/callback"); options.Events.OnCreatingTicket = async context => { // 原有的获取用户信息、保存到数据库的逻辑完全保留 HttpRequestMessage req = new(HttpMethod.Get, context.Options.UserInformationEndpoint); req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken); HttpResponseMessage res = await context.Backchannel.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted); res.EnsureSuccessStatusCode(); var user = JsonDocument.Parse(await res.Content.ReadAsStringAsync()).RootElement; context.RunClaimActions(user); ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>(); int userId = int.Parse(user.GetString("sub")); bool userExists = (await dbContext.Users.FirstOrDefaultAsync(u => u.Id == userId)) is not null; if (!userExists) { string username = user.GetString("preferred_username"); string profilePicture = user.GetString("picture"); dbContext.Users.Add(new ApplicationUser() { Id = userId, Username = username, ProfilePicture = profilePicture }); await dbContext.SaveChangesAsync(); } // 移除这行:context.Response.Redirect("/Home/Index"); }; });
在AuthController中添加回调动作:
using Microsoft.AspNetCore.Mvc; namespace Frontend.Controllers { public class AuthController : Controller { public IActionResult Login() { return Challenge("ExternalProvider"); } // 新增回调动作 public async Task<IActionResult> Callback() { // 此时OAuth认证已完成,系统已为用户签发认证Cookie return RedirectToAction("Index", "Home"); } } }
方案二:使用OnTicketReceived事件指定重定向目标
如果不想新增控制器动作,可以在OAuth事件中配置OnTicketReceived,直接设置认证完成后的跳转路径:
.AddOAuth("ExternalProvider", options => { // 原有配置... options.CallbackPath = new PathString("/auth/callback"); options.Events.OnCreatingTicket = async context => { // 原有的获取用户信息、保存到数据库的逻辑保留 // 移除context.Response.Redirect调用 }; // 新增OnTicketReceived事件配置 options.Events.OnTicketReceived = context => { context.ReturnUri = "/Home/Index"; return Task.CompletedTask; }; })
额外注意事项
- 确保
Home/Index页面如果需要认证(带有[Authorize]属性),用户在认证流程完成后已持有有效的Cookie - 检查全局中间件顺序,确保
app.UseAuthentication()在app.UseAuthorization()之前执行
内容的提问来源于stack exchange,提问作者iKingNinja
相关产品推荐
相关产品推荐

