Facebook 身份验证:调用 https://graph.facebook.com/oauth/access_token returns 400 错误请求

Facebook authentication: call to https://graph.facebook.com/oauth/access_token returns 400 bad request

正在尝试在 mvc web 应用程序中实现 facebook 身份验证。

在 localhost 中,一切正常。在测试服务器中,我得到

调用时出现 400 个错误请求

https://graph.facebook.com/oauth/access_token?client_id=xxx &redirect_uri=xxx &client_secret=xxx &code=xxx

我正在使用从 here

获得的 FacebookScopedClient class
using System;
using System.Net;
using System.Collections.Generic;
using System.Web;
using System.Web.Helpers;
using System.Collections.Specialized;
using Newtonsoft.Json;
using System.Web.Script.Serialization;


namespace ExtensionMethods
{
    public class FacebookV2Client : DotNetOpenAuth.AspNet.Clients.OAuth2Client
    {
        private const string AuthorizationEP = "https://www.facebook.com/v2.0/dialog/oauth";
        private const string TokenEP = "https://graph.facebook.com/v2.0/oauth/access_token";
        private readonly string _appId;
        private readonly string _appSecret;

        public FacebookV2Client(string appId, string appSecret)
            : base("facebook")
        {
            this._appId = appId;
            this._appSecret = appSecret;
        }


        protected override Uri GetServiceLoginUrl(Uri returnUrl)
        {
            return new Uri(
                        AuthorizationEP
                        + "?client_id=" + this._appId
                        + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString())
                        + "&scope=email,user_about_me"
                        + "&display=page"
                    );
        }

        protected override IDictionary<string, string> GetUserData(string accessToken)
        {
            WebClient client = new WebClient();
            string content = client.DownloadString(
                "https://graph.facebook.com/me?access_token=" + accessToken
            );
            dynamic data = Json.Decode(content);
            return new Dictionary<string, string> {
                {
                    "username",
                    data.email
                },
                {
                    "id",
                    data.id
                },
                {
                    "name",
                    data.name
                },
                {
                    "photo",
                    "https://graph.facebook.com/" + data.id + "/picture"
                },
                {
                    "email",
                    data.email
                }
            };
        }

        protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
        {
            WebClient client = new WebClient();
            string content = client.DownloadString(
                TokenEP
                + "?client_id=" + this._appId
                + "&client_secret=" + this._appSecret
                + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString())
                + "&code=" + authorizationCode
            );

            NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(content);
            if (nameValueCollection != null)
            {
                string result = nameValueCollection["access_token"];
                return result;
            }
            return null;
        }
    }
}

并在AuthConfig.cs

string facebook_appId = "Your appId";
string facebook_appSecret = "Your appSecret";

OAuthWebSecurity.RegisterClient(
    new FacebookV2Client(
        appId: facebook_appId,
        appSecret: facebook_appSecret),
        "facebook", null
);

Reference

已解决。 Facebook 返回了 400 个错误请求,因为它需要 redirect_uri 调用两者时参数相同

https://www.facebook.com/dialog/oauthhttps://graph.facebook.com/oauth/access_token

我正在使用网上流传的 FacebookScopedClient class 的变体。

它设置 redirect_uri 的值来自:context.Request.Url.OriginalString;

那个字符串包含端口号,而原来的 url 没有。

解决方案是在第一次调用中包含端口号,在第二次调用中将其删除,或者首先不从 Request.Url 中获取 redirect_uri 值。

我选择了第二个选项,使用这个:

  if (context.Request.Url.IsDefaultPort)
            {
                rawUrl = rawUrl.Replace(":80", ""); //patch to remove port number. 
            }

它可能不是防弹的,因为在 url 的其他地方可能会出现“:80”的奇怪情况,但它足以满足我的需要。