2016-08-03 115 views
11

我偶然发现应用程序将用户重定向到Account/AccessDenied/时出现的问题不一致,因为向当前登录的用户添加社交媒体验证。它似乎在用户第一次登录时工作,然后尝试添加另一种验证方法,它将用户返回到Account/AccessDenied?ReturnUrl=%2Fmanage%2Flinklogincallback应用程序重定向到帐户/ AccessDenied添加Oauth

我的猜测是[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

+0

此错误是否一致? 因为当我的代码仍然抛出错误异常时,我得到了很多错误。清除cookie可以暂时解决问题。后来当我修复我的小错误时,这个redirectd不再发生。 –

+0

它一贯发生,但我不知道它是什么,因为一切都按预期工作。你为了使它工作而修复了哪些微不足道的错误? – Rovdjuret

+0

您是否在'Startup'类的'Configure()'方法中添加了'app.UseGoogleAuthentication(...)'? –

回答

3

通过ASPNET团队安全工作回购,这是一个bug(见本issue)和解决,直到下一个版本我已​​经得到了证实。 暂时的解决办法是设置一个名为

Identity.External

为空饼干,这是在添加外部登录到您的帐户创建。

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

你可以发布链接到github问题吗? –

+0

带链接更新了答案,@GerardoGrignoli – Rovdjuret

+0

我也遇到过这个问题,但升级到1.1.0后,即使没有解决方法,也能正常工作 – Liero

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 }); 
    } 
} 

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

5

我也面临同样的问题。我用的是从IdentityServer4快速入门示例代码从here

 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" 
     }); 

而不是仅仅使用常量“外部”从IdentityServerConstants.ExternalAUthenticationScheme我必须获得用于从由应用使用的当前标识系统的cookie的选项标识外部身份验证Cookie的方案。这是为我解决了这个问题。

+0

感谢您的信息,很高兴知道我现在正在实施IDS4 :) – Rovdjuret

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)); 

    } 
2

如果你在Startup.cs设置config.SignIn.RequireConfirmedEmail = trueEmailConfirmedfalse用于外部认证的用户(例如Facebook登录),以后登录,您将被引导至Account/AccessDenied/操作方法。

+0

我将'EmailConfirmed'设置为'true',因为它对外部登录是有意义的,并且它没有帮助 – Sergey

相关问题