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

в 18:53, , рубрики: android, Facebook, javascript, phonegap, Вконтакте, мобильное приложение, Смартфоны и коммуникаторы, хабрахабр, метки: , , , , ,

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 вида (на который надо перенаправлять пользователя)

https://oauth.vk.com/authorize?client_id=ID_приложеия&scope=права_доступа&redirect_uri=http://oauth.vk.com/blank.html&display=touch&response_type=token

https://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);

Не уверен что кому то это пригодится, но вдруг. К тому же не факт что доведу до ума свою идею, а терять куски кода будет жалко.

Автор: SovGVD

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js