2013-05-23 17 views
11

更新2 この投稿は古いものの、まだ関連しています..以下は私がそれを解決した方法です。私はそれがより良い質問に答えると思うので、私は他の人に答えました。私はaccountcontrollerで同様のメソッド(私はリファクタリングする:)を呼び出しています)。文字列はリストにする必要があります...私はあなたがそれを得ると思います。FacebookのWebアプリケーションの拡張アクセス許可の2番目の手順は表示されません

その後
/// <summary> 
    /// Use this method when an action fails due to lack of priviligies. It will redirect user to facebook with provided permission request. 
    /// Refactor to handle list of request. 
    /// </summary> 
    /// <param name="permission"></param> 
    private static void AddAdditionalPermissions(string permission) 
    { 
     System.Diagnostics.Trace.TraceInformation(permission + " not authorized for user."); 
     string facebook_urlAuthorize_base = "https://graph.facebook.com/oauth/authorize"; 
     string scope = permission; //see: https://developers.facebook.com/docs/authentication/permissions/ for extended permissions 
     string urlAuthorize = facebook_urlAuthorize_base; 
     urlAuthorize += "?client_id=" + AppId; 
     urlAuthorize += "&redirect_uri=" + "https://fbd.anteckna.nu/"; 
     urlAuthorize += "&scope=" + scope; 

     //redirect the users browser to Facebook to ask the user to authorize our Facebook application 
     HttpContext.Current.Response.Redirect(urlAuthorize, true); //this cannot be done using WebRequest since facebook may need to show dialogs in the users browser 
    } 

私/ FacebookがC#SDKと一緒に家がFacebookOAuthExceptionをキャッチし、folling方法にリダイレクト/のようにFacebookを利用して通話を行うすべてのメソッド。これは、ユーザーからの権限を前もって要求しないで、必要なときにベストプラクティスを適用する方法です。このメソッドは同様に一致する直接URLを持つ必要がありますが、私たちはちょうど行くつもりです:)

希望します!

/// <summary> 
    /// Check for what permissions to request or different ways to handle FacebookOAuthExceptions. 
    /// </summary> 
    /// <param name="foae">The exception object</param> 
    public static void HandleAuthorizationsExceptions(FacebookOAuthException foae) 
    { 
     if (foae.Message.Contains("publish_permissions")) 
     { 
      AddAdditionalPermissions("publish_permissions"); 
     } 
     else if (foae.Message.Contains("read_stream")) 
     { 
      AddAdditionalPermissions("read_stream"); 
     } 
     else 
     { 
      System.Diagnostics.Trace.TraceError("Unhandled error at:" + foae.StackTrace); 
     } 
    } 

更新:この動作は、ハード密閉クラスで符号化された範囲を有するネットのOAuth実装によって引き起こされます。図4に、「eメール」以外の追加のスコープがない場合のリクエストパラメータを示します(これは.net oauthプロバイダがすべてのリクエストとともに送信します)。 "、publish_stream"をクエリ文字列に追加すると、私には望ましい動作が得られます。誰でもこれを達成する方法を知っていますか?

Facebookのベストプラクティスまたは代替ソリューションに関する回答やコメントは提出しないでください。私は別の解決策がありますが、これはデフォルトのregisterfacebookclientパラメータで動作するようにしたいと思います。私は、私が求めているアクセス許可を指定する2つの答えに従って、olyがpublish_streamを使用するようにアプリケーションを更新しました。

図4 Image showing scope parameter in query string

オリジナル質問: 私はかなりのFacebookから利用可能なすべてのユーザー権限を必要とするアプリケーション(C#.Net4.5 MVC4、かみそりビュー)を設定しています。 以下のコード例は、どのように設定したかを下に示しています。

問題は、図1の「OK」をクリックするとFacebookが私を自分のアプリケーションに送り返すことです。私が理解しているように、「重い」パーミッションを求める追加の画面(figure2)が必要です。現時点では、図1に記載されている権限のみを取得します。その部分は、私がここに応答を扱うが、どのようこれは

図1 Facebook permissions dialog C#

図2 enter image description here

ので、使用して基本的な AuthConfig.cs

var facebooksocialData = new Dictionary<string, object>(); 
      facebooksocialData.Add("scope", "email,publish_stream,read_stream,publish_actions,manage_pages,create_event,offline_access"); 
      OAuthWebSecurity.RegisterFacebookClient(
       appId: "165359673639901", 
       appSecret: "15091cb2094a1996ae6c7b324f0300e6", 
       displayName: "Facebook", 
       extraData: facebooksocialData); 

...作品facebookは、ユーザーに拡張アクセス許可を要求しませんでしたが、電子メールの場合にのみ

AccountController.cs

// 
     // GET: /Account/ExternalLoginCallback 

     [AllowAnonymous] 
     public ActionResult ExternalLoginCallback(string returnUrl) 
     { 
      AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl })); 
      if (!result.IsSuccessful) 
      { 
       return RedirectToAction("ExternalLoginFailure"); 
      } 

      // Save the accesstoken into session 
      Session["accesstoken"] = result.ExtraData["accesstoken"]; 
      Session["id"] = result.ExtraData["id"]; 

      if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false)) 
      { 
       return RedirectToLocal(returnUrl); 
      } 

      if (User.Identity.IsAuthenticated) 
      { 
       // If the current user is logged in add the new account 
       OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name); 
       return RedirectToLocal(returnUrl); 
      } 
      else 
      { 
       // User is new, ask for their desired membership name 
       string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId); 
       ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName; 
       ViewBag.ReturnUrl = returnUrl; 
       return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData }); 
      } 
     } 

私は同じ問題を持っていたWPプラグインだった見つけることができる答えに最も近いです。彼らの問題は、ドメインをlocalhostに設定することで解決しました。これが私のアプリケーションのセットアップ方法です。 ![ここに画像の説明を入力] [4]

答えて

7

私は同じ問題を抱えています。以前のように、RegisterFacebookClientを辞書で設定してアプリのスコープを定義しましたが、残念ながらリクエストには設定したスコープが含まれていませんでした。だから私はthatを見つけた。それはうまくいくようですが、それだけでは不十分です。だから私はthisを見つけた。だからここ

は私の問題を解決するものである:すべての

まず私は自分のコードにこの新しいクライアントを追加しました:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Text.RegularExpressions; 
using System.Web; 
using DotNetOpenAuth.AspNet; 
using Newtonsoft.Json; 

namespace MyApp.UI.Infrastructure 
{ 
    public class FacebookScopedClient : IAuthenticationClient 
    { 
     private string appId; 
     private string appSecret; 
     private string scope; 

     private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id="; 
     public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?"; 
     public const string graphApiMe = "https://graph.facebook.com/me?"; 

     private static string GetHTML(string URL) 
     { 
      string connectionString = URL; 

      try 
      { 
       System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString); 
       myRequest.Credentials = CredentialCache.DefaultCredentials; 
       //// Get the response 
       WebResponse webResponse = myRequest.GetResponse(); 
       Stream respStream = webResponse.GetResponseStream(); 
       //// 
       StreamReader ioStream = new StreamReader(respStream); 
       string pageContent = ioStream.ReadToEnd(); 
       //// Close streams 
       ioStream.Close(); 
       respStream.Close(); 
       return pageContent; 
      } 
      catch (Exception) 
      { 
      } 
      return null; 
     } 

     private IDictionary<string, string> GetUserData(string accessCode, string redirectURI) 
     { 
      string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode); 
      if (token == null || token == "") 
      { 
       return null; 
      } 
      string access_token = token.Substring(token.IndexOf("access_token="), token.IndexOf("&")); 
      string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token); 

      // this dictionary must contains 
      Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data); 
      return userData; 
     } 

     public FacebookScopedClient(string appId, string appSecret, string scope) 
     { 
      this.appId = appId; 
      this.appSecret = appSecret; 
      this.scope = scope; 
     } 

     public string ProviderName 
     { 
      get { return "facebook"; } 
     } 

     public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl) 
     { 
      string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope; 
      context.Response.Redirect(url); 
     } 

     public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context) 
     { 
      string code = context.Request.QueryString["code"]; 

      string rawUrl = context.Request.Url.OriginalString; 
      //From this we need to remove code portion 
      rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", ""); 

      IDictionary<string, string> userData = GetUserData(code, rawUrl); 

      if (userData == null) 
       return new AuthenticationResult(false, ProviderName, null, null, null); 

      string id = userData["id"]; 
      string username = userData["username"]; 
      userData.Remove("id"); 
      userData.Remove("username"); 

      AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData); 
      return result; 
     } 
    } 
} 

を私はasp.net溶液中にフォルダ「インフラ」の上に置きます次のようにオーデルのもので、次の私は、Facebookの新しいクライアントを使用するためには、私の古い設定を変更します。

旧コード:

OAuthWebSecurity.RegisterFacebookClient(
appId: "<app-id>", 
appSecret: "<app-secret>", 
displayName: "Facebook", 
extraData: facebookExtraData); 

新しいコード:

OAuthWebSecurity.RegisterClient(
        new FacebookScopedClient(
         "<app-id>", 
         "<app-secret>", 
         "scope"), 
        "Facebook", 
        null); 

それです。それは私を助けたように、あなたを助けるかもしれません。

+2

これは変です。あなたのソリューションは私のために働いていますが、ローカルだけです。クラウドに自分のウェブサイトを公開すると、facebook認証が機能しなくなります。デフォルトのfacebookclientが機能するため、私のアプリケーションドメインはFacebook上で正しく設定されています。 – Bastaspast

+1

@Bastaspast、空白の問題は、プロパティ 'context.Request.Url.OriginalString'が返すように、instace URLが特定のネットワークポート内で呼び出されることです。だから、facebookに渡されたURLと一致しない。私はそれを解決するためのエレガントな方法が見つかりませんでしたが、私はこれを行いました: '#if!DEBUG rawUrl = rawUrl.Replace(": "+" context.Request.Url.Port ""); #endif' そのためすべてがスムーズにローカライズされ、クラウド上で動作します。しかし、この解決策は、あなたがDEBUGでロケールで動くようにしているに過ぎません。この場合、あなたはその行をコメントすることができます。あなたの説明のために –

+0

ありがとう! – Bastaspast

1

は、これらのスコープのために登録されたアプリのですか?私はGoogle OAuthに精通していますが、1つの権限にマッピングされた別のスコープがあります。 2番目のウィンドウを表示するには、アプリをスコープ用に登録する必要があります。それ以外の場合は、1番目のポップアップが尋ねる公開情報のみにアクセスできます。

+1

私はスコープでアプリを登録していませんでした。しかし、それは私の問題を解決しませんでした。私の問題をさらに調査したところ、スコープとして提供されているエクストラデータは、要求が行われたときにのみ電子メールを設定するため、この動作が見られました。問題は.Net OAuthの使用のどこかにあります。 –

1

まず、offline_accessはもう存在しません。したがって、あなたが求めている権限からです。

「ほとんどすべてのFacebookから入手できるユーザー権限を必要とする[アプリ]」

彼らは可能性があるため、Facebookは積極的に「念のために」ストレート初めから権限の山を求めて思いとどまら後で必要となる。ユーザが最初にトリガしたアクションに対して実際に必要なときにのみ、拡張パーミッションを要求する必要があります。

また、「読み取り」権限と「書き込み」権限を別々に求められます。

これらの要素が実際にあなたのエラーを引き起こしているかどうかはわかりませんが、私はFacebookがすでに読み書きのために開発者の警告を送信していることを知っています。 FBの従業員は、これらの警告を無視できることを確認しましたが、は現在です。施行これは将来のある時点で開始する可能性があります。

+1

あなたのアドバイスをいただきありがとうございますCBroe。私は、視覚障害者および聴覚障害者のためのインターフェースを備えたアプリケーションを構築しています。これは、できるだけ少ないインタラクションとポップアップを使用する必要があります。 –

+0

私はOPが正しいと思うし、彼のスコープはSDKのどこかで失われていると思います。 – Igy

+0

Magnus Karlsson私も同じ問題に直面しています。 –

関連する問題