Facebook Callback appends '#_=_' to Return URL

前端 未结 23 1737
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 14:56

Facebook callback has started appending #_=_ hash underscore to the Return URL

Does anyone know why? What is the solution?

相关标签:
23条回答
  • 2020-11-22 15:07

    TL;DR

    if (window.location.hash === "#_=_"){
        history.replaceState 
            ? history.replaceState(null, null, window.location.href.split("#")[0])
            : window.location.hash = "";
    }
    

    Full version with step by step instructions

    // Test for the ugliness.
    if (window.location.hash === "#_=_"){
    
        // Check if the browser supports history.replaceState.
        if (history.replaceState) {
    
            // Keep the exact URL up to the hash.
            var cleanHref = window.location.href.split("#")[0];
    
            // Replace the URL in the address bar without messing with the back button.
            history.replaceState(null, null, cleanHref);
    
        } else {
    
            // Well, you're on an old browser, we can get rid of the _=_ but not the #.
            window.location.hash = "";
    
        }
    
    }
    

    Step by step:

    1. We'll only get into the code block if the fragment is #_=_.
    2. Check if the browser supports the HTML5 window.replaceState method.
      1. Clean the URL by splitting on # and taking only the first part.
      2. Tell history to replace the current page state with the clean URL. This modifies the current history entry instead of creating a new one. What this means is the back and forward buttons will work just the way you want. ;-)
    3. If the browser does not support the awesome HTML 5 history methods then just clean up the URL as best you can by setting the hash to empty string. This is a poor fallback because it still leaves a trailing hash (example.com/#) and also it adds a history entry, so the back button will take you back to #_-_.

    Learn more about history.replaceState.

    Learn more about window.location.

    0 讨论(0)
  • 2020-11-22 15:07

    With angular and angular ui router, you can fix this

        app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
    
          // Make a trailing slash optional for all routes
          // - Note: You'll need to specify all urls with a trailing slash if you use this method.
          $urlRouterProvider.rule(function ($injector, $location) {
            /***
            Angular misbehaves when the URL contains a "#_=_" hash.
    
            From Facebook:
              Change in Session Redirect Behavior
              This week, we started adding a fragment #_=_ to the redirect_uri when this field is left blank.
              Please ensure that your app can handle this behavior.
    
            Fix:
              http://stackoverflow.com/questions/7131909/facebook-callback-appends-to-return-url#answer-7297873
            ***/
            if ($location.hash() === '_=_'){
              $location.hash(null);
            }
    
            var path = $location.url();
    
            // check to see if the path already has a slash where it should be
            if (path[path.length - 1] === '/' || path.indexOf('/?') > -1) {
              return;
            }
            else if (path.indexOf('?') > -1) {
              $location.replace().path(path.replace('?', '/?'));
            }
            else {
              $location.replace().path(path + '/');
            }
          });
    
          // etc ...
        });
    });
    
    0 讨论(0)
  • 2020-11-22 15:08

    This was implemented by Facebook by design for security reasons. Here's the explanation from Eric Osgood, a Facebook Team member:

    This has been marked as 'by design' because it prevents a potential security vulnerability.

    Some browsers will append the hash fragment from a URL to the end of a new URL to which they have been redirected (if that new URL does not itself have a hash fragment).

    For example if example1.com returns a redirect to example2.com, then a browser going to example1.com#abc will go to example2.com#abc, and the hash fragment content from example1.com would be accessible to a script on example2.com.

    Since it is possible to have one auth flow redirect to another, it would be possible to have sensitive auth data from one app accessible to another.

    This is mitigated by appending a new hash fragment to the redirect URL to prevent this browser behavior.

    If the aesthetics, or client-side behavior, of the resulting URL are of concern, it would be possible to use window.location.hash (or even a server-side redirect of your own) to remove the offending characters.

    Source: https://developers.facebook.com/bugs/318390728250352/

    0 讨论(0)
  • 2020-11-22 15:11

    For PHP SDK users

    I fixed the problem simply by removing the extra part before forwarding.

     $loginURL = $helper->getLoginUrl($redirectURL, $fbPermissions);
     $loginURL = str_replace("#_=_", "", $loginURL);
     header("Location: " . $loginURL);
    
    0 讨论(0)
  • 2020-11-22 15:14

    via Facebook's Platform Updates:

    Change in Session Redirect Behavior

    This week, we started adding a fragment #____=____ to the redirect_uri when this field is left blank. Please ensure that your app can handle this behavior.

    To prevent this, set the redirect_uri in your login url request like so: (using Facebook php-sdk)

    $facebook->getLoginUrl(array('redirect_uri' => $_SERVER['SCRIPT_URI'],'scope' => 'user_about_me'));
    

    UPDATE

    The above is exactly as the documentation says to fix this. However, Facebook's documented solution does not work. Please consider leaving a comment on the Facebook Platform Updates blog post and follow this bug to get a better answer. Until then, add the following to your head tag to resolve this issue:

    <script type="text/javascript">
        if (window.location.hash && window.location.hash == '#_=_') {
            window.location.hash = '';
        }
    </script>
    

    Or a more detailed alternative (thanks niftylettuce):

    <script type="text/javascript">
        if (window.location.hash && window.location.hash == '#_=_') {
            if (window.history && history.pushState) {
                window.history.pushState("", document.title, window.location.pathname);
            } else {
                // Prevent scrolling by storing the page's current scroll offset
                var scroll = {
                    top: document.body.scrollTop,
                    left: document.body.scrollLeft
                };
                window.location.hash = '';
                // Restore the scroll offset, should be flicker free
                document.body.scrollTop = scroll.top;
                document.body.scrollLeft = scroll.left;
            }
        }
    </script>
    
    0 讨论(0)
  • 2020-11-22 15:14

    If you're using vue-router, you can append to the list of routes:

    {
      path: '/_=_',
      redirect: '/', // <-- or other default route
    },
    
    0 讨论(0)
提交回复
热议问题