Авторизация в PhoneGap приложении через Facebook, Vkontakte и Habrahabr

    PhoneGapПривет, хабраюзер. Недавно я написал статейку о своем видение интерфейса операционной системы мобильного телефона, но она мало кого заинтересовала и я решил попробовать написать приложение, которое бы частично воплотила идею в реальность, а так как кроме веб языков я мало что знаю, то решил писать приложения на html5+js+css с помощью PhoneGap. И начал с авторизации и получения токенов или кук с различных источников. За день неспешного кодинга получилось сделать плагины авторизации для Facebook, Вконтакте и Хабра (большая часть времени ушла на гугление и чтение документации к API).

    Предполагается что вы уже установили Android SDK (для разработки под эту операционную систему), Eclipse и PhoneGap и знаете как начать делать приложение. Если нет, то начинать надо отсюда.

    При написании плагинов потребуется небольшой дополнительный JS скрипт, который будет «распарсивать» ссылки и куки.
    var url_parser={
    		get_args: function (s) {
    			var tmp=new Array();
    			s=(s.toString()).split('&');
    			for (var i in s) {
    				i=s[i].split("=");
    				tmp[(i[0])]=i[1];
    			}
    			return tmp;
    		},
    		get_args_cookie: function (s) {
    			var tmp=new Array();
    			s=(s.toString()).split('; ');
    			for (var i in s) {
    				i=s[i].split("=");
    				tmp[(i[0])]=i[1];
    			}
    			return tmp;		
    		}
    };

    Я специально разделил код для ссылок и кук (вдруг чего поменяется), хотя различия в них в данный момент минимальны. get_args принимает строку вида param1=hello&param2=world, а get_args_cookie принимает то, что отдает document.cookie, т.е. строку вида param1=hi; param2=habr. На выходе получаем массив вида ключ=>значение.

    Вконтакте и Facebook


    Вконтакте и Facebook используют похожие способы авторизации, а именно URL вида (на который надо перенаправлять пользователя)
    oauth.vk.com/authorize?client_id=ID_приложеия&scope=права_доступа&redirect_uri=http://oauth.vk.com/blank.html&display=touch&response_type=token

    www.facebook.com/dialog/oauth?client_id=ID_приложения&scope=права_доступа&redirect_uri=http://sovgvd.info/blank.html&response_type=token

    Вконтакт, в отличае от Facebook для JS приложений предлагает свой адрес, в то время как для facebook пришлось создать пустую страничку на давно заброшенном личном блоге (хотя наверное можно и вконтактовой пользоваться).
    Ответы после успешной авторизации так же похожи и после якоря (#) имеют вид:
    access_token=токен&expires_in=время_жизни_токена

    А Вконтакт добавляет еще &user_id=ID_пользователя.

    Для запроса страничек этих социальных сетей используется расширение InAppBrowser, запускающее браузер внтури вашего почти браузерного приложения, в открытую страницу которого можно внедрить JS или CSS, а так же прочитать заголовок по завершению загрузки страницы.

    Зная всё это получились 2 очень похожих скрипта с одинаковыми методами:
    Vkontakte
    var plugin_vk = {
    	wwwref: false,
    	plugin_perms: "friends,wall,photos,messages,wall,offline,notes",
    	
    	auth: function (force) {
    		if (!window.localStorage.getItem("plugin_vk_token") || force || window.localStorage.getItem("plugin_vk_perms")!=plugin_vk.plugin_perms) {
    			var authURL="https://oauth.vk.com/authorize?client_id=12345&scope="+this.plugin_perms+"&redirect_uri=http://oauth.vk.com/blank.html&display=touch&response_type=token";
    			this.wwwref = window.open(encodeURI(authURL), '_blank', 'location=no');
    			this.wwwref.addEventListener('loadstop', this.auth_event_url);
    		}
    	},
    	auth_event_url: function (event) {
    		var tmp=(event.url).split("#");
    		if (tmp[0]=='https://oauth.vk.com/blank.html' || tmp[0]=='http://oauth.vk.com/blank.html') {
    			plugin_vk.wwwref.close();
    			var tmp=url_parser.get_args(tmp[1]);
    			window.localStorage.setItem("plugin_vk_token", tmp['access_token']);
    			window.localStorage.setItem("plugin_vk_user_id", tmp['user_id']);
    			window.localStorage.setItem("plugin_fb_exp", tmp['expires_in']);
    			window.localStorage.setItem("plugin_vk_perms", plugin_vk.plugin_perms);
    		}
    	}
    };

    Facebook
    var plugin_fb = {
    	wwwref: false,
    	plugin_perms: "read_stream,manage_friendlists,read_friendlists,read_mailbox,publish_actions,offline_access",
    	
    	auth: function (force) {
    		if (!window.localStorage.getItem("plugin_fb_token") || force || window.localStorage.getItem("plugin_fb_perms")!=plugin_fb.plugin_perms) {
    			var authURL="https://www.facebook.com/dialog/oauth?client_id=123456&scope="+this.plugin_perms+"&redirect_uri=http://sovgvd.info/blank.html&response_type=token";
    			this.wwwref = window.open(encodeURI(authURL), '_blank', 'location=no');
    			this.wwwref.addEventListener('loadstop', this.auth_event_url);
    		}
    	},
    	auth_event_url: function (event) {
    		var tmp=(event.url).split("#");
    		if (tmp[0]=='https://sovgvd.info/blank.html' || tmp[0]=='http://sovgvd.info/blank.html') {
    			plugin_fb.wwwref.close();
    			var tmp=url_parser.get_args(tmp[1]);
    			window.localStorage.setItem("plugin_fb_token", tmp['access_token']);
    			window.localStorage.setItem("plugin_fb_exp", tmp['expires_in']);
    			window.localStorage.setItem("plugin_fb_perms", plugin_fb.plugin_perms);
    		}
    
    	}
    };


    Для авторизации в теле основного JavaScript запускаем plugin_vk.auth(false); или plugin_fb.auth(false);. При этом, если уже была совершена авторизация, то ничего не произойдет, если изменился список прав доступа, не происходила авторизация или запущена принудительная авторизация (plugin_vk.auth(true); или plugin_fb.auth(true);), то поизойдет перенаправление на окно логина одной из социальных сетей.
    Небольшое замечания
    Хотя я и сохраняю значения истечения срока действия, но нигде его не использую, а оно наверняка пригодится ;)


    Habrahabr


    Любимый нами хабр не имеет API для авторизации (как и для всего остального), поэтому будем ловить куки, для этого понадобится возможность InAppBrowser расширения по внедрению JavaScript кода — executeScript. Внедрить можно как кусочек кода, так и целый JS файл и получить в callback функцию результат выполнения последней комманды (не путать с return). Т.е. код внедрения и получения кук будет выглядить примерно так:
            plugin_habr.wwwref.executeScript({
                code: "document.cookie;"
            }, function(arg) {
            	plugin_habr.auth_event_url(arg);
            });

    А весь код плагина авторизации для Хабра вот так:
    Habrahabr
    var plugin_habr = {
    	wwwref: false,
    
    	auth: function (force) {
    		if (!window.localStorage.getItem("plugin_habr_PHPSESSID") || force) {
    			var authURL="http://habrahabr.ru/login/";
    			this.wwwref = window.open(encodeURI(authURL), '_blank', 'location=yes');
    			this.wwwref.addEventListener('loadstop', this.auth_jsinjection);
    		}
    	},
    	auth_event_url: function (url) {
    		var tmp=url_parser.get_args_cookie(url);
    		if (tmp['PHPSESSID'] && tmp['hsec_id']) {
    			plugin_habr.wwwref.close();
    			window.localStorage.setItem("plugin_habra_PHPSESSID", tmp['PHPSESSID']);
    			window.localStorage.setItem("plugin_habra_hsec_id", tmp['hsec_id']);
    		}
    	},
    	auth_jsinjection: function () {
    		plugin_habr.wwwref.executeScript({
                code: "document.cookie;"
            }, function(arg) {
            	plugin_habr.auth_event_url(arg);
            });
    	}
    }

    Вызов авторизации осуществляется аналогично прошлым плагинам plugin_habr.auth(false);

    Не уверен что кому то это пригодится, но вдруг. К тому же не факт что доведу до ума свою идею, а терять куски кода будет жалко.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 12

      +7
      >так как кроме веб языков я мало что знаю, то решил писать приложения на html5+js+css с помощью PhoneGap

      Привет.

      Я тоже на это купился, но как оказалось более торомозной фигни чем PhoneGap не найдешь.

      Возможно вам уже не хочется расставаться с вашими наработками, но мой совет, бросайте это дело, PhoneGap годится только для прототипов.
        0
        Расставаться то не жалко — это работа одно дня. Другое дело что на изучение Java и попытку написания Hello world у меня бы ушло на много больше времени, а это всего лишь прототип и just4fun.
        По поводу производительности не могу пока ничего сказать, но в моем понимает PhoneGap не более чем браузер, в котором к JS движку прилепили несколько плагинов взаимодействися с операционкой. К примеру на прошлой работе я писал клиентскую часть на JS, которая со всякими жестами, прокрутками и встроенным видео не тормозила на FullHD (всё нативно+css хаки, варианты фреймворков отпали сразу же, как невероятно тормозные костыли), надеюсь навыки и любимые технологии не подведут.
          +1
          Тормознутость PhoneGap — это от лени и использования стандартных интерфейсных либ типа jQuery UI. Имею опыт написания таких смартфонных приложений, знаю о чем говорю. Можете сами попробовать сделать страничку на jQuery UI простую с длинным списком экрана на два. Будет отлично тормозить на старых телефонах с андроидами 2.2-2.3. Потом сделать простой HTML-список на те же два экрана. Здорово удивитесь вроде бы ниоткуда взявшейся скоростью. Дальше — дело усидчивости. Выяснить, что именно морозит — не так сложно.

          А сам PhoneGap морозным назвать ну никак нельзя. Ведь это довольно тонкая нативная прослойка между WebKit и смартфоновской ОС. Да, программить под него не так просто, как кажется изначально. Но у него довольно много плюсов, чтобы быть востребованным.
            0
            Раз уж у вас есть опыт, у меня пару вопросов вылезло:
            1) насколько секьюрно хранить внтури пакета пароли/сикреты от проектов?
            2) не понял как компилить под iOS, не имея xcode (которому еще и макось хочется) или это возможно только через сервер phonegap?
              +1
              1) Совершенно не секурно. Как IPA-пакеты для iPhone, так и APK для Android на деле — простые ZIP-архивы. То есть Вы легко можете распаковать любое приложение и поглядеть на файлы внутри. В случае с PhoneGap-приложениями все Ваше HTML-ное добро будет лежать там в отдельной папке в совершенно голом и незащищенном виде.

              2) Да, нужен либо Mac, либо нужно пользоваться фермой Build PhoneGap. Ферма бесплатна для одного приложения и удобна, но имеет несколько явных и неявных недостатков. Она не позволяет собирать приложения с использованием пользовательски плагинов. А такие пользовательские плагины приходится писать почти в каждом серьезном приложении, чтобы обходить некоторые неожиданные ограничения платформы (например в одном андроид приложении оказалось, что я не могу пережать на смарте фотку перед отправкой на сервер штатными возможностями на старых версиях ос 2.2-2.3). Из неявных недостатков — то, что ферма на практике существо довольно не стабильное и рассчитывать на нее в реальной работе не стоит. Бывает по нескольку дней проблемы со сборкой.

              Вместо мака можете помучаться с хакинтошем, если просто для самообразования ковыряетесь.
                0
                Build PhoneGap так же не поддерживает некоторые фичи, которые поддерживает даже нативный конфиг. Например, costum protocol. При этом для сборки сертификат iOS всё равно нужен (правда в новой версии билдера они разрешают использовать их, дефолтный).
                0
                Вообще для андроида разрабатывать на PhoneGap гораздо более комфортно, чем для iPhone ) Потому что заморочек с закрытостью Apple там нет…
            0
            Я надеюсь, что увижу статью на хабре, опровергающую это мнение.

            UPD промазал, это для коммента 6287717
              0
              Не увидите. PhoneGap очень медленный и ограниченный.
                0
                От меня такая статья будет явно не скоро, подобным фаном время есть заниматься только по выходным.
                  0
                  Попробовал написать свой скролинг, на мелком старом телефоне вполне не плохо крутить список из 400 элементов с картинками, а вот на планшетнике с бОльшим экраном заметно тормозит, особенно кинетический вариант (надо наверное его с костыля на webkit-transition переделать или попробовать заюзать чужую библиотеку).
                  www.youtube.com/watch?v=U3MtkFsZXu8
                  0
                  Уже месяца 4 InAppBrowser не расширение, а часть самого PhoneGap.

                  Only users with full accounts can post comments. Log in, please.