Pytanie Facebook aplikacja internetowa rozszerzone uprawnienia drugi krok nie wyświetlaj


Update2 Ten wpis się starzeje, ale wciąż jest istotny. Poniżej jest sposób, w jaki go rozwiązałem. Oznaczyłem, że inni faceci odpowiadają, ponieważ myślę, że lepiej odpowiada na to pytanie. Wzywam podobną metodę (mam zamiar refactor :)) w accountcontroller. Ciąg powinien być listą ... Myślę, że to rozumiesz.

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

Następnie każda metoda nawiązywania połączenia z Facebookiem jak / me / home za pomocą facebok C # SDK łapie FacebookOAuthException i przekierowuje do metody folling. W ten sposób stosujemy najlepszą praktykę, nie prosząc użytkowników o uprawnienia z góry, ale w razie potrzeby. Ta metoda powinna mieć również adres URL, który również pasuje, ale dopiero co poszliśmy :)

Mam nadzieję, że to pomoże!

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

Aktualizacja: To zachowanie jest spowodowane przez implementację .Net oauth, która ma zakres zakodowany w zamkniętej klasie. Dodano rysunek 4, aby pokazać parametr żądania, w którym brak dodatkowych zakresów oprócz "e-mail" (który jest wysyłany ze wszystkimi żądaniami przez dostawcę .net oauth). Dodanie ", publish_stream" do ciągu zapytania daje mi pożądane zachowanie. Ktoś wie, jak to osiągnąć?

Nie przesyłaj odpowiedzi ani komentarzy na temat najlepszych praktyk na Facebooku lub alternatywnych rozwiązań. Mam alternatywne rozwiązanie, ale chciałbym, aby działało to z domyślnymi parametrami registerfacebookclient. Zaktualizowałem aplikację do oly use publish_stream zgodnie z dwiema odpowiedziami określającymi, o jakie uprawnienia pytam.

rysunek 4Image showing scope parameter in query string

Oryginalne pytanie: Przygotowuję aplikację (C # .Net4.5 MVC4, widoki maszynki), które potrzebują prawie wszystkich dostępnych uprawnień użytkownika z Facebooka. Poniżej możesz zobaczyć przykłady kodu, jak to wszystko ustawiłem.

Problem polega na tym, że po kliknięciu "OK" na rysunku 1, Facebook odsyła mnie do mojej aplikacji. Jak rozumiem, powinien istnieć dodatkowy ekran (rysunek 2) z prośbą o "cięższe" uprawnienia. W tej chwili mam tylko uprawnienia określone na rysunku pierwszym. Ta część działa ...

Rysunek 1 Facebook permissions dialog C#

Rysunek 2 enter image description here

Tak więc, używając podstawowego 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);

W ten sposób radzę sobie z odpowiedzią, ale tutaj Facebook nie monitował użytkownika o rozszerzone uprawnienia, ale tylko w przypadku wiadomości e-mail,

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

Najbliższe odpowiedzi, jakie mogłem znaleźć, to wtyczka wp, która miała ten sam problem. Ich problem został rozwiązany przez ustawienie domeny na localhost. Tak jest skonfigurowana moja aplikacja. ! [wpisz opis obrazu tutaj] [4]


11
2018-05-23 14:44


pochodzenie




Odpowiedzi:


Mam ten sam problem. Tak jak Ty, skonfigurowałem RegisterFacebookClient ze słownikiem, aby zdefiniować zasięg mojej aplikacji, i niestety żądanie nie zawierało zakresu, który skonfigurowałem. Więc znalazłem że. Wygląda na to, że to zadziała, ale to nie wystarczyło. Więc znalazłem to.

Oto, co rozwiązuje moje problemy:

Przede wszystkim dodałem nowego klienta do mojego kodu:

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

Umieściłem go na folderze "infrastruktura" w moim asp.net rozwiązanie z oder rzeczy, następnie zmieniam moją starą konfigurację, w celu korzystania z nowego klienta Facebook, w następujący sposób:

Stary kod:

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

Nowy kod:

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

to jest to! To może ci pomóc, tak jak mi pomogło.


7
2017-09-19 20:55



To jest dziwne. Twoje rozwiązania działają dla mnie, ale tylko lokalne. Po opublikowaniu mojej witryny w chmurze uwierzytelnianie na Facebooku przestaje działać. Moje domeny aplikacji są poprawnie skonfigurowane na Facebooku, ponieważ działa domyślny facebookclient. - Bastaspast
@Bastaspast, problemem na lazurach jest to, że rola adresu URL instancji jest wywołana w jego specyficznym porcie sieciowym, ponieważ właściwość "context.Request.Url.OriginalString" zwraca ją. Więc nie pasuje do adresu URL przesłanego na facebook. Nie znalazłem eleganckiego sposobu rozwiązania tego problemu, ale zrobiłem to: #if !DEBUG rawUrl = rawUrl.Replace(":" + context.Request.Url.Port, ""); #endif Dlatego wszystko będzie działać sprawnie lokalnie i w chmurze. Ale to rozwiązanie pozwala tylko na uruchamianie w DEBUGU w localy, w oder hand, możesz w tym przypadku skomentować ten wiersz. - Matheus Valiente Souza
Dziękuję za wyjaśnienie! - Bastaspast


Czy Twoja aplikacja została zarejestrowana w tych zakresach? Jestem zaznajomiony z Google OAuth, mają osobny zasięg, który jest mapowany na jedno pozwolenie. Twoja aplikacja powinna zostać zarejestrowana dla zakresów, aby uzyskać drugie okno. W przeciwnym razie będziesz mieć dostęp tylko do publicznych informacji, o które prosi twoje pierwsze wyskakujące okienko.


1
2018-05-24 02:21



Nie zarejestrowałem aplikacji z zakresami. Jednak to nie rozwiązało mojego problemu. Dalsze śledzenie mojego problemu Widziałem to zachowanie, ponieważ ekstradata, które jest dostarczane jako zasięg, ustawia tylko wiadomości e-mail po wysłaniu żądania. Problem tkwi gdzieś w korzystaniu z .Net OAuth. - Magnus Karlsson


Po pierwsze, offline_access już nie istnieje, więc z uprawnień, o które prosisz.

"[aplikacja], która potrzebuje prawie wszystkich dostępnych uprawnień użytkownika z Facebooka"

Facebook aktywnie zniechęca do stawiania kuponów uprawnień od samego początku "na wszelki wypadek", ponieważ mogą być potrzebne później. Należy poprosić o zezwolenie rozszerzone tylko wtedy, gdy jest rzeczywiście potrzebne do działania, które użytkownik uruchomił po raz pierwszy.

Powinieneś też poprosić o pozwolenie "czytaj" i "pisz" oddzielnie.

Nie wiem, czy te aspekty rzeczywiście powodują Twój błąd - ale wiem, że Facebook już wysyłał powiadomienia programistów o rzeczach do odczytu / zapisu; chociaż pracownik FB potwierdził, że te ostrzeżenia można zignorować Na razie, mogą zacząć egzekwowanie to w pewnym momencie w przyszłości.


1
2018-05-24 08:29



Dzięki za twoją radę CBroe. Buduję aplikację z interfejsem dla osób niewidomych i głuchych. Wymaga to użycia jak najmniej interakcji i pop-upów. - Magnus Karlsson
Uważam, że OP jest poprawny, a jego zakresy giną gdzieś w SDK, a nie w rzeczywistym wywołaniu Facebooka - Igy
Magnus Karlsson Mam również do czynienia z tym samym problemem, czy otrzymałeś jakieś rozwiązanie? - Isaiyavan Babu Karan
@IsaiyavanBabuKaran Tak, stworzyłem metodę wysyłania żądań na Facebook, z których mogę korzystać w każdym wyjątku FacebookOAuthException. Działa jak marzenie. Zaktualizuję som kodem jutro. Nawiasem mówiąc, myślę, że kod Matheus wygląda świetnie, gdy potrzebujesz uprawnień z góry! Aktualizuję to teraz :) - Magnus Karlsson