Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Facebook中的ASP.NET MVC5身份验证突然不起作用_Facebook_Asp.net Mvc 5_Owin - Fatal编程技术网

Facebook中的ASP.NET MVC5身份验证突然不起作用

Facebook中的ASP.NET MVC5身份验证突然不起作用,facebook,asp.net-mvc-5,owin,Facebook,Asp.net Mvc 5,Owin,2017年更新 我在发布原始问题时遇到的问题与Facebook最近的改变无关,Facebook强迫所有人使用2.3版API。有关该特定问题的解决方案,请参见下面sammy34的答案。/oauth/access_令牌端点的2.3版现在返回JSON,而不是表单编码的值 出于历史原因,我的原始问题如下: 我有一个MVC5 Web应用程序,它通过Facebook和Google使用内置的身份验证支持。几个月前,当我们构建这个应用程序时,我们遵循了这个教程:一切都很好 现在,Facebook认证突然停止了工

2017年更新

我在发布原始问题时遇到的问题与Facebook最近的改变无关,Facebook强迫所有人使用2.3版API。有关该特定问题的解决方案,请参见下面sammy34的答案。/oauth/access_令牌端点的2.3版现在返回JSON,而不是表单编码的值

出于历史原因,我的原始问题如下:

我有一个MVC5 Web应用程序,它通过Facebook和Google使用内置的身份验证支持。几个月前,当我们构建这个应用程序时,我们遵循了这个教程:一切都很好

现在,Facebook认证突然停止了工作。谷歌认证仍然很有效

问题描述:我们点击链接使用Facebook进行连接,我们会被重定向到Facebook,如果我们不允许Facebook应用访问我们的个人资料,系统会提示我们。当我们点击“确定”时,我们会被重定向回我们的站点,但是我们没有登录,而是直接进入登录屏幕

我已经在调试模式下完成了这个过程,根据上面提到的教程,我在我的帐户控制器中得到了这个ActionResult:

// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }
    ............
我相信这是Facebook正在做的事情,也就是说,它不是给我们提供用户数据,而是用这个错误消息将我们重定向回来

这会导致
AuthenticationManager.GetExternalLoginInfoAsync()
失败并始终返回NULL

我完全没有主意了。据我们所知,我们没有改变任何事情

我试着创建一个新的Facebook应用程序,我试着再次遵循教程,但我总是有同样的问题

欢迎有任何想法

更新

好吧,这让我发疯了!我现在已经手动完成了执行身份验证所需的步骤,当我这样做时,一切都很好。在使用MVC5 Owin时,这到底为什么不起作用

这就是我所做的:

    // 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>
//步骤1-将其粘贴到浏览器中,将返回一个代码
https://www.facebook.com/dialog/oauth?response_type=code&client_id=619359858118523&redirect_uri=https%3A%2F%2Flocalhost%2Fsignin-facebook&scope=&state=u9r1M4iri6td4yacego99etqw9naos06bzwiljrxrn1rh4eqhfuevaq52upnuif-lehgayywrsrrdlw6ghld8ifgx5s2iubhotytqcq9lx2nl091hpiw1n0jv23sc4wyfos2yu5smyw9mghceuinvtaeql2ql2qhbowr62ffu6pyla6m8pd3odiwbymoreMLu2qnpEk0GekbtTVWgQnKnH6t1UcC6KcNXYY
我被重定向回localhost(此时我已关闭该主机,以避免立即被重定向到别处)。我重定向到的URL是:
https://localhost/signin-facebook?code=
现在,我抓取了我得到的代码并在下面的URL中使用它:
//步骤2-在浏览器中打开此URL,并成功检索访问令牌
https://graph.facebook.com/oauth/access_token?client_id=619359858118523&redirect_uri=https://localhost/signin-facebook和客户端\u secret=&代码=
//第3步-现在我可以使用第2步中的访问令牌查询facebook图了!
https://graph.facebook.com/me?access_token=

没有错误,一切都很好!那么,为什么在使用MVC5 Owin的时候,这不起作用呢?OWin实现显然有问题。

好的,我找到了解决问题的方法

这是我以前在Startup.Auth.cs文件中的代码:

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);
行已被注释掉,但我仍在稍后的OnAuthenticated处理程序中查询电子邮件?是的,没错。出于某种原因,这在几周内完美无瑕

我的解决方案是简单地取消对x.Scope.Add(“email”)的注释;行以确保scope=email变量出现在对Facebook的初始请求中

现在一切都和以前一样


我不明白为什么以前会这样。我能想到的唯一解释是Facebook改变了他们的某些方面。

我也有这个问题,但这不是由范围设置引起的。我花了很长时间才弄明白这一点,但最终让我明白的是,在
OwinStartup.Configuration(IAppBuilder app)
中设置了一个自定义记录器

这将输出以下内容:

2014-05-31 21:14:48508[8]错误
Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware
[(null)]-0x00000000-身份验证失败
System.Net.Http.HttpRequestException:发送时出错 请求。-->System.Net.WebException:无法找到远程名称
解析:'graph.facebook.com'位于
System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
在System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)---内部异常堆栈跟踪的结束---at
System.Runtime.CompilerServices.TaskWaiter.ThrowForNonSuccess(任务
任务)在
System.Runtime.CompilerServices.TaskWaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()中 在
Microsoft.Owin.Security.Facebook.FacebookAuthenticationHandler.d_u0.MoveNext()


基于上述调用堆栈,我发现我的Azure VM无法解析graph.facebook.com。我所要做的就是运行“ipconfig/registerdns”来修复这个问题,我已经全部修复了…

我在谷歌认证方面也遇到了同样的问题。以下方法对我有效:

上述解决方案对我无效。最后,它似乎与会议有关。通过在上一次调用中“唤醒”会话,它将不再从getExternalLoginFoAsync()返回null

像OP一样,我让第三方auth工作了很长一段时间,然后突然停止了。我相信这是因为我在Azure上设置会话以使用Redis缓存时对代码进行了更改。

// 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>
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);
x.Scope.Add("email")
app.SetLoggerFactory(new LoggerFactory()); 
// Note: LoggerFactory is my own custom ILoggerFactory
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
        Session["WAKEUP"] = "NOW!";
        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }
public class FacebookOauthResponse
{
    public string access_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
}
        app.UseFacebookAuthentication(new FacebookAuthenticationOptions
        {
            AppId = "hidden",
            AppSecret = "hidden",
            BackchannelHttpHandler = new FacebookBackChannelHandler()
        });
public class FacebookBackChannelHandler : HttpClientHandler
{
    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var result = await base.SendAsync(request, cancellationToken);
        if (!request.RequestUri.AbsolutePath.Contains("access_token"))
            return result;

        // For the access token we need to now deal with the fact that the response is now in JSON format, not form values. Owin looks for form values.
        var content = await result.Content.ReadAsStringAsync();
        var facebookOauthResponse = JsonConvert.DeserializeObject<FacebookOauthResponse>(content);

        var outgoingQueryString = HttpUtility.ParseQueryString(string.Empty);
        outgoingQueryString.Add(nameof(facebookOauthResponse.access_token), facebookOauthResponse.access_token);
        outgoingQueryString.Add(nameof(facebookOauthResponse.expires_in), facebookOauthResponse.expires_in + string.Empty);
        outgoingQueryString.Add(nameof(facebookOauthResponse.token_type), facebookOauthResponse.token_type);
        var postdata = outgoingQueryString.ToString();

        var modifiedResult = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(postdata)
        };

        return modifiedResult;
    }
}
var facebookOptions = new FacebookAuthenticationOptions()
{
    AppId = "xxxxx",
    AppSecret = "xxxxx",
};

// Set requested scope
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("public_profile");

// Set requested fields
facebookOptions.Fields.Add("email");
facebookOptions.Fields.Add("first_name");
facebookOptions.Fields.Add("last_name");

facebookOptions.Provider = new FacebookAuthenticationProvider()
{
    OnAuthenticated = (context) =>
        {
            // Attach the access token if you need it later on for calls on behalf of the user
            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);
                var claimType = string.Format("{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 Task.FromResult(0);
       }
};

app.UseFacebookAuthentication(facebookOptions);
var info = await AuthenticationManager.GetExternalLoginInfoAsync();

if (info != null)
{
    var firstName = info.ExternalIdentity.Claims.First(c => c.Type == "first_name").Value;
    var lastName = info.ExternalIdentity.Claims.First(c => c.Type == "last_name").Value;
}
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 result = await base.SendAsync(request, cancellationToken);
if (!request.RequestUri.AbsolutePath.Contains("access_token"))
return result;
UserInformationEndpoint = "https://graph.facebook.com/v2.8/me?fields=id,name,email,first_name,last_name,picture"