11

When dealing with OAuth from the server, such as Twitter and Facebook, you most likely will redirect the user to an URL asking for app permission. Usually, after clicking a link, you send the request to the server, via AJAX, and then return the authorization URL.

But when you try to use window.open when the answer is received, your browser blocks the popup, making it useless. Of course, you can just redirect the user to the new URL, but that corrupts the user experience, plus it's annoying. You can't use IFRAMES, but they are not allowed (because you can't see the location bar).

So how to do it?

pocesar
  • 6,860
  • 6
  • 56
  • 88

2 Answers2

28

The answer is quite simple, and works cross browser without any issues. When doing the AJAX call (I'll be using jQuery in this example), just do the following. Suppose we have a form with two buttons, Login with Twitter and Login with Facebook.

<button type="submit" class="login" value="facebook" name="type">Login with Facebook</button>
<button type="submit" class="login" value="twitter" name="type">Login with Twitter</button>

Then the Javascript code where the magic happens

$(function () {
    var
        $login = $('.login'),
        authWindow;

    $login.on('click', function (e) {
        e.preventDefault();
        /* We pre-open the popup in the submit, since it was generated from a "click" event, so no popup block happens */
        authWindow = window.open('about:blank', '', 'left=20,top=20,width=400,height=300,toolbar=0,resizable=1');
        /* do the AJAX call requesting for the authorize URL */

        $.ajax({
            url: '/echo/json/',
            type: "POST",
            data: {"json": JSON.stringify({"url": 'http://' + e.target.value + '.com'})}
            /*Since it's a jsfiddle, the echo is only for demo purposes */
        })
        .done(function (data) {
            /* This is where the magic happens, we simply redirec the popup to the new authorize URL that we received from the server */
            authWindow.location.replace(data.url);
        })
        .always(function () {
            /* You can poll if the window got closed here, and so a refresh on the main page, or another AJAX call for example */
        });
    });
});

Here is the POC in JSFiddle http://jsfiddle.net/CNCgG/

This is simple and effective :)

pocesar
  • 6,860
  • 6
  • 56
  • 88
  • This is a very good work around but if you are using FB.ui() I don't think it will work. – deathemperor May 13 '13 at 07:10
  • EDIT: my bad, I misread your phrase. Yes, I think using FB.ui it won't work, because it only works if you can redirect the dialog to a new URL. If the FB.ui have a server-side counterpart, then it will work. – pocesar May 13 '13 at 14:32
  • 1
    this is a fantastically simple and effective workaround making sure ajax-opened popups get focus. thanks pocesar! – designosis Oct 09 '13 at 08:42
  • 1
    unfortunately doesn't work on iOS so not really a good solution – Thomas Heymann Feb 17 '14 at 18:14
  • @ThomasHeymann thanks for pointing out, maybe another step in the code to detect iOS and instead of opening a window, open the FB address directly (and do a window.location.replace() instead of authWindow.location.replace()) – pocesar Feb 18 '14 at 19:39
  • Nice work, this helped get rid of the popup, assigning the popup to a window and then replacing its location, it also allows me to still access the parent variables. thanks! – Tony Aug 11 '14 at 17:14
8

Try adding async: false. It should be working

$('#myButton').click(function() {
$.ajax({
    type: 'POST',
    async: false,
    url: '/echo/json/',
    data: {'json': JSON.stringify({
        url:'http://google.com'})},
    success: function(data) {
        window.open(data.url,'_blank');
    }
});
});
rajesh
  • 382
  • 4
  • 5