应用在添加 Oauth 时重定向到 Account/AccessDenied

App redirects to Account/AccessDenied on adding Oauth

我偶然发现了一个问题,即在向当前登录用户添加社交媒体身份验证后,应用程序不一致地将用户重定向到 Account/AccessDenied/。它似乎在用户第一次登录时工作,然后通过尝试添加另一种身份验证方法 returns 用户 Account/AccessDenied?ReturnUrl=%2Fmanage%2Flinklogincallback.

我的猜测是 [Authorize] 属性出了问题,但这只是我第二次尝试添加外部身份验证方法。

管理控制器

[Authorize]
public class ManageController : Controller
{
    //
    // POST: /Manage/LinkLogin
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult LinkLogin(string provider)
    {
        // Request a redirect to the external login provider to link a login for the current user
        var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
        var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
        return Challenge(properties, provider);
    }

    //
    // GET: /Manage/LinkLoginCallback
    [HttpGet]
    public async Task<ActionResult> LinkLoginCallback()
    {
        var user = await GetCurrentUserAsync();
        if (user == null)
        {
            return View("Error");
        }
        var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
        if (info == null)
        {
            return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error });
        }
        var result = await _userManager.AddLoginAsync(user, info);
        var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error;
        return RedirectToAction(nameof(ManageLogins), new { Message = message });
    }
}

难道是startup.cs的排列顺序?

这是request/response

我已经得到从事安全存储库工作的 aspnet 团队的确认,这是一个错误(请参阅此 issue)并在下一个版本之前解决。 一个临时的解决方法是设置一个名为

的 cookie

Identity.External

为 null,这是在向您的帐户添加外部登录时创建的。

if (Request.Cookies["Identity.External"] != null)
{
     Response.Cookies.Delete("Identity.External"); 
}

@Rovdjuret 的解决方法帮助了我,直到它被 asp.net 团队解决。这是我的控制器登录操作:

public IActionResult Login(string returnUrl = null)
{
    if (_signInManager.IsSignedIn(User))
    {
        // redirect to user profile page
        return RedirectToAction(nameof(HomeFileController.Index), "HomeFile");                
    }
    else
    {
        // clear Identity.External cookie
        if (Request.Cookies["Identity.External"] != null)
        {
            Response.Cookies.Delete("Identity.External");
        }
        return View(new LoginViewModel{ ReturnUrl = returnUrl, RememberMe = true });
    }
}

更新:在最新版本(截至 2017 年 5 月)中,cookie 具有前缀“.AspNetCore.”。所以cookie名称应该是“.AspNetCore.Identity.External

我也遇到了同样的问题。我使用的是来自 here

的 IdentityServer4 QuickStart 示例中的代码
        app.UseGoogleAuthentication(new GoogleOptions
        {
            AuthenticationScheme = "Google",
            DisplayName = "Google",
            SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,

            ClientId = "xxx.apps.googleusercontent.com",
            ClientSecret = "xxxx-Xxxxxxx"
        });

我必须将代码更改为以下内容才能解决问题。

        var CookieScheme= app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value.Cookies.ExternalCookieAuthenticationScheme;

        app.UseGoogleAuthentication(new GoogleOptions
        {
            AuthenticationScheme = "Google",
            DisplayName = "Google",
            SignInScheme = CookieScheme,

            ClientId = "xxx.apps.googleusercontent.com",
            ClientSecret = "xxxx-Xxxxxxx"
        });

我不得不从应用程序使用的当前身份系统的 cookie 选项中获取用于识别外部身份验证 cookie 的方案,而不是仅使用 IdentityServerConstants.ExternalAUthenticationScheme 中的常量 'external'。这就是为我解决问题的原因。

解决方法帮助了我,直到 asp.net 团队

解决了它
    // GET: /Account/AccessDenied
    [HttpGet]
    [AllowAnonymous]
    public IActionResult AccessDenied(string returnUrl = null)
    {
        // workaround
        if (Request.Cookies["Identity.External"] != null)
        {
            return RedirectToAction(nameof(ExternalLoginCallback), returnUrl);
        }
        return RedirectToAction(nameof(Login));

    }

如果您在 Startup.cs 中设置了 config.SignIn.RequireConfirmedEmail = true 并且 EmailConfirmed 字段是 false 对于外部身份验证的用户(例如 Facebook 登录),在后续登录时,您将被引导至 Account/AccessDenied/ 操作方法。