问题描述
更新2017!
当我发布原始问题时,我遇到的问题与Facebook最近发生的更改无关他们迫使所有人的API都是2.3版本。要解决该具体问题,请参阅下面的 sammy34的答案。 / oauth / access_token端点的2.3版本现在返回JSON而不是表单编码值
由于历史原因,这是我原来的问题/问题:
我有一个MVC5 Web应用程序,它通过Facebook和Google使用内置的身份验证支持。几个月前我们构建了这个程序,我们遵循这个教程:,一切都很好。
现在,所有的突然间,Facebook身份验证刚刚停止工作。 Google身份验证仍然很好。
问题描述:我们点击使用Facebook连接的链接,我们被重定向到Facebook,如果我们不能允许我们的Facebook应用程序访问我们的个人资料。当我们点击确定时,我们被重定向回到我们的网站,但不是登录,我们只是在登录屏幕上。
我已经经历了在调试模式下进行处理,根据上述教程,我的帐户控制器中有这个ActionResult:
// GET: / Account / ExternalLoginCallback
[AllowAnonymous]
public async任务< ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if(loginInfo == null)
{
return RedirectToAction(Login);
}
............
当通过代码并从Facebook返回时,loginInfo对象始终为NULL,这将导致用户重定向回登录。
为了了解什么实际上是在幕后发生的,我安装了Fiddler并监控HTTP流量。我解决的是,在Facebook权限对话框中点击确定后,Facebook通过以下URL重定向到我们的应用程序:
?HTTPS://本地主机/登入Facebook的代码= LT;访问令牌GT;
此URL不是实际文件,可能由此OWIN框架中内置的某个控制器/处理程序处理猜猜很可能,它使用给定的代码连接回Facebook,以查询有关正在尝试登录的用户的信息。现在,问题是,而不是这样做,我们被重定向到:
/ Account / ExternalLoginCallback?error = access_denied
我确信这是Facebook正在做的,也就是说,而不是给我们的用户数据,使用此错误消息重定向我们。
这将导致 AuthenticationManager.GetExternalLoginInfoAsync();
失败并始终返回NULL。
我完全没有想法。据我们所知,我们没有改变任何事情。
我已经尝试创建一个新的Facebook应用程序,我已经尝试了继续教程,但我总是有同样的问题。
任何想法欢迎!
更新! / p>
好的,这让我疯狂!我现在已经手动执行了执行身份验证所需的步骤,一切都很好,当我这样做。为什么在使用MVC5 Owin的时候这个不起作用?
这就是我所做的:
//步骤1 - 将其粘贴到浏览器中,返回代码
https://www.facebook.com/dialog/oauth?response_type=code&client_id=619359858118523& REDIRECT_URI = HTTPS%3A%2F%2Flocalhost%2Fsignin-Facebook和安培;范围=安培;状态= u9R1m4iRI6Td4yACEgO99ETQw9NAos06bZWilJxJrXRn1rh4KEQhfuEVAq52UPnUif-lEHgayyWrsrdlW6t3ghLD8iFGX5S2iUBHotyTqCCQ9lx2Nl091pHPIw1N0JV23sc4wYfOs2YU5smyw9MGhcEuinvTAEql2QhBowR62FfU6PY4lA6m8pD3odI5MwBYOMor3eMLu2qnpEk0GekbtTVWgQnKnH6t1UcC6KcNXYY
我被重定向回本地主机(我已经在这一点上,以避免关闭被重定向马上离开)。我被重定向到的URL是:
https:// localhost / signin-facebook?code =< code-received-removed-for-apparent-reason>
现在,我抓住了我在下面的URL中使用的代码:
//步骤2 - 在浏览器中打开此URL,并成功检索到访问令牌
https://graph.facebook.com/oauth/access_token?client_id=619359858118523&redirect_uri=https://localhost/signin-facebook&client_secret=<client-secret>&code=<code-从步1 GT;
//步骤3 - 现在我可以使用第2步中的访问令牌查询Facebook图表!
https://graph.facebook.com/me?access_token=<access-token-from-step-2>
没有错误,一切都很好!那么为什么在使用MVC5 Owin的时候呢,这不行呢? OWin实现显然有问题。
确定我有解决问题的方法。 b
$ b
这是我以前在我的Startup.Auth.cs文件中的代码:
var x = new FacebookAuthenticationOptions();
//x.Scope.Add(\"email);
x.AppId =1442725269277224;
x.AppSecret =< secret>;
x.Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
//从FB获取访问令牌并将其存储在数据库中,
//使用FacebookC#SDK获取有关用户的更多信息
context.Identity.AddClaim (新的System.Security.Claims.Claim(FacebookAccessToken,context.AccessToken));
context.Identity.AddClaim(new System.Security.Claims.Claim(urn:facebook:name,context.Name));
context.Identity.AddClaim(new System.Security.Claims.Claim(urn:facebook:email,context.Email));
}
};
x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(x);
注意
x.Scope.Add(email)
行已被注释掉,但是稍后在OnAuthenticated处理程序中我仍然查询电子邮件?嗯,没错。由于某种原因,这可以在几个星期内完美工作。
我的解决方案是简单地取消注释x.Scope.Add(email);行,以确保在Facebook的初始请求中存在scope = email变量。
现在一切都像这样!
我不明白为什么这样工作就像这样。我可以想出的唯一的解释是Facebook改变了一些事情。
Update 2017!
The issue I had when I posted the original question has got nothing to do with the recent changes Facebook made when they forced everyone to version 2.3 of their API. For a solution to that specific problem, see sammy34's answer below. Version 2.3 of the /oauth/access_token endpoint now returns JSON instead of form-encoded values
For historical reasons, here's my original question/issue:
I've got an MVC5 Web application which is using the built-in support for authentication via Facebook and Google. When we built this app a few months ago, we followed this tutorial: http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on and everything worked great.
Now, all of a sudden, the Facebook authentication has just stopped working alltogether. The Google authentication still works great.
Description of the problem: We click the link to connect using Facebook, we are redirected to Facebook where we are prompted if we wan't to allow our Facebook app access to our profile. When we click "OK" we are redirected back to our site, but instead of being logged in we simply end up at the login screen.
I've gone through this process in debug mode and I've got this ActionResult in my account controller as per the tutorial mentioned above:
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
............
When stepping through the code and upon returning from Facebook, the loginInfo object is always NULL, which causes the user to be redirected back to the login.
In order to understand what is actually happening behind the scenes, I installed Fiddler and monitored the HTTP traffic. What I disovered is that upon clicking "OK" at the Facebook permission dialog, Facebook redirects back to our application with this URL:
https://localhost/signin-facebook?code=<access-token>
This URL is not an actual file and probably handled by some controller/handler built into this OWIN framework I'm guessing. Most likely, it is connecting back to Facebook using the given code to query information about the user which is trying to login. Now, the problem is that instead of doing that, we are redirected to:
/Account/ExternalLoginCallback?error=access_denied
Which I'm sure is something Facebook is doing, that is, instead of giving us the user data, it's redirecting us back with this error message.
This causes the AuthenticationManager.GetExternalLoginInfoAsync();
to fail and always return NULL.
I'm completely out of ideas. As far as we know, we did not change anything on our end.
I've tried creating a new Facebook app, I've tried following the tutorial again but I always have the same problem.
Any ideas welcome!
Update!
OK, this is driving me insane! I've now manually gone through the steps required to perform the authentication and everything works great when I do that. Why on earth is this not working when using the MVC5 Owin stuff?
This is what I did:
// Step 1 - Pasted this into a browser, this returns a code
https://www.facebook.com/dialog/oauth?response_type=code&client_id=619359858118523&redirect_uri=https%3A%2F%2Flocalhost%2Fsignin-facebook&scope=&state=u9R1m4iRI6Td4yACEgO99ETQw9NAos06bZWilJxJrXRn1rh4KEQhfuEVAq52UPnUif-lEHgayyWrsrdlW6t3ghLD8iFGX5S2iUBHotyTqCCQ9lx2Nl091pHPIw1N0JV23sc4wYfOs2YU5smyw9MGhcEuinvTAEql2QhBowR62FfU6PY4lA6m8pD3odI5MwBYOMor3eMLu2qnpEk0GekbtTVWgQnKnH6t1UcC6KcNXYY
I was redirected back to localhost (which I had shut down at this point to avoid being redirected immediately away). The URL I was redirected to is this:
https://localhost/signin-facebook?code=<code-received-removed-for-obvious-reasons>
Now, I grabbed the code I got and used it in the URL below:
// Step 2 - opened this URL in a browser, and successfully retrieved an access token
https://graph.facebook.com/oauth/access_token?client_id=619359858118523&redirect_uri=https://localhost/signin-facebook&client_secret=<client-secret>&code=<code-from-step-1>
// Step 3 - Now I'm able to query the facebook graph using the access token from step 2!
https://graph.facebook.com/me?access_token=<access-token-from-step-2>
No errors, everything works great! Then why the hell is this not working when using the MVC5 Owin stuff? There's obviously something wrong with the OWin implementation.
Ok I've got a solution to the problem.
This is the code I had previously in my Startup.Auth.cs file:
var x = new FacebookAuthenticationOptions();
//x.Scope.Add("email");
x.AppId = "1442725269277224";
x.AppSecret = "<secret>";
x.Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
//Get the access token from FB and store it in the database and
//use FacebookC# SDK to get more information about the user
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken",context.AccessToken));
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:name", context.Name));
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:email", context.Email));
}
};
x.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(x);
Notice how the
x.Scope.Add("email")
line has been commented out, but still I'm query-ing for the e-mail later in the OnAuthenticated handler? Yup, that's right. For some reason this worked flawlessly for a few weeks.
My solution was to simply uncomment the x.Scope.Add("email"); line to make sure that the scope=email variable was present in the initial request to Facebook.
Now everything works like it did!
I cannot understand why this worked before like it was. The only explanation I can come up with is that Facebook changed something on their end.
这篇关于ASP.NET MVC5 OWIN Facebook认证突然不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!