Pop-up авторизации ВКонтакте для протокола OAuth 2.0

    На данный момент существует 2 возможности авторизации в социальной сети «В Контакте»:
    • Open API
    • OAuth 2.0

    Первый устаревший, а второй — модный, прогрессивный и стандартизированный.

    Но, однако, переходя на новый способ, я заметил, что нигде в документации «В Контакте» не говорится, как сделать авторизационное окошко небольшим попапом.

    На странице "Авторизация сайтов" сказано: «Для начала процесса авторизации необходимо создать окно браузера и открыть в нём диалог авторизации». Но ни слова не сказано о том, как создать такое окно.

    У Facebook есть свой метод JavaScript FB.login для этой цели. У OpenAPI «В Контакте» есть VK.Auth.login. А для OAuth 2 «В Контакте» нет ничего.

    «Ну что же, challenge accepted», — сказал я себе. И решил написать свой метод.

    Вот что у меня получилось:
    function vk_popup(options)<br>{<br>  var<br>    screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,<br>    screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,<br>    outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.body.clientWidth,<br>    outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.body.clientHeight - 22),<br>    width = options.width,<br>    height = options.height,<br>    left = parseInt(screenX + ((outerWidth - width) / 2), 10),<br>    top = parseInt(screenY + ((outerHeight - height) / 2.5), 10),<br>    features = (<br>      'width=' + width +<br>        ',height=' + height +<br>        ',left=' + left +<br>        ',top=' + top<br>      );<br>  return window.open(options.url, 'vk_oauth', features);<br>}<br><br>function doLogin() {<br>  var win;<br>  var redirect_uri = 'http://MY_APP/vk_auth/';<br>  var uri_regex = new RegExp(redirect_uri);<br>  var url = 'http://oauth.vkontakte.ru/authorize?client_id=CLIENT_ID&display=popup&redirect_uri=' + redirect_uri;<br>  win = vk_popup({<br>    width:620,<br>    height:370,<br>    url:url<br>  });<br><br>  var watch_timer = setInterval(function () {<br>    try {<br>      if (uri_regex.test(win.location)) {<br>        clearInterval(watch_timer);<br><br>        setTimeout(function () {<br>          win.close();<br>          document.location.reload();<br>        }, 500);<br>      }<br>    } catch (e) {<br><br>    }<br>  }, 100);<br>}<br><br>* This source code was highlighted with Source Code Highlighter.

    Сначала создаю окно с диалогом авторизации, которое выглядит в точности, как аналогичное для OpenAPI.

    image

    Затем таймером отслеживаю изменение текущего URL в этом окошке, чтобы определить, когда «В Контакте» перенаправит на мой URL авторизации. И жду 500 мс, чтобы сервер уж точно успел обработать запрос. После этого перезагружаю основное окно своего сайта.

    Обёртывать обращение к win.location в try {} catch(e) {} необходимо, потому что политика кросс-доменности не позволяет узнавать URL'ы окон других сайтов.

    Хотелось также сделать это через какой-нибудь Observer, который бы наблюдал за изменением win.location и оповещал о событии, но подходящих примеров я не нашёл и JavaScript не моя основная специализация, поэтому остановился на реализации таймером. Буду благодарен, если кто-нибудь подскажет, как перевести на события.

    Надеюсь, эта заметка будет полезной людям.
    Поделиться публикацией

    Комментарии 8

      0
      Спасибо за код, но мне кажется, что если пользователь просто закроет поп-ап кно, то у вас свалится эксепшн, который словится и ничего не произойдет, так как у вас в catch пусто. Возможно стоит обработать эту ситуацию тоже?
        0
        Да, можно проверять объект win на существование. Хотя и без этого не будет ничего страшного. Просто останется лишний таймер на странице до перехода на другой URL.
        –3
        Может OpenID, а не Open API?
          +1
          Нет, Open API. Это их собственное изобретение.
            0
            ОМГ, какой изврат
        • НЛО прилетело и опубликовало эту надпись здесь
            0
            На самом деле она происходит только по URL их OAuth сервера, но не по протоколу OAuth 2.0.
            0
            И жду 500 мс, чтобы сервер уж точно успел обработать запрос.

            :-) У нас для такого быдло-кода даже специальный термин был «Синхронизация на sleep'ах», на продакшине я бы посоветовал такого избегать…

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое