Веб-приложение Facebook расширенные разрешения второго шага не показывают
Update2
Это сообщение стареет, но все еще актуально. Ниже я решил это. Я отметил, что другие ребята отвечают, потому что я думаю, что он лучше отвечает на вопрос. Я вызываю аналогичный метод (я собираюсь реорганизовать:)) в accountcontroller. Строка должна быть списком... Я думаю, вы поняли.
/// <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, например /me/home с facebok С# SDK, захватывает FacebookOAuthException и перенаправляет на метод folling. Именно так мы применяем наилучшую практику отказа от запросов от пользователей, но при необходимости. Этот метод должен иметь прямой 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);
}
}
Обновить. Это поведение вызвано реализацией .Net oauth, которая имеет область жесткого кодирования в закрытом классе. Добавлена цифра 4, чтобы показать параметр запроса, где отсутствуют дополнительные области, кроме "электронной почты" (который отправляется со всеми запросами поставщика .net oauth). Добавление ", publish_stream" в строку запроса дает мне желаемое поведение. Кто-нибудь знает, как достичь этого?
Пожалуйста, не отправляйте ответы или комментарии о лучших практиках Facebook или альтернативных решениях. У меня есть альтернативное решение, но мне бы хотелось, чтобы это работало с параметрами registerfacebookclient по умолчанию. Я обновил приложение, чтобы использовать publish_stream в соответствии с двумя ответами, определяющими, на какие разрешения я прошу.
Рисунок 4 ![Image showing scope parameter in query string]()
Оригинальный вопрос:
Я настраиваю приложение (С#.Net4.5 MVC4, виды бритвы), которому требуется почти все доступные разрешения пользователя из facebook.
Ниже вы можете увидеть примеры кода, как я все это установил.
Проблема заключается в том, что при нажатии "okay" на рисунке 1 Facebook отправляет меня обратно в мое приложение. Насколько я понимаю, должен быть дополнительный экран (рисунок2), требующий "более тяжелых" разрешений. На данный момент я получаю только разрешения, указанные на рисунке 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]
Ответы
Ответ 1
У меня такая же проблема. Как и вы, я настроил RegisterFacebookClient со словарем, чтобы определить область моего приложения, и, к сожалению, запрос не включал область, как я настроил. Поэтому я нашел . Кажется, что это сработает, но этого было недостаточно. Поэтому я нашел этот.
Итак, вот что решает мои проблемы:
Прежде всего, я добавил этого нового клиента в свой код:
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
Зарегистрировано ли ваше приложение для этих областей? Я знаком с Google OAuth, у них есть отдельная область, которая соответствует одному разрешению. Ваше приложение должно быть зарегистрировано для областей, чтобы получить второе окно. Кроме того, у вас будет доступ только к общедоступной информации, которую запрашивает ваше первое всплывающее окно.
Ответ 3
Прежде всего, offline_access
больше не существует, поэтому он из разрешений, о которых вы просите.
"[app], которому требуется почти все доступные разрешения пользователя из facebook"
Facebook активно отвлекает внимание на кучу разрешений прямо с самого начала "на всякий случай", потому что они могут понадобиться позже. Нужно только запрашивать расширенное разрешение, когда оно действительно необходимо для действия, которое пользователь только запускал в первый раз.
Кроме того, вы должны просить "читать" и "писать" разрешения отдельно.
Я не знаю, действительно ли эти аспекты вызывают вашу ошибку, но я знаю, что Facebook уже отправил уведомления разработчиков для чтения/записи; хотя сотрудник FB подтвердил, что эти предупреждения можно игнорировать на данный момент, они могут начать применять это в какой-то момент в будущем.