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

时间:2016-08-03 18:58:44

标签: c# asp.net-mvc asp.net-core .net-core

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

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

ManageController

[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如何安排的顺序吗?

这是请求/回复

enter image description here

5 个答案:

答案 0 :(得分:6)

@ 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具有前缀&#34; .AspNetCore。&#34;。所以cookie名称应为&#34; .AspNetCore.Identity.External &#34;

答案 1 :(得分:5)

我也遇到了同样的问题。我使用的是来自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"
        });

而不仅仅是使用常数&#39;外部&#39;从IdentityServerConstants.ExternalAUthenticationScheme我必须获得用于从应用程序使用的当前身份系统的cookie选项中识别外部身份验证cookie的方案。这就是为我解决问题的原因。

答案 2 :(得分:3)

我已经得到了安全回购的aspnet团队的确认,这是一个错误(请参阅此issue)并解决到下一个版本。 临时解决方法是设置名为

的cookie
  

Identity.External

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

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

答案 3 :(得分:3)

解决方法帮助了我,直到它被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));

    }

答案 4 :(得分:2)

如果您在config.SignIn.RequireConfirmedEmail = true中设置Startup.csEmailConfirmed字段为false,则对于外部验证的用户(例如Facebook登录),在后续登录时,您将被定向到Account/AccessDenied/操作方法。