FacebookApplication.VerifyAuthentication (_httpContext, GenerateLocalCallbackUri ()) renvoie la valeur null sur Facebook.

J’ai développé une application MVC 5 à l’aide de nopcommerce et j’utilise la connexion à Facebook à l’aide d’un rappel externe, mais cela ne fonctionne plus et je ne peux pas trouver le problème. Et en utilisant ce code ci-dessous

this.FacebookApplication.VerifyAuthentication(_httpContext, GenerateLocalCallbackUri());

et il me renvoie toujours null et le statut d’authentification a échoué, j’ai cherché sur le Web et tout suivi et suivi les étapes, mais je ne peux toujours pas me connecter avec Facebook.

Mon code est comme ça dans FacebookProviderAuthorizer.cs

 private AuthorizeState VerifyAuthentication(ssortingng returnUrl) { var authResult = DotNetOpenAuth.AspNet.Clients.FacebookApplication.VerifyAuthentication(_httpContext, GenerateLocalCallbackUri()); if (authResult.IsSuccessful) { } } 

Et puis écrire la méthode de rappel

 private Uri GenerateLocalCallbackUri() { ssortingng url = ssortingng.Format("{0}plugins/externalauthFacebook/logincallback/", _webHelper.GetStoreLocation()); return new Uri(url); } 

Puis générer l’URL de connexion au service

 private Uri GenerateServiceLoginUrl() { //code copied from DotNetOpenAuth.AspNet.Clients.FacebookClient file var builder = new UriBuilder("https://www.facebook.com/dialog/oauth"); var args = new Dictionary(); args.Add("client_id", _facebookExternalAuthSettings.ClientKeyIdentifier); args.Add("redirect_uri", GenerateLocalCallbackUri().AbsoluteUri); args.Add("response_type", "token"); args.Add("scope", "email"); AppendQueryArgs(builder, args); return builder.Uri; } 

Nous avons rencontré le même problème le lundi 3/27/2017, lorsque Facebook a cessé de prendre en charge leur API de graphisme v2.2.

Nous utilisons également DotNetOpenAuth, qui a été initialement installé via Nuget. Le code source est disponible sur le lien ci-dessous:

https://github.com/DotNetOpenAuth/DotNetOpenAuth

Plus précisément, nous avons découvert que notre code utilisait la twig 4.3 qui contient le code source de DotNetOpenAuth.AspNet.DLL. Lors de l’inspection de la source, nous avons découvert que le problème venait de cet extrait de code de DotNetOpenAuth.AspNet \ Clients \ OAuth2 \ FacebookClient.cs, situé dans la méthode QueryAccessToken:

 using (WebClient client = new WebClient()) { ssortingng data = client.DownloadSsortingng(builder.Uri); if (ssortingng.IsNullOrEmpty(data)) { return null; } var parsedQuerySsortingng = HttpUtility.ParseQuerySsortingng(data); return parsedQuerySsortingng["access_token"]; } 

Le problème, en particulier, est l’appel ParseQuerySsortingng. À partir de la v2.3 de l’API, les données ne sont plus renvoyées sous forme de chaîne de requête HTML, mais au format JSON standard.

Pour résoudre ce problème, nous avons créé notre propre classe personnalisée, héritée de OAuth2Client, et importé la majeure partie du même code à partir de FacebookClient.cs. Nous avons ensuite remplacé le fragment de code ci-dessus par un code qui parsing la réponse JSON pour extraire le code d’access_token et le renvoie à la place. Vous pouvez voir un exemple de procédure à suivre dans la même classe FacebookClient, dans la méthode GetUserData:

 FacebookGraphData graphData; var request = WebRequest.Create( "https://graph.facebook.com/me?access_token=" + MessagingUtilities.EscapeUriDataSsortingngRfc3986(accessToken)); using (var response = request.GetResponse()) { using (var responseStream = response.GetResponseStream()) { graphData = JsonHelper.Deserialize(responseStream); } } 

Le seul autre changement était d’enregistrer notre classe personnalisée à la place de la classe FacebookClient afin que le rappel OAuth l’utilise pour gérer la publication à partir de l’API de Facebook. Une fois que nous avons fait cela, tout a fonctionné à nouveau.

J’ai utilisé le code partagé par @Vishal et j’ai obtenu le même résultat.

La principale chose sur laquelle nous devons nous concentrer est de remplacer la méthode QueryAccessToken pour utiliser la réponse json.

 protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng 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); ssortingng 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 desirializedJsonObject = JsonConvert.DeserializeObject>(jConvert.ToSsortingng()); accessToken = desirializedJsonObject["access_token"].ToSsortingng(); } return accessToken; } 

Étapes pour y parvenir: Étape 1. Ce que vous devez faire est d’append un fichier nommé FacebookClientOverride.cs (autre que FacebookClient.cs).

Voici l’extrait de code de l’ensemble du fichier.

  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 FacebookClient : OAuth2Client { #region Constants and Fields ///  /// The authorization endpoint. ///  private const ssortingng AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth"; ///  /// The token endpoint. ///  private const ssortingng TokenEndpoint = "https://graph.facebook.com/oauth/access_token"; ///  /// The user info endpoint. ///  private const ssortingng UserInfoEndpoint = "https://graph.facebook.com/me"; ///  /// The app id. ///  private readonly ssortingng _appId; ///  /// The app secret. ///  private readonly ssortingng _appSecret; ///  /// The requested scopes. ///  private readonly ssortingng[] _requestedScopes; #endregion ///  /// Creates a new Facebook OAuth2 client, requesting the default "email" scope. ///  /// The Facebook App Id /// The Facebook App Secret public FacebookClient(ssortingng appId, ssortingng appSecret) : this(appId, appSecret, new[] { "email" }) { } ///  /// Creates a new Facebook OAuth2 client. ///  /// The Facebook App Id /// The Facebook App Secret /// One or more requested scopes, passed without the base URI. public FacebookClient(ssortingng appId, ssortingng appSecret, params ssortingng[] requestedScopes) : base("facebook") { if (ssortingng.IsNullOrWhiteSpace(appId)) throw new ArgumentNullException("appId"); if (ssortingng.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 = ssortingng.IsNullOrEmpty(returnUrl.Query) ? ssortingng.Empty : returnUrl.Query.Subssortingng(1); return BuildUri(AuthorizationEndpoint, new NameValueCollection { { "client_id", _appId }, { "scope", ssortingng.Join(" ", _requestedScopes) }, { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) }, { "state", state }, }); } protected override IDictionary GetUserData(ssortingng 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>(json); var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToSsortingng()); data.Add("picture", ssortingng.Format("https://graph.facebook.com/{0}/picture", data["id"])); return data; } } } protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng 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); ssortingng 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 desirializedJsonObject = JsonConvert.DeserializeObject>(jConvert.ToSsortingng()); accessToken = desirializedJsonObject["access_token"].ToSsortingng(); } return accessToken; } private static Uri BuildUri(ssortingng baseUri, NameValueCollection queryParameters) { var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k])); var qs = Ssortingng.Join("&", keyValuePairs); var builder = new UriBuilder(baseUri) { Query = qs }; return builder.Uri; } ///  /// 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. ///  public static void RewriteRequest() { var ctx = HttpContext.Current; var stateSsortingng = HttpUtility.UrlDecode(ctx.Request.QuerySsortingng["state"]); if (stateSsortingng == null || !stateSsortingng.Contains("__provider__=facebook")) return; var q = HttpUtility.ParseQuerySsortingng(stateSsortingng); q.Add(ctx.Request.QuerySsortingng); q.Remove("state"); ctx.RewritePath(ctx.Request.Path + "?" + q); } } 

Étape 2. Ajoutez une référence à System.Web.Extensions

Étape 3. Dans le projet FacebookProviderAuthorizer.cs (projet Nopcommerce), recherchez la propriété FacebookClient private Facebook Facebook _Client _facebookApplication;

Cela devrait faire référence à votre nouveau fichier que vous venez d’append.

Étape 4. Maintenant, mettez un point d’arrêt dans la méthode nommée VerifyAuthentication dans le fichier FacebookProviderAuthorizer.cs.

AuthResult.IsSuccessful doit être vrai maintenant, car le jeton a été analysé avec succès.

Merci a tous. S’il vous plaît, si les solutions ont fonctionné pour vous.

En me basant sur le message de Steve, j’ai créé un “FriendlyFacebookClient” à utiliser à la place de FacebookClient, une copie de certaines des méthodes internes et remplacé QueryAccessToken par ce qui suit:

  protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng authorizationCode) { UriBuilder builder = new UriBuilder("https://graph.facebook.com/oauth/access_token"); AppendQueryArgs(builder, (IEnumerable>)new Dictionary() { { "client_id", this.appId}, { "redirect_uri", FriendlyFacebookClient.NormalizeHexEncoding(returnUrl.AbsoluteUri)}, { "client_secret", this.appSecret }, { "code", authorizationCode }, { "scope", "email" } }); using (WebClient webClient = new WebClient()) { var response = webClient.DownloadSsortingng(builder.Uri); var data = JsonConvert.DeserializeObject>(response); return data["access_token"]; } } 

Selon la réponse précédente, j’ai eu ma solution. Dans MVC4 tout le monde écrit son AppID et son SecurityCode En raison du changement de Facebook GRAPH API, ces liens précédents sont cassés. Par conséquent, tout le monde doit changer de classe RegisterFacebookClient . Mais cette classe est une classe scellée dans la bibliothèque .Net, donc personne ne peut l’étendre ou l’écraser. En conséquence, nous devons utiliser une classe wrapper . J’écris cette réponse parce que tous les fournisseurs de la réponse précédente ont manqué une chose pour laquelle j’ai beaucoup souffert. Parce qu’ils n’ont pas mentionné le système de classe AuthConfig dans la classe AuthConfig . Donc, il en faut trop pour résoudre ce problème. Par conséquent, je vais étape par étape comme ci-dessous. Considérons que ma classe Wrapper est FacebookClientV2Dot3 donc ma classe sera

 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 ///  /// The authorization endpoint. ///  private const ssortingng AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth"; ///  /// The token endpoint. ///  private const ssortingng TokenEndpoint = "https://graph.facebook.com/oauth/access_token"; ///  /// The user info endpoint. ///  private const ssortingng UserInfoEndpoint = "https://graph.facebook.com/me"; ///  /// The app id. ///  private readonly ssortingng _appId; ///  /// The app secret. ///  private readonly ssortingng _appSecret; ///  /// The requested scopes. ///  private readonly ssortingng[] _requestedScopes; #endregion ///  /// Creates a new Facebook OAuth2 client, requesting the default "email" scope. ///  /// The Facebook App Id /// The Facebook App Secret public FacebookClient(ssortingng appId, ssortingng appSecret) : this(appId, appSecret, new[] { "email" }) { } ///  /// Creates a new Facebook OAuth2 client. ///  /// The Facebook App Id /// The Facebook App Secret /// One or more requested scopes, passed without the base URI. public FacebookClient(ssortingng appId, ssortingng appSecret, params ssortingng[] requestedScopes) : base("facebook") { if (ssortingng.IsNullOrWhiteSpace(appId)) throw new ArgumentNullException("appId"); if (ssortingng.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 = ssortingng.IsNullOrEmpty(returnUrl.Query) ? ssortingng.Empty : returnUrl.Query.Subssortingng(1); return BuildUri(AuthorizationEndpoint, new NameValueCollection { { "client_id", _appId }, { "scope", ssortingng.Join(" ", _requestedScopes) }, { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) }, { "state", state }, }); } protected override IDictionary GetUserData(ssortingng 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>(json); var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToSsortingng()); data.Add("picture", ssortingng.Format("https://graph.facebook.com/{0}/picture", data["id"])); return data; } } } protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng 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); ssortingng 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 desirializedJsonObject = JsonConvert.DeserializeObject>(jConvert.ToSsortingng()); accessToken = desirializedJsonObject["access_token"].ToSsortingng(); } return accessToken; } private static Uri BuildUri(ssortingng baseUri, NameValueCollection queryParameters) { var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k])); var qs = Ssortingng.Join("&", keyValuePairs); var builder = new UriBuilder(baseUri) { Query = qs }; return builder.Uri; } ///  /// 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. ///  public static void RewriteRequest() { var ctx = HttpContext.Current; var stateSsortingng = HttpUtility.UrlDecode(ctx.Request.QuerySsortingng["state"]); if (stateSsortingng == null || !stateSsortingng.Contains("__provider__=facebook")) return; var q = HttpUtility.ParseQuerySsortingng(stateSsortingng); q.Add(ctx.Request.QuerySsortingng); q.Remove("state"); ctx.RewritePath(ctx.Request.Path + "?" + q); } } 

Regardez, vous avez remplacé tous les liens API par des liens plus récents.

Maintenant, vous devez modifier votre

AuthConfig

Utilisez simplement une classe wrapper au lieu de RegisterFacebookClient . Bloquez complètement ces portions de code. Et ajoutez ceci …

 OAuthWebSecurity.RegisterClient(new FacebookClientV2Dot3("AppID", "HassedPassword")); 

Alors tout le succès. Votre identifiant facebook sera de nouveau à l’état précédent.

Cependant, vous pouvez faire face à un nouveau problème concernant cette nouvelle API plutôt que la précédente, le problème est celui de la IP Whitelisting . Comme cette image . J’espère que vous n’aurez besoin de rien d’autre. Bonne codage.

Comme suggéré par @SteveTerry, nous devons mettre à jour la fonction QueryAccessToken dans la classe FacebookClient. Malheureusement, “FacebookClient” est une classe scellée, nous ne pouvons donc pas hériter ni remplacer. Alors, quelle que soit la manière que vous choisissez, vous le souhaitez. Voici à quoi devrait ressembler le résultat final:

L’ancien code de cette fonction était:

 protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng authorizationCode) { // Note: Facebook doesn't like us to url-encode the redirect_uri value var builder = new UriBuilder(TokenEndpoint); builder.AppendQueryArgs( new Dictionary { { "client_id", this.appId }, { "redirect_uri", NormalizeHexEncoding(returnUrl.AbsoluteUri) }, { "client_secret", this.appSecret }, { "code", authorizationCode }, { "scope", "email" }, }); using (webclient client = new webclient()) { ssortingng data = client.downloadssortingng(builder.uri); if (ssortingng.isnullorempty(data)) { return null; } var parsedqueryssortingng = httputility.parsequeryssortingng(data); return parsedqueryssortingng["access_token"]; } 

}

Et pour supporter la nouvelle version de fb api, cela devrait être comme ceci:

 ///  /// Contains access_token of a Facebook user. ///  [DataContract] [EditorBrowsable(EditorBrowsableState.Never)] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Facebook", Justification = "Brand name")] public class FacebookAccessTokenData { #region Public Properties ///  /// ///  [DataMember(Name = "access_token")] public ssortingng AccessToken { get; set; } ///  /// ///  [DataMember(Name = "token_type")] public ssortingng TokenType { get; set; } ///  /// ///  [DataMember(Name = "expires_in")] public ssortingng ExpiresIn { get; set; } #endregion } ///  /// Obtains an access token given an authorization code and callback URL. ///  ///  /// The return url. ///  ///  /// The authorization code. ///  ///  /// The access token. ///  protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng authorizationCode) { // Note: Facebook doesn't like us to url-encode the redirect_uri value var builder = new UriBuilder(TokenEndpoint); builder.AppendQueryArgs( new Dictionary { { "client_id", this.appId }, { "redirect_uri", NormalizeHexEncoding(returnUrl.AbsoluteUri) }, { "client_secret", this.appSecret }, { "code", authorizationCode }, { "scope", "email" }, }); FacebookAccessTokenData graphData; var request = WebRequest.Create(builder.Uri); using (var response = request.GetResponse()) { using (var responseStream = response.GetResponseStream()) { graphData = JsonHelper.Deserialize(responseStream); } } return graphData.AccessToken; } 

Je résous mon problème. Je vais faire la même chose que @Adam décrit dans sa réponse. Conformément à @Adam, @SteveTerry et à la réponse de @ Adeem, je modifie mon code et crée une classe personnalisée pour FacebookClient avec un nom différent. et remplacez par la référence originale de FacebookClient dans nopCommerce.

 public class FacebookOAuth2Client : OAuth2Client { #region Constants and Fields ///  /// The authorization endpoint. ///  private const ssortingng AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth"; ///  /// The token endpoint. ///  private const ssortingng TokenEndpoint = "https://graph.facebook.com/oauth/access_token"; ///  /// The user info endpoint. ///  private const ssortingng UserInfoEndpoint = "https://graph.facebook.com/me"; ///  /// The app id. ///  private readonly ssortingng _appId; ///  /// The app secret. ///  private readonly ssortingng _appSecret; ///  /// The requested scopes. ///  private readonly ssortingng[] _requestedScopes; #endregion ///  /// Creates a new Facebook OAuth2 client, requesting the default "email" scope. ///  /// The Facebook App Id /// The Facebook App Secret public FacebookClient(ssortingng appId, ssortingng appSecret) : this(appId, appSecret, new[] { "email" }) { } ///  /// Creates a new Facebook OAuth2 client. ///  /// The Facebook App Id /// The Facebook App Secret /// One or more requested scopes, passed without the base URI. public FacebookClient(ssortingng appId, ssortingng appSecret, params ssortingng[] requestedScopes) : base("facebook") { if (ssortingng.IsNullOrWhiteSpace(appId)) throw new ArgumentNullException("appId"); if (ssortingng.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 = ssortingng.IsNullOrEmpty(returnUrl.Query) ? ssortingng.Empty : returnUrl.Query.Subssortingng(1); return BuildUri(AuthorizationEndpoint, new NameValueCollection { { "client_id", _appId }, { "scope", ssortingng.Join(" ", _requestedScopes) }, { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) }, { "state", state }, }); } protected override IDictionary GetUserData(ssortingng 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>(json); var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToSsortingng()); data.Add("picture", ssortingng.Format("https://graph.facebook.com/{0}/picture", data["id"])); return data; } } } protected override ssortingng QueryAccessToken(Uri returnUrl, ssortingng 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); ssortingng 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 desirializedJsonObject = JsonConvert.DeserializeObject>(jConvert.ToSsortingng()); accessToken = desirializedJsonObject["access_token"].ToSsortingng(); } return accessToken; } private static Uri BuildUri(ssortingng baseUri, NameValueCollection queryParameters) { var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k])); var qs = Ssortingng.Join("&", keyValuePairs); var builder = new UriBuilder(baseUri) { Query = qs }; return builder.Uri; } ///  /// 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. ///  public static void RewriteRequest() { var ctx = HttpContext.Current; var stateSsortingng = HttpUtility.UrlDecode(ctx.Request.QuerySsortingng["state"]); if (stateSsortingng == null || !stateSsortingng.Contains("__provider__=facebook")) return; var q = HttpUtility.ParseQuerySsortingng(stateSsortingng); q.Add(ctx.Request.QuerySsortingng); q.Remove("state"); ctx.RewritePath(ctx.Request.Path + "?" + q); } } 

Dans ce code, je n’ai aucune référence à JsonHelper, donc j’utilise jsonConvert simple. Merci encore @Adam, @SteveTerry et @ Adeem de l’aide.