为什么新的fb api 2.4在Identity和oauth 2上的MVC 5上返回null电子邮件?
所有的东西都用来完美的工作,直到fb把它的api升级到2.4 (我在以前的项目中我的版本是2.3 )。
今天当我在fb开发人员上添加一个新的应用程序时,我使用api 2.4。
问题:现在我从fb( loginInfo.email = null
)收到空电子邮件。
当然,我检查用户的电子邮件是在公共状态fbconfiguration文件,
我去了loginInfo
对象,但没有find任何其他的电子邮件地址。
我谷歌,但没有find任何答案。
请任何帮助..我有点失落..
谢谢,
我的原始代码(在2.3 api上工作):
在AccountController.cs中:
// // GET: /Account/ExternalLoginCallback [AllowAnonymous] public async Task<ActionResult> ExternalLoginCallback(string returnUrl) { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); if (loginInfo == null) { return RedirectToAction("Login"); } //A way to get fb details about the log-in user: //var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:first_name"); <--worked only on 2.3 //var firstNameClaim = loginInfo.ExternalIdentity.Claims.First(c => c.Type == "urn:facebook:name"); <--works on 2.4 api // Sign in the user with this external login provider if the user already has a login var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); switch (result) { case SignInStatus.Success: return RedirectToLocal(returnUrl); case SignInStatus.LockedOut: return View("Lockout"); case SignInStatus.RequiresVerification: return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false }); case SignInStatus.Failure: default: // If the user does not have an account, then prompt the user to create an account ViewBag.ReturnUrl = returnUrl; ViewBag.LoginProvider = loginInfo.Login.LoginProvider; return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); //<---DOESN'T WORK. loginInfo.Email IS NULL } }
在Startup.Auth.cs中:
Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions fbOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions() { AppId = System.Configuration.ConfigurationManager.AppSettings.Get("FacebookAppId"), AppSecret = System.Configuration.ConfigurationManager.AppSettings.Get("FacebookAppSecret"), }; fbOptions.Scope.Add("email"); fbOptions.Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider() { OnAuthenticated = (context) => { context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken)); foreach (var claim in context.User) { var claimType = string.Format("urn:facebook:{0}", claim.Key); string claimValue = claim.Value.ToString(); if (!context.Identity.HasClaim(claimType, claimValue)) context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook")); } return System.Threading.Tasks.Task.FromResult(0); } }; fbOptions.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie; app.UseFacebookAuthentication(fbOptions);
采取从武士刀线我devise了以下内容:
将FacebookAuthenticationOptions
更改为包含BackchannelHttpHandler
和UserInformationEndpoint
,如下所示。 确保包含您想要的和实施所需的字段的名称。
var facebookOptions = new FacebookAuthenticationOptions() { AppId = "*", AppSecret = "*", BackchannelHttpHandler = new FacebookBackChannelHandler(), UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name" }
然后创build一个自定义FacebookBackChannelHandler
,将拦截到Facebook的请求,并根据需要修复格式不正确的url。
更新: FacebookBackChannelHandler
基于FB api 2017年3月27日更新进行更新。
public class FacebookBackChannelHandler : HttpClientHandler { protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { if (!request.RequestUri.AbsolutePath.Contains("/oauth")) { request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.Replace("?access_token", "&access_token")); } var result = await base.SendAsync(request, cancellationToken); if (!request.RequestUri.AbsolutePath.Contains("/oauth")) { return result; } var content = await result.Content.ReadAsStringAsync(); var facebookOauthResponse = JsonConvert.DeserializeObject<FacebookOauthResponse>(content); var outgoingQueryString = HttpUtility.ParseQueryString(string.Empty); outgoingQueryString.Add("access_token", facebookOauthResponse.access_token); outgoingQueryString.Add("expires_in", facebookOauthResponse.expires_in + string.Empty); outgoingQueryString.Add("token_type", facebookOauthResponse.token_type); var postdata = outgoingQueryString.ToString(); var modifiedResult = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(postdata) }; return modifiedResult; } } public class FacebookOauthResponse { public string access_token { get; set; } public string token_type { get; set; } public int expires_in { get; set; } }
一个有用的补充是检查库的版本3.0.1,并且如果和当它改变时抛出一个exception。 这样你会知道是否有人升级或更新NuGet软件包后,解决这个问题已被释放。
(已更新为构build,使用C#5而不使用新function)
要解决这个问题,你需要从NuGet包安装Facebook SDK。
在启动文件
app.UseFacebookAuthentication(new FacebookAuthenticationOptions { AppId = "XXXXXXXXXX", AppSecret = "XXXXXXXXXX", Scope = { "email" }, Provider = new FacebookAuthenticationProvider { OnAuthenticated = context => { context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken)); return Task.FromResult(true); } } });
在控制器或助手
var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie); var accessToken = identity.FindFirstValue("FacebookAccessToken"); var fb = new FacebookClient(accessToken); dynamic myInfo = fb.Get("/me?fields=email,first_name,last_name,gender"); // specify the email field
有了这个,你可以得到EmailId,名字,性别。
您还可以在查询string中添加其他必需的属性。
希望这会帮助别人。
对于我来说,这个问题是通过升级到Microsoft.Owin.Security.Facebook 3.1.0
并向Fields
集合添加“email”来解决的:
var options = new FacebookAuthenticationOptions { AppId = "-------", AppSecret = "------", }; options.Scope.Add("public_profile"); options.Scope.Add("email"); //add this for facebook to actually return the email and name options.Fields.Add("email"); options.Fields.Add("name"); app.UseFacebookAuthentication(options);
只是想在Mike的回答中加上这一行
facebookOptions.Scope.Add("email");
仍然需要添加之后
var facebookOptions = new FacebookAuthenticationOptions() { AppId = "*", AppSecret = "*", BackchannelHttpHandler = new FacebookBackChannelHandler(), UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=id,name,email,first_name,last_name,location" }
如果你已经注册你的Facebook帐户到您的开发网站没有“电子邮件许可”。 更改代码并再次尝试后,您仍然不会收到电子邮件,因为电子邮件许可权未授予您的开发者网站。 我的方式是去https://www.facebook.com/settings?tab=applications ,删除我的Facebook应用程序,并重新进行过程。
- 将Microsoft.Owin升级到3.0.1(Install-Package Microsoft.Owin.Security.OAuth)
- 在Startup.Auth.cs中添加facebookOptions.UserInformationEndpoint =“ https://graph.facebook.com/v2.4/me?fields=id,name,email ”;
阅读更新日志 ,这是devise。 您需要明确地请求您在响应中重新调用的字段和边缘:
声明性字段为了尝试提高移动networking的性能,v2.4中的节点和边缘要求您显式地请求您的
GET
请求所需的字段。 例如,GET /v2.4/me/feed
默认不再包含喜欢和评论,但GET /v2.4/me/feed?fields=comments,likes
将返回数据。 有关更多详细信息,请参阅有关如何请求特定字段的文档 。