Аутентификация на внешних сервисах посредством OAuth

03.04.19

Администрирование - Информационная безопасность

Пример подключения к сервисам Google из 1С с помощью протокола OAuth и получения данных с внешнего сервиса.

Скачать исходный код

Наименование Файл Версия Размер
Аутентификация на внешних сервисах посредством OAuth:
.epf 13,71Kb
76
.epf 1.0 13,71Kb 76 Скачать

 В данной  статье на примере подключения к сервисам Google я продемонстрирую реализацию подключения к сервисам Google при помощи аутентификации по протоколу OAuth 2.0 на языке программирования 1С.  В статье будет показана реализация подключения к сервису календарей Google с помощью авторизации по протоколу OAuth 2.0. Получение списка календарей и загрузка событий календаря на форму.

Сперва следует немного рассказать о популярном ныне протоколе аутентификации OAuth который сейчас используется повсеместно.

OAuth - открытый протокол (схема) авторизации, который позволяет предоставить третьей стороне ограниченный доступ к защищённым ресурсам пользователя без необходимости передавать ей (третьей стороне) логин и пароль(ru.wikipedia.org/wiki/OAuth). Суть такого вида аутентификации является отсутствие необходимости передавать логин и пароль к персональным данным или регистрироваться на сервисе проходя нудную процедуру регистрации затем хранить пароли от разных аккаунтов, да и сервисам полегче не нужно создавать системы хранения учётных данных и ещё и отвечать за их возможную утечку. Пользователь может быть уверен что приложению будет доступен только тот набор данных которые он разрешил.  Также можно гарантировать что приложение будет продолжать работать пока пользователь не запретит ему доступ к своим данным, при этом пользователь может менять пароль и это никак не скажется на работе приложения. После получения доступа приложение может работать не требуя от пользователя подтверждения своих привилегий доступа (хотя у сервисов предоставляющих доступ есть свои ньюансы на этот счёт).

Итак как работает этот протокол аутентификации. В стандарте описана несколько схем работы протокола на все случаи жизни от авторизации на Web серверах до аутентификации на Smart-телевизорах. Жаждущие подробносей могут углубиться в чтение на https://www.digitalocean.com/community/tutorials/oauth-2-ru. В статье я не буду подробно останавливаться на деталях и особенностях этого протокола. В статье будет описан только наиболее часто используемый способ авторизации - получение токена доступа через код авторизации.

Итак аутентификация состоит из трёх последовательных этапов и одного предварительного связанного с регистрацией 1С обработки в качестве приложения на сервисах Google. Для приложения мы активируем API для тех типов данных, доступ к которым нам понадобится для приложения, ещё в приложении мы создадим OAuth идентификатор нашего приложения.

Начнем с предварительного этапа, регистрации приложения.

Нам потребуетя войти в консоль Google Api с действующей учетной записи Google по ссылке https://console.developers.google.com/apis/dashboard.

Создадим проект.

 

 

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

 

 

 

Осталось создать идентификатор учётных данных OAuth. На картинке жмем Учётные данные,
Теперь создаём идентификатор OAuth

 

 


 

 

Далее открывается вот такое модальное окно, в котором Google предлагает нам настроить окно подтверждения пользователем доступа к их данным. Это то самое окно в котором вы даёте согласие на доступ к своим учётным данным. Настроим, жмём на Set up Consent Screen.

Здесь нас интересуют области действия для API Google. Это те разрешения на доступ к персональным данным которые мы будем просить у пользователя. Для примера достаточно прав чтения данных календаря (read only).  В нашем примере нам нужны такие права
 

 

 

 

 

Нажимаем сохранить. И переходим в учетные данные для создания идентификатора OAuth.

 

 

Итак, с консолью Google мы закончили. Для удобства можно скачать файл JSON. В нём содержатся все требуемые данные которые потребуются нам в дальнейшем.
Пора заняться подключением из 1С.
И это только предварительный этап😊.

 

Этапы авторизации будут располагаться совместно с их реализацией в обработки. Сама обработка будет состоять из двух форм, первая основная на которой будут отображаться получаемые данные и вспомогательная, служащая в качестве встроенного web-браузера для отображения веб страницы пользователю, в которой он сможет разрешить для нашего приложения доступ к своим данным.доступ к пользовательским данным. Поле в котором будет отображаться страница имеет вид полеHTMLДокумент

Версия платформы на которой тестировалась обработка 8.3.14, в которой, наконец-то, был заменен веб-движок с престарелой версией Internet Explorer на современный WebKit. Что само по себе открывает огромные возможности по взаимодействию с интернетом из 1С.

 

 

Первый этап.  1.    Обращение к авторизационному серверу за разрешением пользовательских данных. Авторизационный сервер это сервис который хранит пользовательские данные и предоставляет доступ к пользовательским данным. На этом этапе формируется GET запрос со следующими параметрами

client_id - идентификатор нашего приложения

redirect_uri - веб-страница на которую вы будете переадресованы после того как пользователь разрешил доступ к своим данным

scope  - это области пользовательских данных, на которые мы будем просить разрешения у пользователя. Помните мы настраивали их в окне аутентификации. Задаются в качестве текстовой строки через пробел.

response_type - тип возвращаемого кода,задаётся как code, и означает вернуть аутентификационный код  в параметрах запроса при переадресации на страницу redirect_uri, после того  как пользователь нажмёт разрешить на доступ к своим данным.

Есть также и другие параметры но значение по умолчанию этих параметров нас вполне устраивает, подробнее можно почитать здесь(англ.)

Кнопка Авторизация  содержит код начала процесса авторизации

&НаКлиенте
Процедура Авторизоваться(ОписаниеДействия = Неопределено)
	
	ПараметрыФормы = новый структура("Адрес", АдресСтраницыАутентификации());
	ОО = Новый ОписаниеОповещения("ОбработатьAccessToken", ЭтаФорма, ОписаниеДействия);		
	ОткрытьФорму("ВнешняяОбработка.АутентификацияGoogle.Форма.ФормаАутентификации", ПараметрыФормы, Элементы.Авторизоваться, ,,,ОО, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

 Мы просто открываем вспомогательную форму авторизацию с одним параметром - адресом страницы аутентификации, который формирует для нас функция:

&НаКлиентеНаСервереБезКонтекста
Функция АдресСтраницыАутентификации()

	ПараметрыURL = Новый Структура;
	Адрес = "https://accounts.google.com/o/oauth2/v2/auth";
	ПараметрыURL.Вставить("client_id", "<ваш уникальный идентификатор приложения из Google API console>.apps.googleusercontent.com");
	ПараметрыURL.Вставить("redirect_uri", "http://localhost");
	ПараметрыURL.Вставить("scope", "https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.events.readonly  https://www.googleapis.com/auth/calendar");
	ПараметрыURL.Вставить("response_type", "code");
	ПараметрыURL.Вставить("prompt", "consent"); //Пользователю отображается только окно разрешения доступа к его пользовательским данным
	Возврат Адрес(Адрес, ПараметрыURL);

КонецФункции // ПолучитьAuthToken()

В результате работы кода кнопки открывается окно аутентификации. После того как пользователь нажал кнопку Allow(разрешить), сервер Google перенаправит нас на страницу указанную при регистрации приложения - http://localhost, которая попытается открыться в том же поле HTML Документа, но скорее всего не сможет, если у вас не запущен локальный веб-сервер. В обработчике события поля HTML документа мы извлечём полученный код аутентификации.

Ниже показан код формы, в котором нам нужно извлечь аутентификационный код из параметров командной строки, так как 1С не предоставляет возможности в случае localhost обработать параметры адресной строки(напишите в комментариях, если существует способ), но отображает адрес страницы редиректа в теле полеHTML документа, то код извлекаем из тела страницы.
 


&НаКлиенте
Процедура ПолеHTMLДокументСформирован(Элемент)
	
	Адрес = Элемент.Документ.URL;
	if Адрес = "about:blank" Then
		InnerHTML = Элемент.Документ.body.InnerHTML;
		AuthCode = AuthCode(InnerHTML);
		Закрыть(AuthCode);
	endif

КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция AuthCode(URL)
	НачалоКода = СтрНайти(ВРЕГ(URL), ВРЕГ("code="), НаправлениеПоиска.СНачала);
	Если НачалоКода = 0 Тогда
		Возврат "";
	КонецЕсли;
	НачалоКода = НачалоКода + 5;
	КонецКода = СтрНайти(ВРЕГ(URL), ВРЕГ("&amp;"), НаправлениеПоиска.СНачала, НачалоКода); 
	Возврат Сред(URL, НачалоКода, КонецКода - НачалоКода);
КонецФункции

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Адрес = Параметры.Адрес;
КонецПроцедуры




На основную форму возвращаем код аутентификации который позволит нам обменять его на токен доступа на следующем этапе еще одним запросом к серверу.

Второй этап. Полученный код следует обменять на токен доступа(Access token). Токен доступа это идентификатор который выдаётся авторизационным сервером приложению на определенный промежуток времени для доступа к данным пользователя. Запрос выполняется методом POST со следующими параметрами.

code - полученный авторизационный код

client_id - идентификатор приложения из Console APi Goolge

client_secret - секретный код приложения из Console APi Google

redirect_uri - адрес переадресации указанный в Console APi Google

grant_type - содержит значение authorization_code

&НаКлиенте
Процедура ОбработатьAccessToken(AuthCode, ОписаниеДействия) Экспорт

	Если AuthCode <> Неопределено И Не ПустаяСтрока(AuthCode) Тогда
		Tokens = Tokens(AuthCode);
		AccessToken = AccessToken(Tokens);
		RefreshToken = ?(RefreshToken(Tokens) = Неопределено, RefreshToken, RefreshToken(Tokens));
		Календари = ЗаполнитьКалендари(AccessToken);
		ЗаполнитьКалендариНаФорме(Календари);
		ПоказатьОповещениеПользователя("Авторизация успешна",,,,СтатусОповещенияПользователя.Информация);
		Если ОписаниеДействия <> Неопределено Тогда
			СтрокаВыполнить = ОписаниеДействия.Действие + "(" + AccessToken + "," + ОписаниеДействия.ПараметрыДействия + ")";
			Выполнить(СтрокаВыполнить);
		КонецЕсли;
	Иначе
		AccessToken = "";
	КонецЕсли;

КонецПроцедуры // ОбработатьAccessToken()

&НаКлиентеНаСервереБезКонтекста
Функция AccessToken(Tokens)
	
	Если типЗнч(Tokens ) = Тип("Структура") Тогда
		Возврат Tokens.access_token;
	Иначе
		Возврат Неопределено;
	КонецЕсли;
	
КонецФункции // AccessToken()

&НаКлиентеНаСервереБезКонтекста
Функция RefreshToken(Tokens)

	Если Tokens.Свойство("refresh_token") Тогда
		Возврат Tokens.refresh_token;
	Иначе
		Возврат Неопределено;
	КонецЕсли;

КонецФункции // RefreshToken()

&НаСервереБезКонтекста
Функция Tokens(AuthCode)
	
	ПараметрыURL = Новый Структура;
	АдресЗапроса = "https://www.googleapis.com/oauth2/v4/token";
	ПараметрыURL.Вставить("client_id", "<ваш идентификатор приложения из Google API Console>.apps.googleusercontent.com");
	ПараметрыURL.Вставить("redirect_uri", "http://localhost");
	ПараметрыURL.Вставить("code", AuthCode);
	ПараметрыURL.Вставить("client_secret", "<ваш secret key>");
	ПараметрыURL.Вставить("grant_type", "authorization_code");
	
	АдресЗапроса = Адрес(АдресЗапроса, ПараметрыURL);
	СтруктураURI = СтруктураURI(АдресЗапроса);
	HTTPСоединение = новый HTTPСоединение(СтруктураURI.Хост,443 , , ,, 15, Новый ЗащищенноеСоединениеOpenSSL);
	headers = Новый Соответствие;
	headers.Вставить("User-Agent", "Mozilla");
	headers.Вставить("Host", СтруктураURI.Хост);
	headers.Вставить("Content-Type", "application/x-www-form-urlencoded");
	HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, headers);
	HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	Если HTTPОтвет.КодСостояния = 200 Тогда
		Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
		ЧтениеJSON = новый ЧтениеJSON();
		ЧтениеJSON.УстановитьСтроку(Ответ);
		 Token = ПрочитатьJSON(ЧтениеJSON, Ложь);
		 Возврат Token;
	 Иначе
		 ВызватьИсключение "Произошла ошибка обращения к серверу," + "Токен не получен" +
		 Символы.ПС + "Статус ответа сервера: " + HTTPОтвет.КодСостояния;
	КонецЕсли;
	
КонецФункции
&НаСервереБезКонтекста
Функция Адрес(Знач URL, Знач ПараметрыURL)
	
	Перем МассивПараметров;
	МассивПараметров = Новый Массив;
	Для каждого Параметр Из ПараметрыURL Цикл
		МассивПараметров.Добавить(Параметр.Ключ + "=" + Параметр.Значение);
	КонецЦикла;
	URL = СокрП(URL);
	URL = ?(СтрЗаканчиваетсяНа(URL, "/"), URL, URL + "/"); 
	Возврат URL + "?" + КодироватьСтроку(СтрСоединить(МассивПараметров, "&"),	СпособКодированияСтроки.URLВКодировкеURL);

КонецФункции

В коде отправляем подготовленный POST-запрос и в случае успешного результата, получаем JSON ответ с токеном доступа(access token) и токеном обновления, который мы можем использовать при повторном запросе токена доступа когда действующий токен доступа истечёт.

На этом авторизация завершена, пришло время воспользоваться пройденной авторизацией и получить что-нибудь полезное.

Третий этап.

Имея токен доступа в получим список календарей и события выбранного календаря.

&НаКлиенте
Процедура ЗаполнитьКалендариНаФорме(Календари)

	Элементы.КалендариGoogle.СписокВыбора.Очистить();
	Если Календари.items.Количество() > 0 Тогда
		Для Каждого Календарь Из Календари.items Цикл	
			Элемент = Элементы.КалендариGoogle.СписокВыбора.Добавить(Календарь.id, Календарь.summary);	
		КонецЦикла;
		КалендариGoogle = Элементы.КалендариGoogle.СписокВыбора.Получить(0).Значение;
		КалендариGoogleПриИзменении(Неопределено);
	КонецЕсли;
	
КонецПроцедуры 

Функция ЗаполнитьКалендари(AccessToken)

	Возврат ПолучитьСписокКалендарей(AccessToken);
	
КонецФункции

Функция ПолучитьСписокКалендарей(AccessToken)
	
	ПараметрыURL = Новый Структура;
	АдресЗапроса = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
	
	СтруктураURI = СтруктураURI(АдресЗапроса);
	HTTPСоединение = новый HTTPСоединение(СтруктураURI.Хост,443 , , ,, 15, Новый ЗащищенноеСоединениеOpenSSL);
	headers = Новый Соответствие;
	headers.Вставить("User-Agent", "Mozilla");
	headers.Вставить("Host", "www.googleapis.com");
	headers.Вставить("Content-Type", "application/x-www-form-urlencoded");
	headers.Вставить("Authorization", "Bearer " + AccessToken);
	headers.Вставить("Accept", "application/json");
	HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, headers);
	HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
	Если HTTPОтвет.КодСостояния = 200 Тогда
		Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
		ЧтениеJSON = новый ЧтениеJSON();
		ЧтениеJSON.УстановитьСтроку(Ответ);
		Календари = ПрочитатьJSON(ЧтениеJSON, ЛОжь);
		 Возврат Календари;
	 Иначе
		 ВызватьИсключение "Произошла ошибка обращения к серверу," + "Токен не получен" +
		 Символы.ПС + "Статус ответа сервера: " + HTTPОтвет.КодСостояния;
	КонецЕсли;
	
КонецФункции

&НаКлиенте
Функция ПолучитьСписокСобытий(Знач AccessToken,Знач ИдКалендаря)
	
	ПараметрыURL = Новый Структура;
	АдресЗапроса = "https://www.googleapis.com/calendar/v3/calendars/{ИдКалендаря}/events";
	ИдКалендаря = КодироватьURI(ИдКалендаря);
	АдресЗапроса = СтрЗаменить(АдресЗапроса, "{ИдКалендаря}", ИдКалендаря); 
	ПараметрыURL = Новый Структура;
	ПараметрыURL.Вставить("key", "<Секретный ключ клиента>");
	
	АдресЗапроса = Адрес(АдресЗапроса, ПараметрыURL);
	
	СтруктураURI = СтруктураURI(АдресЗапроса);
	HTTPСоединение = новый HTTPСоединение(СтруктураURI.Хост,443 , , ,, 15, Новый ЗащищенноеСоединениеOpenSSL);
	headers = Новый Соответствие;
	headers.Вставить("Host", СтруктураURI.Хост);
	headers.Вставить("Content-Type", "application/x-www-form-urlencoded");
	headers.Вставить("Authorization", "Bearer " + AccessToken);
	headers.Вставить("Content-length", "0");
	headers.Вставить("Accept", "application/json");
	HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, headers);
	HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
	Если HTTPОтвет.КодСостояния = 200 Тогда
		Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
		ЧтениеJSON = новый ЧтениеJSON();
		ЧтениеJSON.УстановитьСтроку(Ответ);
		 СобытияКалендаря = ПрочитатьJSON(ЧтениеJSON, Истина);
		 Возврат СобытияКалендаря;
	 ИначеЕсли HTTPОтвет.КодСостояния = 401 Тогда
		 ЧтениеJSON = Новый ЧтениеJSON;
		 ЧтениеJSON.УстановитьСтроку(HTTPОтвет.ПолучитьТелоКакСтроку());
		 ОтветJSON = ПрочитатьJSON(ЧтениеJSON, ЛОЖЬ);
		 Если ОтветJSON.error.message = "Invalid Credentials" Тогда
			 //Обновить Token
			 AccessToken = AccessToken(ОбновитьТокен(RefreshToken));
			 Если ЗначениеЗаполнено(AccessToken) Тогда
				 Возврат ПолучитьСписокСобытий(AccessToken, ИдКалендаря);
			 Иначе
				 ПоказатьОповещениеПользователя("Необходима авторизация",,,,СтатусОповещенияПользователя.Информация);
				 ПараметрыДействия = Новый Массив;
				 ПараметрыДействия.Добавить(ИдКалендаря);
				 Авторизоваться(ОписаниеДействия("ПолучитьСписокСобытий", ПараметрыДействия));
			 КонецЕсли;
		 КонецЕсли;

	КонецЕсли;
	

КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ОбновитьТокен(RefreshToken)

	Если Не ПустаяСтрока(RefreshToken) Тогда
		Возврат RefreshTokens(RefreshToken);
	Иначе
		Возврат Неопределено;
	КонецЕсли;

КонецФункции

&НаСервереБезКонтекста
Функция RefreshTokens(RefreshToken)
	
	ПараметрыURL = Новый Структура;
	АдресЗапроса = "https://www.googleapis.com/oauth2/v4/token";
	ПараметрыURL.Вставить("client_id", "<идентификатор приложения>.apps.googleusercontent.com");
	ПараметрыURL.Вставить("redirect_uri", "http://localhost");
	ПараметрыURL.Вставить("refresh_token", RefreshToken);
	ПараметрыURL.Вставить("client_secret", "<секретный ключ>");
	ПараметрыURL.Вставить("grant_type", "refresh_token");
	
	АдресЗапроса = Адрес(АдресЗапроса, ПараметрыURL);
	СтруктураURI = СтруктураURI(АдресЗапроса);
	HTTPСоединение = новый HTTPСоединение(СтруктураURI.Хост,443 , , ,, 15, Новый ЗащищенноеСоединениеOpenSSL);
	headers = Новый Соответствие;
	headers.Вставить("User-Agent", "Mozilla");//google-oauth-playground
	headers.Вставить("Host", СтруктураURI.Хост);
	headers.Вставить("Content-Type", "application/x-www-form-urlencoded");
	HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, headers);
	HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	Если HTTPОтвет.КодСостояния = 200 Тогда
		Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
		ЧтениеJSON = новый ЧтениеJSON();
		ЧтениеJSON.УстановитьСтроку(Ответ);
		 Token = ПрочитатьJSON(ЧтениеJSON, Ложь);
		 Возврат Token;
	 Иначе
		 ВызватьИсключение "Произошла ошибка обращения к серверу," + "Токен не получен" +
		 Символы.ПС + "Статус ответа сервера: " + HTTPОтвет.КодСостояния;
	КонецЕсли;
	
КонецФункции

&НаКлиенте
Процедура КалендариGoogleПриИзменении(Элемент)
	
	ИдКалендаря = Элементы.КалендариGoogle.СписокВыбора.НайтиПоЗначению(КалендариGoogle);
	СписокСобытий = ПолучитьСписокСобытий(AccessToken, ИдКалендаря.Значение) ;
	События.Очистить();
	Если События = Неопределено Тогда 
		Возврат;
	Конецесли;
	Для каждого Событие Из СписокСобытий["items"] Цикл
		
		Если Событие["start"] ["date"] = Неопределено Тогда
			ДатаСобытия = '00010101';
		Иначе
			ДатаСобытия = ПрочитатьДатуJSON(Событие["start"] ["date"], ФорматДатыJSON.ISO);
		КонецЕсли;
		Если Событие["summary"] = Неопределено Тогда
			ОписаниеСобытия = "";
		Иначе
			ОписаниеСобытия =  Событие["summary"];
		КонецЕсли;
		События.Добавить(ДатаСобытия, ОписаниеСобытия + "("  + Формат(ДатаСобытия, "ДФ=dd.MM.yy") + ")");
	
	КонецЦикла;
КонецПроцедуры

В коде мы формируем пару GET запросов на получение календарей и событий календаря, адреса на которые отправляются запросы определены в документации Google, применительно к API календаря подробнее ознакомиться можно по ссылке здесь(англ.). Обратите особое внимание на заголовок Bearer в запросах в нем мы передаём наш токен доступа. Обязателен также задать заголовок Content-type как в примере. Остальные параметры упоминались ранее.

Стоит прокомментировать этот участок кода, здесь анализируем код ответа. Если в результате запроса получили ошибку "Invalid Credentials", это означает что наш текущий токен доступа истёк, и тогда есть два варианта, или получить новый токен доступа повторно с помощью токена обновления (Refresh token) или запросить у пользователя повторно доступ к его данным через окно авторизации.

Если HTTPОтвет.КодСостояния = 200 Тогда
		Ответ = HTTPОтвет.ПолучитьТелоКакСтроку();
		ЧтениеJSON = новый ЧтениеJSON();
		ЧтениеJSON.УстановитьСтроку(Ответ);
		 СобытияКалендаря = ПрочитатьJSON(ЧтениеJSON, Истина);
		 Возврат СобытияКалендаря;
	 ИначеЕсли HTTPОтвет.КодСостояния = 401 Тогда
		 ЧтениеJSON = Новый ЧтениеJSON;
		 ЧтениеJSON.УстановитьСтроку(HTTPОтвет.ПолучитьТелоКакСтроку());
		 ОтветJSON = ПрочитатьJSON(ЧтениеJSON, ЛОЖЬ);
		 Если ОтветJSON.error.message = "Invalid Credentials" Тогда
			 //Обновить Token
			 AccessToken = AccessToken(ОбновитьТокен(RefreshToken));
			 Если ЗначениеЗаполнено(AccessToken) Тогда
				 Возврат ПолучитьСписокСобытий(AccessToken, ИдКалендаря);
			 Иначе
				 ПоказатьОповещениеПользователя("Необходима авторизация",,,,СтатусОповещенияПользователя.Информация);
				 ПараметрыДействия = Новый Массив;
				 ПараметрыДействия.Добавить(ИдКалендаря);
				 Авторизоваться(ОписаниеДействия("ПолучитьСписокСобытий", ПараметрыДействия));
			 КонецЕсли;
		 КонецЕсли;
		 //ВызватьИсключение "Произошла ошибка обращения к серверу," + "Токен не получен" +
		 //Символы.ПС + "Статус ответа сервера: " + HTTPОтвет.КодСостояния;
		 Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
		 Сообщить(AccessToken);
	КонецЕсли;





R03;

Осталось отразить полученные данные на форме, календари в выпадающем списке, а список событий в списке на форме. При выборе календаря предусмотрен обработчик события выбора календаря обновляющего список событий из выбранного календаря.

 

 

К статье прикреплена обработка содержащая полный код описанной в статье обработки. Из обработки удалены зарегистированные мной идентификаторы приложения, перед запуском вам нужно будет зарегистрировать собственное приложение в Google API.

Спасибо за внимание.

OAuth

См. также

Перенос данных из Парус 8 в ЗГУ 3

Зарплата Внешние источники данных Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 8 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

84000 руб.

19.08.2020    22647    19    1    

22

Экстрактор данных 1С в BI - выгрузка данных из 1С в BI-аналитику

Внешние источники данных Платформа 1С v8.3 Управляемые формы Анализ и прогнозирование Конфигурации 1cv8 Узбекистан Беларусь Кыргызстан Молдова Россия Казахстан Платные (руб)

Готовое решение для автоматической выгрузки данных из 1С 8.3 в базу данных ClickHouse, PostgreSQL или Microsoft SQL для работы с данными 1С в BI-системах. «Экстрактор данных 1С в BI» работает со всеми типовыми и нестандартными конфигурациями 1С 8.3 и упрощает работу бизнес-аналитиков. Благодаря этому решению, специалистам не требуется быть программистами, чтобы легко получать данные из 1С в вашей BI-системе.

15.11.2022    13737    12    SQV0    47    

29

Перенос данных из Парус 10 в ЗГУ ред.3

Внешние источники данных Кадровый учет Файловый обмен (TXT, XML, DBF), FTP Обмен между базами 1C Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 10 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

60000 руб.

05.10.2022    9318    9    8    

11

Перенос данных из Парус 7.хх в ЗГУ ред.3

Внешние источники данных Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 7.хх учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

24000 руб.

24.04.2017    48873    97    163    

86

Перенос данных из Парус 10 (Торнадо) в ЗГУ ред.3 через Excel

Внешние источники данных Загрузка и выгрузка в Excel Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате из Парус 10(Торнадо) учреждений через файлы Excel в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ). В принципе, обработка может быть использована для загрузки из файлов Excel, полученных из любых информационных систем.

24000 руб.

16.11.2018    30091    20    31    

21

Загрузка в БГУ из УРМ "Криста"

Внешние источники данных Банковские операции Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия государственного учреждения Россия Бухгалтерский учет Платные (руб)

Обработки для загрузки данных из УРМ "Криста" в бухгалтерию государственного учреждения редакция 2.0. Есть Демо доступ на вкладке Бесплатные файлы на 1 месяц со дня получения демонстрационного ключа регистрации. Поддерживает ПО "Web-исполнение" от НПО "Криста".

4800 руб.

19.06.2013    38533    136    90    

30
Отзывы
3. uno-c 235 01.05.19 08:12 Сейчас в теме
(1)
Слишком много действий, только для того чтобы авторизоваться.

Если делать двуногую авторизацию с помощью ключа сервисного аккаунта (а не с помощью идентификатора клиента oAuth) - то поменьше действий получается, подтверждение пользователя совсем не нужно запрашивать. Автору спасибо за такую длинную подробную статью!
Прикрепленные файлы:
Hexed; KidMo; +2 Ответить
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
103. uno-c 235 02.06.20 14:32 Сейчас в теме
(97) Это нигде не написано. Это нужно понять. Вам объяснить или сами попробуете?
96. uno-c 235 01.06.20 23:32 Сейчас в теме
(94)
вы пустослов, сударь

Пустословие - это когда Вы заспамили тему Вашей демагогией, сами что-то придумываете, сами с собой спорите, сами себя опровергаете, многословно объясняете банальности, вместо того, чтобы заняться самообразованием.
Обратите внимание на ошибки, которые Вы допустили из-за непонимания терминологии.То Вам не важно авторизация или аутентификация, то трехногий access token не производит аутентификации, то я утверждаю, что могу получить доступ к данным пользователя без его согласия. Все мимо, все пустое.
100. uno-c 235 02.06.20 06:17 Сейчас в теме
(44)
Просто признайте свою ошибку. И Все.

Ответьте на вопрос, у Вас проблемы с памятью или с вниманием? Свою ошибку я признал сразу же (13):
Если имеете в виду ошибку употребления терминов - то конечно Вы правы. Не двуногая авторизация, а двуногая аутентификация.


Или у Вас проблемы с признанием Ваших собственных ошибок? Не поняли суть моей поправки? Так и признайте, на этом и завершим.
Факт остается фактом:
Сервисная учетка аутентифицируется без подтверждения пользователя.
Сервисная учетка умеет работать с календарями разных пользователей.
При этом secretkey.json используется один на всех пользователей - что довольно удобно.
102. Pawlick 10 02.06.20 14:30 Сейчас в теме
(100)
Ответьте на вопрос, у Вас проблемы с памятью или с вниманием?


Отвечаю: нет. Проблем с памятью у мен нет. Иногда с вниманием бывают, но не в этот раз.

Вы признали свою ошибку? Какую именно? С подменой терминов? Да. Признали.
Вы ошиблись не в терминологии. Вы ошиблись с пониманием того, что о чем на самом деле статья. Вы ошиблись в том, что Автор показывает процесс получения токена не для аутентификации, а для авторизации. И Ваше (3) тут совершенно не уместно.

Как видите, я стараюсь отвечать на Ваши вопросы. Ответьте, пожалуйста на мой вопрос в 97
104. uno-c 235 02.06.20 14:33 Сейчас в теме
(102) Ошибку я признал сразу. Употребил авторизация вместо аутентификации. Разумеется.
Понимание о чем статья у нас с Вами разные. Каждый концентрирует внимание на то, что ему важно - о том для него и статья.
Мне не интересен календарь, но любопытен процесс добывания токенов доступа - для меня статья об этом.
105. Pawlick 10 02.06.20 14:39 Сейчас в теме
(102)
а для авторизации

нужно согласие пользователя.

Получите ли Вы своим "методом" данные календаря? Скорее всего получите, просто с силу того, что к календарям применимо свойство "опубликовать", как и к таблицам.

Но Вы не получите доступа к почте, и вообще ко всему, что не имеет этого "свойства".

То, что Вы изобрели "нетривиальный" способ получения доступа к Google API? Ну это предмет терминологии. Я это назвал "велосипедом", Вы "нетривиальным". Сути эт не меняет. Важно то, что это смесь двух сценариев применения применения протокола. Треногаий сценарий применяется там, где приложению нужен доступ к пользовательским (чужим) данным, двуногий - когда приложению нужен доступ к своим собственным.
Вы их скрестили. Вот поэтому я и называю это "ноу хау".
106. uno-c 235 02.06.20 14:44 Сейчас в теме
(105) Я ничего не изобретал - переложил инструкцию на язык 1С. Получилось интересно, и порой удобно. Пока мне требовались только таблицы и диск - работает. Календари чужие тоже получает - факт проверенный.
107. Pawlick 10 02.06.20 14:45 Сейчас в теме
(106) От Вас жать ответа на 97?
Или опять "замылите" болтологией?
108. uno-c 235 02.06.20 14:49 Сейчас в теме
(107) Выполните любой запрос с трехногим акцесс-токеном. Зайдите в дашборд в свое приложение - и посмотрите изменившуюся статистику запросов. Ответьте себе на вопрос: могла ли измениться статистика, если бы в момент запроса не прошла аутентификация Вашего приложения по акцесс-токену.
109. uno-c 235 02.06.20 14:53 Сейчас в теме
(107)Это ответ из практики. А из теории - чтобы понять, какие есть доступы - сначала надо знать кто претендует на эти доступы. Т.е. перед проверкой прав доступа (авторизацией) идет выяснение - а от кого собственно идет запрос информации. Это выяснение и называется аутентификацией.
Все, что Вы передаете в запросе например списка календарей - это акцесс токен, он аутентифицирует Ваше приложение, затем авторизует права доступа этого приложения.
111. Pawlick 10 02.06.20 15:19 Сейчас в теме
(109)
Зайдите в дашборд в свое приложение - и посмотрите изменившуюся статистику запросов


Это коллега, называется "косвенные доказательства".

Факты же говорят о том, однозначно существует связь между Приложением и полученными им токенами,что и позволяет Вам наблюдать картину описанную в 109 (это факт №1).

Но вот что это за связь - бабушка "на двое" сказала.
Может Google API хранит информацию от том, какому приложению какие токены оно выдало, может идентификатор приложения "вшит" в получаемые им токены - это не Вы, не я утверждать не сможем, потому что явного описания этому в протоколе от Google нет (я специально вчера прочел, и для уверенности попросил это сделать Вас).

Но зато можно однозначно утверждать, что на самом первом шаге выполнения варианта протокола, описанного в статье, пользователь направляется на сервер Авторизации, куда вместе с пользователем отправляется "client_id", и именно ЭТО действие позволяет Google API впервые и однозначно идентифицировать приложение. Это, коллега, Факт №2.

Теперь, внимание, вопрос:
Вы согласны с приведенными мною фактами?

Ответьте пожалуйста на него.
112. uno-c 235 02.06.20 15:24 Сейчас в теме
(111) Для настройки прав доступа необходимо понять - кому предоставляется доступ, т.е. аутентифицировать получателя доступа. Поэтому клиент-ид и клиент-секрет также аутентифицируют приложение в процессе делегирования прав пользователем.

Неважно, хранит гугл какому приложению выдан акцесс токен, или вшито это в акцесс токен - в любом случае по акцесс токену определяется приложение. Определение приложения - это и есть процесс аутентификации.
113. Pawlick 10 02.06.20 15:42 Сейчас в теме
(112)
в любом случае по акцесс токену определяется приложение


Полностью согласен.

Теперь следите за мыслью:
факты из 111 в совокупности с текстом статьи означают что, в статье, все таки, описан процесс Авторизации приложения, т.е. перенаправление пользователя в Google, для получения от него разрешения на действия с ЕГО данными.

Аутентификация же происходит "фоном", это один из параметров запроса для получения Авторизации, без которого Авторизацию невозможно получить. И это не цель, а СРЕДСТВО получения Авторизации.

Теперь вопрос:
Вы согласны ли Вы, что целью статьи является Авторизация приложения на доступ к данным, в процессе которой происходит неизбежная Аутентификация приложения?
114. uno-c 235 02.06.20 15:50 Сейчас в теме
(113) Про цель надо спрашивать у автора. Вы решили, что цель - это работа с календарем. Я увидел цель - описание инструмента по добыче акцесс-токенов. Какую цель статьи ставил автор - это вопрос.
115. Pawlick 10 02.06.20 16:45 Сейчас в теме
(114)
Я увидел цель - добывание токенов.


А вот с этого момента, коллега, мы можем "подводить итоги", как Вы вчера выразились, поскольку коллекционирование токенов ради Вашего спортивного интереса - выходит за рамки моего интереса чтения Вашей демагогии.

Когда Вы хотите кушать - Вы добываете пищу, не "для добывания пиши", а для того, что бы утолить голод.

Вот и Автор (и Вы, кстати, тоже в своей статье) получает токен не ради токена, а использует полученный токен для получения данных от Google API. Иначе бы статья Автора закончилась на получении токена.

Таким образом:
а) В статье описан процесс Авторизации приложения (получения согласия пользователя на доступ Приложения к его данным в Google API, подтверждаемого получением Приложением Токена доступа) а не Аутентификации (идентификации приложения в Google API);
б) Авторизацию как в "треногой" так и в "двуногой" схеме протокола OAuth невозможно получить без получения согласия пользователя (да же у Вас в Вашей статьене получилось, о чем я Вам указал в 31).
б) Процесс Аутентификации приложения в принципе не требует согласия пользоваться по определению.

Таким образом Ваш "лучший" комментарий в (3), ДО вашей корректировки - просто ошибочен, а ПОСЛЕ Вашей корректировки вообще потерял логический смысл и превратился, набор слов, употребленных в одном предложении, где каждое слово по отдельности имеет смысл, но вместе - это "советы космического масштаба и космической же глупости".

Что и требовалось доказать. Честь имею.
116. uno-c 235 02.06.20 17:26 Сейчас в теме
(115) А Вы в своей страсти к демагогии все продолжаете свою бесплодную и многословную тему. Но для Вас вижу польза-таки есть, разобрались в терминах, можете не благодарить )

Сформулирую для особо одаренных, на всякий случай. Вдруг еще какой демагог прибежит.

Процесс двуногой аутентификации выдает программисту access token для дальнейшего использования в запросах к АПИ. При этом присутствие пользователя, таблицу, диск или календарь которого собираемся редактировать - не нужно, окно подтверждения пользователя (consent screen) не используется.


Задумайтесь на будущее - кому и какую пользу Вы приносите своим пустословием.
117. uno-c 235 02.06.20 19:05 Сейчас в теме
(115)
Процесс Аутентификации приложения в принципе не требует согласия пользоваться по определению

И все-таки долго до Вас доходило. Как видите - Вы оспаривали то, что масло масленое.
Теперь Вам понятно, насколько нелепы были Ваши многословные посты в ответ на такую банальность?
И как смешно смотрелось, когда Вы задавали мне вопрос - нужно ли согласие пользователя на доступ к его данным, требуя от меня ответ на этот риторический вопрос )))

Это все из-за Вашей страсти к демагогии, поработайте над этим тоже.
118. uno-c 235 04.06.20 19:13 Сейчас в теме
(115)
Таким образом Ваш "лучший" комментарий в (3), ДО вашей корректировки - просто ошибочен

Если хотите дальше продвигаться в познании двуногой - то на самом деле мой комментарий (3) не ошибочен. Про ошибочность я упростил, чтобы Вам было понятнее. У Вас и так ушло несколько дней для осознания, что масло масляное.

Интересует почему (3) не ошибочен ? Спрашивайте, отвечу. Думаю, приобретенные знания отличия аутентификации от авторизации Вам уже позволят это понять.
120. uno-c 235 21.06.20 11:05 Сейчас в теме
(115)
Процесс Аутентификации приложения в принципе не требует согласия пользоваться по определению.

Это Ваше утверждение тоже ошибочно. На днях телеграм разблокировали - там при аутентификации клиентского приложения требуется подтверждение пользователя - пользователь должен ввести код из СМС или код из клиента, работающего на другом устройстве.

Соответственно Ваши дальнейшие выводы ошибочны, профессор-недоучка )
121. uno-c 235 22.06.20 21:57 Сейчас в теме
(115)
Процесс Аутентификации приложения в принципе не требует согласия пользоваться по определению...комментарий [аутентификация не требует подтверждения пользователя]...вообще потерял логический смысл

В утверждении выше - логическая ошибка. Не требует - не значит запрещает. Аутентификация может быть без подтверждения пользователя, а может быть и с подтверждением - ни то ни другое не противоречит определению "Аутентификация". Отсюда следует: уточнение - требует ли аутентификация подтверждения пользователя или не требует - не лишено смысла.
122. uno-c 235 23.06.20 02:13 Сейчас в теме
(115)
а) В статье описан процесс Авторизации приложения (получения согласия пользователя на доступ Приложения к его данным в Google API, подтверждаемого получением Приложением Токена доступа) а не Аутентификации (идентификации приложения в Google API);

В этом утверждении тоже ошибка. Процессу Авторизации предшествует процесс Аутентификации. В статье описаны оба процесса - и Аутентификация и Авторизация. Аутентификация производится по client_id + client_secret, авторизация - по подтверждению пользователя с получением code.
123. uno-c 235 23.06.20 02:19 Сейчас в теме
(115)
б) Авторизацию как в "треногой" так и в "двуногой" схеме протокола OAuth невозможно получить без получения согласия пользователя (да же у Вас в Вашей статьене получилось, о чем я Вам указал в 31).

И наконец, в этом утверждении опять ошибка. В процессе двуногой авторизации (2LO) - приложение получает access_token после авторизации без согласия пользователя. В 2LO не проверяется право приложения на доступ к объектам пользователя. Пока проверяется только право доступа к необходимым API-scope. Приложение будет аутентифицировано по цифровой подписи - как приложение конкретного проекта, но в случае, если этот проект не подписан на запрашиваемые в scope API - процесс авторизации выдаст отказ приложению в доступе к запрашиваемым scope, при этом access_token не будет получен.
110. uno-c 235 02.06.20 15:09 Сейчас в теме
(105)
применимо свойство "опубликовать", как и к таблицам.

Не "опубликовать", а предоставить доступ конкретному сервис-аккаунту. Публикация не обязательна.
43. uno-c 235 01.06.20 15:33 Сейчас в теме
(31)
я утверждаю, что Вы не сможете получить доступ к данным пользователя через Google API без его явного согласия пользователя, а Вы утверждаете обратное.

Это не я утверждаю обратное. Это Вы, в виду непонимания термина Аутентификация решили, что я утверждаю обратное. Приписали мне некое суждение, повторяете это выдуманное суждение, опровергаете - классическая демагогия с подменой тезиса.
98. uno-c 235 02.06.20 05:01 Сейчас в теме
(31)
Как правило, приложение использует учетную запись службы, когда приложение использует Google API для работы со своими собственными данными, а не с данными пользователя


Вы разницу понимаете между "как правило" и "всегда" ? Или для Вас это так же сложно, как разница между авторизацией и аутентификацией? Неуместные вопросы, неграмотные предположения, нелепые аргументы ... ох и демагог.
101. uno-c 235 02.06.20 10:59 Сейчас в теме
(31)
Вы предварительно «расшарили доступ к своим объектам гугла», таким образом предоставили явное разрешение на доступ сервисной учетной записи к своим собственным данным.

Зачем Вы мне это пишете, у меня нет проблем с памятью. Именно поэтому я сразу исправил мою ошибку, заменив авторизацию на аутентификацию. Теперь истинность тезиса неоспорима: "аутентификация сервисной учетки происходит без подтверждения пользователя."
129. user1597854 18.05.21 18:52 Сейчас в теме
(3) А вы знаете что? После авторизации сервисного аккаунта у этого аккаунта имеется собственный GoogleDrive с собственными бесплатными 15 гигабайтами.
5. binx 167 01.05.19 19:13 Сейчас в теме
Спасибо за комментарий, надо посмотреть.
6. fixin 4253 09.12.19 12:31 Сейчас в теме
Большое человеческое спасибо.
Использовал для доступа к accounts.zoho.com
Долго тупил по поводу ошибки 301 на получении Refresh токена, только потом скопировал 1:1 и понял, что стучался на HTTP, а не на HTTPS.
Спасибо.
user774630; +1 Ответить
9. Hawk_sib 29 15.01.20 11:50 Сейчас в теме
спасибо за статью, подключив свой аккаунт начал понимать, как работает oAuth авторизация, не мог бы кто-нибудь пояснить зачем нужен костыль в виде функции AuthCode(URL)? я так понимаю в этой функции из некорректного ответа localhosta вытаскивается код авторизации и закрывается вспомогательная форма, ни ужели нельзя как-то более изящно получить код авторизации? для этого и нужен ключ сервисного аккаунта?

и ещё одно замечание до изменения строки кода

ОткрытьФорму("ВнешняяОбработка.АутентификацияGoogle.Форма.ФормаАутентификации", ПараметрыФормы, Элементы.Авторизоваться, ,,,ОО, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);


на

ОткрытьФорму("ВнешняяОбработка.АутентификацияGoogle.Форма.ФормаАутентификации", ПараметрыФормы, Элементы.Авторизоваться, ,,,ОО, );


происходила запись дамка и 1с-ка выключалась, платформа 8.3.15.1778
15. acanta 30.05.20 00:31 Сейчас в теме
Это очень интересно. На моей практике были случаи перевода личной учетной записи в корпоративную. Обратный переход возможен (теоретически) только с ликвидацией корпорации.
124. novinnik 05.10.20 14:33 Сейчас в теме
Пользуясь данной публикацией как примером, решил тоже самое сделать на обычных формах, но на первом этапе, где должна отобразиться страница с авторизацией google с указанием календаря. Выдает ошибку 404, что такая страница не найдена. В чем может быть проблема?
125. novinnik 05.10.20 16:37 Сейчас в теме
(124) Разобрался в причине, но теперь первым при появлении выходит окно авторизации, а не запроса на разрешение для доступа. Когда пытаюсь авторизоваться выходит сообщение "Возможно, этот браузер или приложение небезопасны. Подробнее… Попробуйте сменить браузер. Если вы уже используете поддерживаемый браузер, обновите страницу и попробуйте войти ещё раз."
126. binx 167 08.10.20 15:15 Сейчас в теме
(125)
Вероятно дело в том, что в обычных формах используется движок на основе Internet Explorer который плохо работает с интернет-технологиями.
127. user1597854 14.05.21 17:34 Сейчас в теме
Зарегился, чтобы сказать спасибо ОГРОМНОЕ! Разжевали так, что понятно и новичку. Интересно, сколько времени ушло у вас, чтобы в это вникнуть и перевести на 1С? И ёлки-палки, если чтобы просто залогиниться нужно столько перелопатить, то что же меня дальше ждет...
Оставьте свое сообщение