Reputation: 4734
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
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
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
);
Upvotes: 1