Best Practices for Dual-Use iFrame + External Authentication for Facebook-Enabled Application

Well, if cookies are no, no, then I need a little guide on the best way to implement the applications that I create.

The scenario is that I am trying to create a single ASP.NET MVC application that can authenticate a user regardless of whether the user visits the site directly or via iFrame on Facebook. There are separate actions (on separate controllers, in fact) for entering the application, depending on whether the user logs in via Facebook or not, but there are also places in the Facebook application where I open a new window for “advanced” functionality in other areas applications that cannot really work well in iFrame. It should smoothly transition. It currently works pretty well with cookies, but I have come from several sources that this is not very good for iFrame applications. However, I'm not sure what that means.

Without cookies, can you somehow access server access to the authentication token? If not, what is the “right” way to handle this. Do I need to resort to manually analyze the token using the JS API and send an AJAX notification to the server that the user is authenticated and creates a token for the forms? Will the CanvasAuthorize attribute work without cookies? Currently, I have added code to the FormsAuthentication_OnAuthenticate event in Global.asax to create an auth token for forms if the user is logged in via Facebook (and correctly connected to the real user in the external application) as follows:

protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs args)
{
    if (FormsAuthentication.CookiesSupported)
    {
        if (Request.Cookies[FormsAuthentication.FormsCookieName] == null)
        {
            // Attempt to authenticate using Facebook
            try
            {
                FacebookApp fbApp = new FacebookApp();
                if (fbApp.Session != null)
                {
                    dynamic me = fbApp.Get("me");
                    String fbID = "" + me.id;
                    MembershipUser mUser = AppMembershipProvider.GetUserByFacebookID(fbID);
                    if (mUser != null)
                    {
                        FormsAuthentication.SetAuthCookie(mUser.UserName, false);
                        AppMembershipProvider.UpdateLastLogin(mUser.UserName);
                        Session["FacebookLogin"] = true;
                    }
                }
            }
            catch (Exception e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
            }
        }
    }
    else
    {
        throw new HttpException("Cookieless Forms Authentication is not " +
                                "supported for this application.");
    }
}

Do I need to change this?

Sorry if this is basic knowledge, but I'm confused about how best to implement this. Thank!

+3
2

cookie. , , cookie iFrames, . IE . , cookie iframes:

P3P: CP="CAO PSA OUR"

cookie iframe - Safari. - Safari, cookie iframes. , cookie iframe.

iframe, cookie. , , iframe. .

iframe - . , facebook URL-, URL- iframe. . Facebook # SDK , .. , . URL- iframe facebook, - http://www.mysite.com/page/?signed_request= {blahblahblah}.

, , , iframe, ? signed_request URL.

. -, CanvasRedirect. System.Web.Mvc.Controller Facebook.Web.Mvc. canvas javascript URL-. , Facebook signed_request URL- iframe. , iframe, .

? signed_request URL- . - :

public ActionResult Something() {  return RedirectToAction ( "something", new {signed_request = Request.Querystring [ "signed_requets" ]); }

, - , .

, , - , , , , , . , - . nathan@ntotten.com @ntotten .

+3

. , , :

  • cookie #, JavaScript SDK.
  • actionfilter, FacebookAuthorizeAttribute HandleUnauthorizedRequest CanvasAuthorizeAttribute.
  • signed_request ( ) auth_token (connect app) querystring .
  • oauth , .

- , , oauth . Facebook, signed_request . connect, , FacebookApp.

    public class FbAuthenticateAttribute : FacebookAuthorizeAttribute
    {
        private FacebookApp _fbApp;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            var accessToken = filterContext.HttpContext.Request.Params["access_token"];
            if (FacebookApp.AccessToken != accessToken && !string.IsNullOrEmpty(accessToken))
            {
                _fbApp = new FacebookApp(accessToken);
            }
            else
            {
                _fbApp = FacebookApp;
            }
            filterContext.Controller.ViewBag.Context = GetContext().ToString();
            filterContext.RequestContext.HttpContext.Response.AppendHeader("p3p", "CP=\"CAO PSA OUR\"");
            try
            {
                dynamic user = _fbApp.Get("me");
                var signedRequest = filterContext.HttpContext.Request.Params["signed_request"];
                filterContext.Controller.ViewBag.QueryString = string.IsNullOrEmpty(signedRequest)
                                          ? "?access_token=" + _fbApp.AccessToken
                                          : "?signed_request=" + signedRequest;
            }
            catch (Exception ex)
            {
                string url = GetRedirectUrl(filterContext);
                filterContext.Result = new RedirectResult(url);
            }
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            string url = GetRedirectUrl(filterContext);
            filterContext.Result = new RedirectResult(url);
        }

        private string GetRedirectUrl(ControllerContext filterContext)
        {
            return new UrlHelper(filterContext.RequestContext).Action(GetRedirectAction(GetContext()), "Authentication");
        }

        private Enums.AppContext GetContext()
        {
            //Note: can't rely on this alone - find something more robust
            return FacebookApp.SignedRequest == null ? Enums.AppContext.FBWeb : Enums.AppContext.FBApp;
        }

        private string GetRedirectAction(Enums.AppContext context)
        {
            return context == Enums.AppContext.FBWeb ? "ConnectAuthenticate" : "Authenticate";
        }
    }

, , .

+1

Source: https://habr.com/ru/post/1782237/


All Articles