Domanda

Sto sviluppando un'app Facebook, e voglio solo consentire l'accesso a alcune opinioni se il visitatore è autorizzato tramite Facebook. Questo dovrebbe essere un compito piuttosto semplice, e ho pensato che sia stato, finché non l'ho provato in IE. Il codice seguente funziona bene in Chrome e Safari. Voglio usare l'autenticazione dei moduli, e quindi ho impostato

<forms loginUrl="~/Account/Login" timeout="2880" />
.

in web.config. Ciò dirigerà il visitatore al seguente AzioneResult quando si entra nella mia app:

    public ActionResult Login(string returnUrl)
    {
        ManagerGame2.Utilities.StaticDataContent.InitStaticData();

        var oAuthClient = new FacebookOAuthClient();
        oAuthClient.AppId = FacebookApplication.Current.AppId;
        oAuthClient.RedirectUri = new Uri(redirectUrl);
        var loginUri = oAuthClient.GetLoginUrl(new Dictionary<string, object> { { "state", returnUrl } });
        return Redirect(loginUri.AbsoluteUri);
    }
.

Quindi l'utente viene reindirizzato a una pagina Facebook e un token di accesso viene rimesso nel mio Opauth ActionResult:

public ActionResult OAuth(string code, string state)
    {
        FacebookOAuthResult oauthResult;
        if (FacebookOAuthResult.TryParse(Request.Url, out oauthResult))
        {
            if (oauthResult.IsSuccess)
            {
                var oAuthClient = new FacebookOAuthClient();
                oAuthClient.AppId = FacebookApplication.Current.AppId;
                oAuthClient.AppSecret = FacebookApplication.Current.AppSecret;
                oAuthClient.RedirectUri = new Uri(redirectUrl);
                dynamic tokenResult = oAuthClient.ExchangeCodeForAccessToken(code);
                string accessToken = tokenResult.access_token;

                DateTime expiresOn = DateTime.MaxValue;

                if (tokenResult.ContainsKey("expires"))
                {
                    DateTimeConvertor.FromUnixTime(tokenResult.expires);
                }

                FacebookClient fbClient = new FacebookClient(accessToken);
                dynamic me = fbClient.Get("me?fields=id,name");
                long facebookID = Convert.ToInt64(me.id);


                Account acc = (from x in db.Account.OfType<Account>() where x.FaceBookID == facebookID select x).FirstOrDefault();
                if (acc == null)
                {
                    acc = CreateAccount(me);
                }
                acc.LatestLogin = DateTime.Now;
                db.Entry(acc).State = EntityState.Modified;
                db.SaveChanges();

                MemoryUserStore.CurrentAccount = acc;

                UserRoleProvider usp = new UserRoleProvider();
                usp.GetRolesForUser(acc.AccountID.ToString());
                FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);

                if (Url.IsLocalUrl(state))
                {
                    return Redirect(state);
                }
                return RedirectToAction("Details", "Account", new { id = acc.AccountID });
            }
        }

        return RedirectToAction("Index", "Account");
    }
.

Quello che sto cercando di fare qui, è quello di verificare prima se il token ritorni dal reindirizzamento è valido. Se lo è, quindi tiro alcuni dati sul visitatore, come FacebookID e nome. Allora l'abbinilo con il mio database, per vedere se l'utente esiste già e, se no, ne creo uno. Assegnando anche un ruolo per l'utente nel mio fornitore di ruoli personalizzato, ma ho avuto il problema del ciclo infinito prima di questo. Quindi ho impostato

FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);
.

E presumo che questo sia il nucleo di tenere traccia di Weter un visitatore è autorizzato o meno. Per quanto ne capisco, quando il visitatore sta cercando di chiamare un actionresult che richiede [Autorizzazione], il sistema controllerà questo cookie.

Beh, potrebbe qualcuno per favore chiarire perché il codice sopra sta lavorando in Chrome / Safari, ma continua a looping attraverso il login e poi OAuth infinitamente in IE?

La mia app sta usando MVC 3, codice EF First e Facebook C # SDK 5.0.25

È stato utile?

Soluzione

Okay, so i figured out that the problem was triggered by the [Authorize] annotation, as expected. The Facebook SDK has a [CanvasAuthorize] annotation, and when i switch to using this, IE works fine and does not login forever.

Before this, i tried using cookieless authentication, but IE still didn't want to play along.

As far as i have figured out, the problem occurs because Facebook apps are inside an IFrame. This supposedly screws something up with cookies and trust. If someone knows why this is, i would appreciate to hear about it.

Also, if anyone knows how to use and maintain roles, easily, with this [CanvasAuthorize], i would be glad to know.

Altri suggerimenti

I know this seems obvious but are you sure cookies aren't disabled in IE? There is an option to disable cookies in developer tools.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top