You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC中Discord OAuth2配置异常求助:授权后未跳转至指定回调Action

问题分析与解决方案

看起来你遇到的核心问题是OAuth认证中间件已经接管了回调路径的处理逻辑,导致你自定义的DiscordSignIn Action根本不会被触发,最终按照默认配置重定向到了Index页面。下面详细拆解原因和解决办法:


为什么自定义回调Action没被触发?

AspNet.Security.OAuth.Providers提供的AddDiscord中间件,会自动拦截你配置的CallbackPath(也就是/signin-discord)请求。当Discord返回授权码后,中间件会先完成以下流程:

  1. 用授权码交换Access Token
  2. 调用Discord的用户信息接口获取用户数据
  3. 生成认证票据(Authentication Ticket)
  4. 根据你在Challenge时设置的RedirectUri完成重定向

整个过程完全由中间件在MVC路由之前处理,所以你写的[Route("signin-discord")] Action永远不会被执行。


为什么会重定向到Index?

看你的Index POST方法里的代码:

var challengeResult = Challenge(new AuthenticationProperties { RedirectUri = "/" }, provider);

这里明确设置了认证成功后的重定向地址为根路径/,而根路径对应的就是你的Index GET Action,所以中间件处理完认证后自然会跳转到这里。


正确的处理方式

你不需要自己写回调Action,而是利用中间件提供的扩展点来处理认证后的逻辑,或者调整重定向目标来获取用户信息。

方案1:利用OnCreatingTicket事件处理认证逻辑

在AddDiscord配置中添加OnCreatingTicket事件,这是处理用户信息、添加自定义Claims或保存用户数据的最佳时机:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie()
    .AddDiscord(o => {
        o.ClientId = DiscordDefaults.ClientId;
        o.ClientSecret = DiscordDefaults.ClientSecret;
        o.CallbackPath = new PathString("/signin-discord");
        o.Scope.Add("identify");
        o.Scope.Add("email"); // 注意:需要在Discord机器人设置中开启email权限
        
        o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id", ClaimValueTypes.UInteger64);
        o.ClaimActions.MapJsonKey(ClaimTypes.Name, "username", ClaimValueTypes.String);
        o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email", ClaimValueTypes.Email);
        
        // 认证成功后触发的事件,在这里处理自定义逻辑
        o.Events.OnCreatingTicket = async context => {
            // 获取Discord返回的原始用户数据
            var userId = context.User.GetProperty("id").GetString();
            var username = context.User.GetProperty("username").GetString();
            var avatarHash = context.User.GetProperty("avatar").GetString();
            
            Debug.WriteLine($"已认证用户:{username}(ID:{userId})");
            
            // 示例:添加自定义Claim
            context.Identity.AddClaim(new Claim("DiscordAvatar", avatarHash));
            
            // 示例:将用户信息保存到数据库
            // await _userRepository.CreateOrUpdateUser(userId, username, ...);
            
            await Task.CompletedTask;
        };
    });

方案2:调整重定向目标,在目标页面获取用户信息

修改Challenge时的RedirectUri,指向专门的成功页面,然后在该页面的Action中获取当前认证用户的信息:

  1. 修改POST Index方法的重定向地址:
var challengeResult = Challenge(new AuthenticationProperties { RedirectUri = "/login-success" }, provider);
  1. 添加LoginSuccess Action:
public IActionResult LoginSuccess()
{
    // 获取当前已认证的用户信息
    var currentUser = HttpContext.User;
    if (!currentUser.Identity.IsAuthenticated)
    {
        return RedirectToAction(nameof(Index));
    }
    
    var userId = currentUser.FindFirstValue(ClaimTypes.NameIdentifier);
    var username = currentUser.FindFirstValue(ClaimTypes.Name);
    var email = currentUser.FindFirstValue(ClaimTypes.Email);
    var avatar = currentUser.FindFirstValue("DiscordAvatar"); // 对应方案1中添加的自定义Claim
    
    Debug.WriteLine($"用户ID:{userId},用户名:{username},邮箱:{email}");
    
    return View();
}

额外注意事项

  • 确保Discord机器人OAuth2设置中的回调URL和你配置的CallbackPath完全一致(例如https://your-domain.com/signin-discord)
  • 如果需要获取用户邮箱,必须在Discord开发者后台开启email权限,并且在Scope中添加email
  • 移除你自定义的DiscordSignIn Action,避免路由冲突

内容的提问来源于stack exchange,提问作者Patrick Schulz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:29:07