Facebook Web应用程序扩展权限第二步不显示 [英] Facebook web application extended permissions second step dont show

查看:303
本文介绍了Facebook Web应用程序扩展权限第二步不显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Update2
这个帖子变老了,但仍然是相关的..下面是我解决的方法。我标记了其他人的回答,因为我认为它更好地回答了这个问题。我在accountcontroller中调用类似的方法(我将要重构:))。字符串应该是一个列表...我想你得到它。

  ///< summary> 
///由于缺少私有权,操作失败时使用此方法。它将通过提供的许可请求将用户重定向到Facebook。
/// Refactor来处理请求列表。
///< / 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;

//将用户浏览器重定向到Facebook,要求用户授权我们的Facebook应用程序
HttpContext.Current.Response.Redirect(urlAuthorize,true); //这不能使用WebRequest,因为Facebook可能需要在用户浏览器中显示对话框
}

然后,每个使用facebok C#SDK调用脸书的方法,如/ me / home都会抓住FacebookOAuthException,并重定向到该方法。这就是我们如何应用最后的做法,即不需要向用户询问权限。这种方法应该有匹配的直接url,但是我们刚刚开始:)



希望它有帮助

  ///< summary> 
///检查请求的权限或处理FacebookOAuthExceptions的不同方式。
///< / summary>
///< param name =foae>异常对象< / 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);
}
}

更新:此行为是由.Net oauth实现引起的,其具有在密封类中硬编码的范围。添加图4以显示除电子邮件(由.net oauth提供程序的所有请求发送)之外缺少其他范围的请求参数。将,publish_stream添加到查询字符串可以让我想要的行为。任何人都知道如何实现这一点?



请不要提交关于Facebook最佳做法或替代解决方案的答案或评论。我有一个替代解决方案,但希望这可以使用默认的registerfacebookclient参数。我已经根据两个答案指定了我要求的权限,将应用程序更新为oly使用publish_stream。



图4



原始问题:
我正在设置一个需要漂亮的应用程序(C#.Net4.5 MVC4,razor views) Facebook的所有可用用户权限。
您可以在下面看到代码示例,我如何设置全部。



问题是当点击图1中的好时,Facebook会将我发回给我的应用程序。据了解,应该有一个额外的屏幕(图2)要求更重的权限。到目前为止,我只获得了图1所示的权限。图1



图2



所以,使用基本的
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);

这是我如何处理响应,但是这里没有提示用户扩展权限,对于电子邮件,



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

//将会话保存到会话
会话[accesstoken] = result.ExtraData [accesstoken];
会话[id] = result.ExtraData [id];

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

if(User.Identity.IsAuthenticated)
{
//如果当前用户登录,则添加新帐户
OAuthWebSecurity.CreateOrUpdateAccount (result.Provider,result.ProviderUserId,User.Identity.Name);
return RedirectToLocal(returnUrl);
}
else
{
//用户是新的,请求他们所需的会员名称
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]

解决方案

我有同样的问题。像你一样,我配置了用于定义我的应用程序范围的RegisterFacebookClient,不幸的是,请求没有包括我配置的范围。所以我发现 。似乎这样会奏效,但还不够。所以我发现这个



所以这里是解决我的问题:



首先我将这个新客户端添加到我的代码中:

 使用系统; 
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用System.Net;
使用System.Text;
使用System.Text.RegularExpressions;
使用System.Web;
使用DotNetOpenAuth.AspNet;
使用Newtonsoft.Json;

命名空间MyApp.UI.Infrastructure
{
public class FacebookScopedClient:IAuthenticationClient
{
private string appId;
私人字符串appSecret;
私有字符串范围;

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;
////获取响应
WebResponse webResponse = myRequest.GetResponse();
Stream respStream = webResponse.GetResponseStream();
////
StreamReader ioStream = new StreamReader(respStream);
string pageContent = ioStream.ReadToEnd();
////关闭流
ioStream.Close();
respStream.Close();
return pageContent;
}
catch(异常)
{
}
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);

//这个字典必须包含
字典< 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 {returnfacebook;


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;
//从这里我们需要删除代码部分
rawUrl = Regex.Replace(rawUrl,& code = [^&] *,);

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

if(userData == null)
返回新的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);
返回结果;
}
}
}

我把它放在一个文件夹我的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);

就是这样。这可以帮助你,帮助我。


Update2 This post is getting old but still relevant.. Below is whe way I solved it. I marked the other guys answer because I think it answers the question better. I'm calling a similar method(I'am about to refactor:)) in accountcontroller. The string should be a list... I think you get it.

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

Then every method making a call to facebook like /me/home with facebok C# SDK catches FacebookOAuthException and redirects to the folling method. This is how we apply the best practise of not asking permissions from users up front but when needed. This method should have aredirect url that matches as well but we've just get going :)

Hope it helps!

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

Update: This behaviour is caused by .Net oauth implementation which has the scope hard coded in a sealed class. Added figure 4 to show the request parameter where the lack of additional scopes besides "email"(which is sent with all requests by .net oauth provider). Adding ",publish_stream" to the query string gives me the wanted behaviour. Anyone knows how to achieve this?

Please do not submit answers or comments about facebook best practices or alternative solutions. I have an alternative solution but would like this to work with default registerfacebookclient parameters. I have updated the application to oly use publish_stream according to the two answers specifying on what permissions I'm asking for.

figure 4

Original question: I'm setting up an application (C#.Net4.5 MVC4, razor views) which need pretty much all available user permissions from facebook. You can see code examples below how I have set it all up.

The problem is that when clicking "okay" in figure 1, Facebook sends me back to my application. As I understand there should be an additional screen(figure2) asking for the "heavier" permissions. As of now I only get the permissions stated in figure one. That part works...

Figure 1

Figure 2

So, using basic 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);

This is how I handle the response but here facebook has not prompted the user for the extended permissions but only for email,

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

The closest to an answer I could find was a wp plugin which had the same issue. Their problem was solved by setting domain to localhost. This is how my application is set up. ![enter image description here][4]

解决方案

I got the same problem. As you did, I configured the RegisterFacebookClient with dictionary to define my app's scope, and unfortunately the request didn't include the scope as I configured. So I found that. It seems that would work, but it wasn't enough. So I found this.

So here is what solve my problems:

First of all I added this new client to my code:

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

I put it on a folder "infrastructure" in my asp.net solution with oder stuff, next I change my old configuration, in order to use the new facebook client, as follows:

Old code:

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

New Code:

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

That's it. It may help you, as helped me.

这篇关于Facebook Web应用程序扩展权限第二步不显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆