Google的间歇性ASP.NET oAuth问题,AuthenticationManager.GetExternalIdentityAsync返回null

我正在尝试使用Google作为外部登录提供程序来解决间歇性问题。

尝试登录时,会将用户重定向回登录页面,而不是进行身份validation。

问题出现在这一行(下面的链接第55行),GetExternalIdentityAsync返回null。

var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); 

完整的代码是:

 [Authorize] public abstract class GoogleAccountController : Controller where TUser : Microsoft.AspNet.Identity.IUser { public IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } } public abstract UserManager UserManager { get; set; } [AllowAnonymous] [HttpGet] [Route("login")] public ActionResult Login(string returnUrl) { ViewData.Model = new LoginModel() { Message = TempData["message"] as string, Providers = HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes(), ReturnUrl = returnUrl }; return View(); } [AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] [Route("login")] public ActionResult Login(string provider, string returnUrl) { return new ChallengeResult(provider, Url.Action("Callback", "Account", new { ReturnUrl = returnUrl })); } [AllowAnonymous] [Route("authenticate")] public async Task Callback(string returnUrl) { var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); if (externalIdentity == null) { return RedirectToAction("Login", new { ReturnUrl = returnUrl }); } var emailAddress = externalIdentity.FindFirstValue(ClaimTypes.Email); var user = await UserManager.FindByNameAsync(emailAddress); if (user != null) { await SignInAsync(user, false); return RedirectToLocal(returnUrl); } else { TempData.Add("message", string.Format("The account {0} is not approved.", emailAddress)); return RedirectToAction("Login", new { ReturnUrl = returnUrl }); } } [HttpPost] [ValidateAntiForgeryToken] [Route("logout")] public ActionResult Logout(string returnUrl) { AuthenticationManager.SignOut(); return RedirectToLocal(returnUrl); } private async Task SignInAsync(TUser user, bool isPersistent) { AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); var authenticationProperties = new AuthenticationProperties() { IsPersistent = isPersistent }; AuthenticationManager.SignIn(authenticationProperties, identity); } private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } protected override void Dispose(bool disposing) { if (disposing && UserManager != null) { UserManager.Dispose(); UserManager = null; } base.Dispose(disposing); } } 

这也是在这里 。

这是一个非常间歇性的问题,重新部署应用程序通常会让它暂时起作用。

看着Fiddler,我可以看到只是在身份validation方法之前签名google的电话,它无法找到cookie。

Fiddler截图

该应用使用以下代码初始化谷歌登录

 app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/login") }); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); app.UseGoogleAuthentication(); 

我已在web.config中将身份validation模式设置为非,并删除了表单身份validation模块。

          

这些站点托管在Azure上,一些站点运行在一个实例上,一些站点运行。它们具有自定义域,但在自定义域和azurewebsites域以及http / https上仍然失败。

任何人都可以帮助解决为什么会这样吗?

更新

Microsoft.Owin.Security.Google 3.0版于昨晚发布。 要切换,看看这是否解决了这个问题。

https://www.nuget.org/packages/Microsoft.Owin.Security.Google

我忘了在google开发者控制台中启用“Google + API”。 Google登录似乎没问题,但GetExternalLoginInfoAsync返回null。

您可以点击此链接https://stackoverflow.com/a/27631109/657926

Tom我使用REST API在我的asp.net应用程序中使用google-oauth。 它工作正常,我没有遇到任何连接问题。

我正在执行以下步骤:

1.我在谷歌开发者控制台中创建了一个项目,我创建了“Web应用程序的客户端ID”设置,其中包含以下参数。

a)客户ID =>它将由谷歌自动生成b)电子邮件地址=>它将由谷歌自动生成c)客户端密码=>它将由谷歌自动生成d)重定向URI =>需要指定url将用于处理身份validation过程的网页。 在此页面中,我们可以进行身份​​validation,我们可以获取用户的基本信息。

 my url: "http://localhost:1822/WebForm1.aspx/code" 

我的用法:

  1. 我创建了一个示例项目,其中包含“Webpage1.aspx”和“Webpage2.aspx”。

我已经设置了“Webpage2.aspx”启动页面,我正在“Webpage2.aspx”中形成开放的auth url并重定向到google登录页面。

Google Open Auth url Formation

登录后,它将重定向到“Webpage1.aspx”以及访问代码。 通过将此访问代码传递给“ https://accounts.google.com/o/oauth2/token ”url,我将获得访问令牌以及令牌类型和令牌到期时间。 之后通过将此访问权限传递给“ https://www.googleapis.com/oauth2/v2/userinfo ”url,我将获得用户基本信息,如“电子邮件,姓名,性别,照片等…”

示例代码

  public class GoogleAuthorizationData { public string access_token { get; set; } public int expires_in { get; set; } public string token_type { get; set; } } public class GoogleUserInfo { public string name { get; set; } public string family_name { get; set; } public string gender { get; set; } public string email { get; set; } public string given_name { get; set; } public string picture { get; set; } public string link { get; set; } public string id { get; set; } } Webpage1.aspx ============ protected void Page_Load(object sender, EventArgs e) { string code = Request.QueryString["code"].ToString(); string scope = Request.QueryString["scope"].ToString(); string url = "https://accounts.google.com/o/oauth2/token"; string postString = "code=" + code + "&client_id=" + ConfigurationManager.AppSettings["GoogleClientID"].ToString() + "&client_secret=" + ConfigurationManager.AppSettings["GoogleSecretKey"].ToString() + "&redirect_uri=" + ConfigurationManager.AppSettings["ResponseUrl"].ToString() + "&grant_type=authorization_code"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString()); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; UTF8Encoding utfenc = new UTF8Encoding(); byte[] bytes = utfenc.GetBytes(postString); Stream os = null; try { request.ContentLength = bytes.Length; os = request.GetRequestStream(); os.Write(bytes, 0, bytes.Length); } catch { } try { HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); StreamReader responseStreamReader = new StreamReader(responseStream); var result = responseStreamReader.ReadToEnd();// var json = new JavaScriptSerializer(); GoogleAuthorizationData authData = json.Deserialize(result); HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v2/userinfo"); request1.Method = "GET"; request1.ContentLength = 0; request1.Headers.Add("Authorization", string.Format("{0} {1}", authData.token_type, authData.access_token)); HttpWebResponse webResponse1 = (HttpWebResponse)request1.GetResponse(); Stream responseStream1 = webResponse1.GetResponseStream(); StreamReader responseStreamReader1 = new StreamReader(responseStream1); GoogleUserInfo userinfo = json.Deserialize(responseStreamReader1.ReadToEnd()); Response.Write(userinfo.email); } catch (Exception eX) { throw eX; } } 

我相信你不应该使用app.UseGoogleAuthentication(); 因为这是一个试图使用OpenID 2.0的调用,它已被弃用 。
您应该使用的是OAuth 2.0 for Login(OpenID Connect) 。
所以:

  1. 在Google Developers Console中注册您的应用
  2. 允许它访问Google+ API(即使您不打算直接使用Google+ – 它现在用作身份validation的平均值)
  3. 以这种方式启用ASP.NET Identity的Google身份validation
 app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = "YOUR_CLIENT_ID", ClientSecret = "YOUR_CLIENT_SECRET", }); 

我也有同样的问题。 我使用的是Visual Studio 2013,网站是在Azure上。 社交日志一直在工作,没有问题停止工作,LinkLoginCallback在loginInfo中收到null。 我重新发布项目没有代码更改或重建,然后loginInfo收到正确的数据,一切正常。 没有意义,但你去了。

我昨天遇到了这个问题,而且我完全没问题! 而且,正如你所描述的那样,我毫无理由地得到了它。

我设法修复它(经过几个小时的比较2个项目 – 一个测试项目每次都没有问题,另一个是一个更严重的项目 – 他们有完全相同的代码,但不同的DLL版本)

问题出在DLL上 – 来自Nuget的引用包。 确保您拥有最新的软件包,并检查web.config中运行时部分。

在我更新了所有与Owin相关的软件包和Microsoft.Owin并添加了:

                   

……它再次奏效! 它们可能会根据您使用的包装而有所不同,但这就是它对我有用的方式。

Microsoft的Owin System.Web实现中存在一个错误。 在IIS上运行Owin应用程序时使用的那个。 如果我们在ASP.NET MVC5中使用基于Owin的新身份validation处理,那么我们99%的人可能会这样做。

这个bug让Owin设置的cookie在某些场合神秘地消失了。

app.UseGoogleAuthentication(...)之前将这个nuget放在https://github.com/KentorIT/owin-cookie-saver之前

确保已启用第三方Cookie。 我发现如果你在尝试用你的应用程序“注册”用户时没有登录谷歌,它会重定向到登录页面,因为它会查找不存在的cookie,但仍然设法做什么它需要外部提供商。 下次你尝试“注册”时,因为它已完成部分过程,所以不再需要查找外部cookie,因此第二次成功。