According to Previous Answer I got my solution. In MVC4 everyone write down their AppID and SecurityCode. Due to change of facebook GRAPH API those previous links are broken. Consequently everyone need to change the RegisterFacebookClient calss. But this class is a sealed class in the .Net library, so anyone can't extend or overwrite it. As a result we need to use a wrapper class. Let us consider my Wrapper class is FacebookClientV2Dot3 therefore my class will be
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using DotNetOpenAuth.AspNet.Clients;
using Newtonsoft.Json;
public class FacebookClientV2Dot3 : OAuth2Client
{
#region Constants and Fields
/// <summary>
/// The authorization endpoint.
/// </summary>
private const string AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth";
/// <summary>
/// The token endpoint.
/// </summary>
private const string TokenEndpoint = "https://graph.facebook.com/oauth/access_token";
/// <summary>
/// The user info endpoint.
/// </summary>
private const string UserInfoEndpoint = "https://graph.facebook.com/me";
/// <summary>
/// The app id.
/// </summary>
private readonly string _appId;
/// <summary>
/// The app secret.
/// </summary>
private readonly string _appSecret;
/// <summary>
/// The requested scopes.
/// </summary>
private readonly string[] _requestedScopes;
#endregion
/// <summary>
/// Creates a new Facebook OAuth2 client, requesting the default "email" scope.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
public FacebookClient(string appId, string appSecret)
: this(appId, appSecret, new[] { "email" }) { }
/// <summary>
/// Creates a new Facebook OAuth2 client.
/// </summary>
/// <param name="appId">The Facebook App Id</param>
/// <param name="appSecret">The Facebook App Secret</param>
/// <param name="requestedScopes">One or more requested scopes, passed without the base URI.</param>
public FacebookClient(string appId, string appSecret, params string[] requestedScopes)
: base("facebook")
{
if (string.IsNullOrWhiteSpace(appId))
throw new ArgumentNullException("appId");
if (string.IsNullOrWhiteSpace(appSecret))
throw new ArgumentNullException("appSecret");
if (requestedScopes == null)
throw new ArgumentNullException("requestedScopes");
if (requestedScopes.Length == 0)
throw new ArgumentException("One or more scopes must be requested.", "requestedScopes");
_appId = appId;
_appSecret = appSecret;
_requestedScopes = requestedScopes;
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
var state = string.IsNullOrEmpty(returnUrl.Query) ? string.Empty : returnUrl.Query.Substring(1);
return BuildUri(AuthorizationEndpoint, new NameValueCollection
{
{ "client_id", _appId },
{ "scope", string.Join(" ", _requestedScopes) },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
{ "state", state },
});
}
protected override IDictionary<string, string> GetUserData(string accessToken)
{
var uri = BuildUri(UserInfoEndpoint, new NameValueCollection { { "access_token", accessToken } });
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
using (var webResponse = webRequest.GetResponse())
using (var stream = webResponse.GetResponseStream())
{
if (stream == null)
return null;
using (var textReader = new StreamReader(stream))
{
var json = textReader.ReadToEnd();
var extraData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToString());
data.Add("picture", string.Format("https://graph.facebook.com/{0}/picture", data["id"]));
return data;
}
}
}
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
var uri = BuildUri(TokenEndpoint, new NameValueCollection
{
{ "code", authorizationCode },
{ "client_id", _appId },
{ "client_secret", _appSecret },
{ "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
});
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
string accessToken = null;
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
// handle response from FB
// this will not be a url with params like the first request to get the 'code'
Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);
using (StreamReader sr = new StreamReader(response.GetResponseStream(), rEncoding))
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
var jConvert = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(jsonObject));
Dictionary<string, object> desirializedJsonObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jConvert.ToString());
accessToken = desirializedJsonObject["access_token"].ToString();
}
return accessToken;
}
private static Uri BuildUri(string baseUri, NameValueCollection queryParameters)
{
var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k]));
var qs = String.Join("&", keyValuePairs);
var builder = new UriBuilder(baseUri) { Query = qs };
return builder.Uri;
}
/// <summary>
/// Facebook works best when return data be packed into a "state" parameter.
/// This should be called before verifying the request, so that the url is rewritten to support this.
/// </summary>
public static void RewriteRequest()
{
var ctx = HttpContext.Current;
var stateString = HttpUtility.UrlDecode(ctx.Request.QueryString["state"]);
if (stateString == null || !stateString.Contains("__provider__=facebook"))
return;
var q = HttpUtility.ParseQueryString(stateString);
q.Add(ctx.Request.QueryString);
q.Remove("state");
ctx.RewritePath(ctx.Request.Path + "?" + q);
}
}
Look here you I have replaces all the API links by newer version links.
Now you need to modify your
AuthConfig
Just use a wrapper class
OAuthWebSecurity.RegisterClient(new FacebookClientV2Dot3("AppID", "HassedPassword"));
Then all success. You facebook login will be back in previous state.
However you can face a new issue regarding this new API rather than previous API, the problem is that IP Whitelisting. Like this image. Hope you will need nothing but this. Happy coding.