CodeToad
CodeToad

Reputation: 4734

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

Trying to implement facebook authentication in mvc web application.

In localhost, everything works as expected. in testing server, I get

400 bad request when calling

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

I am using a FacebookScopedClient class that I got from here

Upvotes: 3

Views: 2687

Answers (2)

CodeToad
CodeToad

Reputation: 4734

Solved. Facebook returned 400 bad request because it expects the redirect_uri parameter to be identical in calls to both

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

I am using a variation of the FacebookScopedClient class that is floating on the net.

It sets the value of redirect_uri from: context.Request.Url.OriginalString;

that string contains the port number, while the original url does not.

the solution is to either include the port number in the first call, remove it from the second, or not get the redirect_uri value from the Request.Url in the first place.

I went with the second option, using this:

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

Its probably not bullet proof since there may be an odd case with ":80" showing up elsewhere in the url, but its suficcient for my needs.

Upvotes: 7

Muhammad Usman
Muhammad Usman

Reputation: 1362

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;
        }
    }
}

And in 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

Upvotes: 1

Related Questions