Делаем для своего http-сервиса авторизацию с помощью токена (OAuth2.0), на примере сервиса обработки заказов Яндекс Еда

01.03.23

Интеграция - WEB-интеграция

Разрабатывая http-сервис для получения и обработки заказов "Яндекс Еда", я столкнулся с необходимостью реализовать авторизацию по протоколу OAuth2.0 с помощью токенов. К моему счастью, 1С реализовала такую возможность в платформе версии 8.3.21.1302.

Скачать файлы

Наименование Файл Версия Размер
Сервер аутентификации OAuth2.0
.cf 94,61Kb
16
.cf 94,61Kb 16 Скачать
В задании Яндекса сказано: "Вы реализуете у себя OAuth2.0, передаете нам ключ (client_id) и секрет (client_secret). С этими данными мы получаем токен, запросом - POST /security/oauth/token. Далее, с этим токеном мы выполняем все остальные запросы". Также Яндекс предоставляет файлы спецификации (nomenclature_retail.json и orders.json), которые можно открыть в любом swagger-редакторе, например в https://editor.swagger.io/.

Из спецификации видим, что параметры client_id и client_secret передаются в теле запроса в кодировке application/x-www-form-urlencoded.

 

 

Итак, нужен сервер аутентификации, для того чтобы принять запрос от клиента с ключом и секретом, проверить их и в случае успеха – выдать токен. В качестве сервера аутентификации я сделал микро-конфигурацию с одним http-сервисом.

 

 

Обработчик для свойства POST:

Функция tokenPOST(Запрос)
	
	Перем client_id, client_secret; 
	
	Ошибки = Новый Массив;

	// Получаем параметры из тела запроса application/x-www-form-urlencoded
	ПараметрыЗапроса = x_www_form_urlencoded_ВСтруктуру(Запрос.ПолучитьТелоКакСтроку());	
		
	ПараметрыЗапроса.Свойство("client_id"    , client_id);
	ПараметрыЗапроса.Свойство("client_secret", client_secret);
	
	Если client_id = Неопределено Тогда
		ДобавитьОшибку(Ошибки, "Необходимо в теле запроса application/x-www-form-urlencoded: client_id.");
	КонецЕсли;

	Если client_secret = Неопределено Тогда
		ДобавитьОшибку(Ошибки, "Необходимо в теле запроса application/x-www-form-urlencoded: client_secret.");
	КонецЕсли;
	
	Если client_id <> Неопределено И client_secret <> Неопределено 
		И НЕ Справочники.Клиенты.Существует(client_id, client_secret) Тогда
		ДобавитьОшибку(Ошибки, "Ошибка аутентификации, проверьте client_id и client_secret.");
	КонецЕсли;
	
	Если Ошибки.Количество() > 0 Тогда
		Возврат ОтветHTTP(400, Ошибки);		
	КонецЕсли;
	
	// Создаем токен	
	ТокенДоступа = Новый ТокенДоступа;
    ТокенДоступа.Заголовки.Вставить("alg", Строка(АлгоритмПодписиТокенаДоступа.HS256));
    ТокенДоступа.Эмитент = "ssl";
    
    МассивПолучателей = Новый Массив;
    МассивПолучателей.Добавить("YandexEda"); // имя http-сервиса из default.vrd
    ТокенДоступа.Получатели = МассивПолучателей;

    ТокенДоступа.КлючСопоставленияПользователя = "tokenuser"; // имя пользователя 1С, у которого должна стоять галочка "Аутентификация токеном доступа"
    ТокенДоступа.ВремяСоздания = ТекущаяУниверсальнаяДата() - Дата(1970,1,1,0,0,0);
    ТокенДоступа.ВремяЖизни = 3600; 
    ТокенДоступа.Идентификатор = Новый УникальныйИдентификатор;
	
    ТокенДоступа.Подписать(АлгоритмПодписиТокенаДоступа.HS256, Константы.КлючПодписи.Получить()); // ключ, он должен быть указан в default.vrd
    access_token = Строка(ТокенДоступа); // получим токен строкой
	
	Возврат ОтветHTTP(200, Новый Структура("access_token", access_token));

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

Остальные обработчики модуля:

Процедура ДобавитьОшибку(МассивОшибок, ОписаниеОшибки)
	
	Ошибка = Новый Структура;
	Ошибка.Вставить("description", ОписаниеОшибки);
	
	МассивОшибок.Добавить(Ошибка);	
	
КонецПроцедуры

Функция СформироватьЗаголовки()

	Заголовки = Новый Соответствие;

	Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");	
	Заголовки.Вставить("Cache-Control", "private, max-age=0, no-cache, no-store");
	Заголовки.Вставить("Expires"      , Формат(ТекущаяУниверсальнаяДата(), "Л=en_US; ДФ='ddd, dd MMM yyyy HH:mm:ss'")+" GMT");
	Заголовки.Вставить("ETag"         , Новый УникальныйИдентификатор);
	Заголовки.Вставить("Vary"         , "User-Agent");
	Заголовки.Вставить("Pragma"       , "no-cache");	

	Возврат Заголовки;
	
КонецФункции

Функция ОтветHTTP(Код, Структура, ДобавитьЗаголовки = Истина)

	Ответ = Новый HTTPСервисОтвет(Код);
	СтрокаJSON = СформироватьJSON(Структура);						
	Ответ.УстановитьТелоИзСтроки(СтрокаJSON);
	Если ДобавитьЗаголовки Тогда
		Ответ.Заголовки = СформироватьЗаголовки();
	КонецЕсли;
	
	Возврат Ответ;
	
КонецФункции

Функция СформироватьJSON(Значение)
	
	ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON();
	
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
			
	НастройкиСериализацииJSON = Новый НастройкиСериализацииJSON;
	НастройкиСериализацииJSON.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДатаСоСмещением;
	НастройкиСериализацииJSON.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
	
	ЗаписатьJSON(ЗаписьJSON, Значение, НастройкиСериализацииJSON); 
	
	Возврат ЗаписьJSON.Закрыть();
	
КонецФункции

Функция x_www_form_urlencoded_ВСтруктуру(ТелоЗапроса)

	Структура = Новый Структура;
	
	МассивСтрок = СтрРазделить(ТелоЗапроса, "&");
	
	Для Каждого ТекСтрока Из МассивСтрок Цикл
		Мас = СтрРазделить(ТекСтрока, "=");
		Структура.Вставить(Мас[0], Мас[1]);
	КонецЦикла;
	
	Возврат Структура;
		
КонецФункции

При публикации http-сервиса аутентификации формируется файл default.vrd, в котором нужно прописать имя пользователя и пароль для входа в базу. Это нужно сделать потому, что в запросе Яндекса отсутствует Basic-аутентификация, поэтому мы пропускаем запрос без аутентификации и потом уже в коде проверяем client_id и client_secret, полученные из тела запроса в кодировке application/x-www-form-urlencoded.

Вот строка из файла default.vrd базы аутентификации, в которой нужно прописать имя пользователя (UserName) и пароль (Password) для входа в базу.

ib="File=&quot;D:\1C\Base\HTTP_YandexEda_Auth&quot;;Usr=&quot;UserName&quot;;Pwd=&quot;Password&quot;"

Теперь о самом главном, о токене.

В базе, в которую клиент будет входить по токену, создаем пользователя для аутентификации токеном.

 

 

В моем случае это отдельная база и конфигурация. Т.е. у меня есть база http-сервиса аутентификации, которая только выдает токен и основная база http-сервиса обработки заказов "Яндекс Еды", в которую и будет выполняться вход по токену.

После публикации этой базы, необходимо внести изменения в файл default.vrd, для того, чтобы входить в эту базу используя токен доступа.

Вот содержимое файла default.vrd базы http-сервиса обработки заказов "Яндекс Еда":

<?xml version="1.0" encoding="UTF-8"?>
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
		xmlns:xs="http://www.w3.org/2001/XMLSchema"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		base="/goldfishyayeda"
		ib="File=&quot;D:\1C\Base\HTTP_YandexEda&quot;;"
		enable="false">
	<ws enable="false"
			pointEnableCommon="false"/>
	<httpServices publishByDefault="false">
		<service name="YandexEda"
				rootUrl="v1"
				enable="true"
				reuseSessions="autouse"
				sessionMaxAge="30"
				poolSize="10"
				poolTimeout="5">
                <accessTokenAuthentication>
                    <accessTokenRecepientName>YandexEda</accessTokenRecepientName>
                    <issuers>
                        <issuer name="ssl" 
								authenticationClaimName="sub" 
								authenticationUserPropertyName="tokenuser"
								keyInformation="OTVjMDNkOWM2N2QyNDE1ZjgyNDMwZGI0ZTg1Y2VlNWQ="/>
					</issuers>
                </accessTokenAuthentication>						
		</service>				
	</httpServices>
	<standardOdata enable="false"
			reuseSessions="autouse"
			sessionMaxAge="20"
			poolSize="10"
			poolTimeout="5"/>
	<analytics enable="false"/>
</point>

Ключ подписи - это любой набор символов закодированный в Base64 строку.

Вот пример функции для генерации ключей подписи токена:

Функция СоздатьКлючПодписи()
	
	УИД = Новый УникальныйИдентификатор;
	УИД = СтрЗаменить(УИД, "-", "");
	
	Возврат Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(УИД));
	
КонецФункции

Общая схема настройки:

 

Выводы:

При формировании токена необходимо указать:

  • получателя токена, это имя http-сервиса, оно будет указано в файле default.vrd;
    МассивПолучателей = Новый Массив;
    МассивПолучателей.Добавить("YandexEda"); // имя http-сервиса из default.vrd
    ТокенДоступа.Получатели = МассивПолучателей;
  • ключ сопоставления пользователя, это имя пользователя 1с, у которого установлена галочка "Аутентификация токеном доступа", также это параметр authenticationUserPropertyName в файле default.vrd;
    ТокенДоступа.КлючСопоставленияПользователя = "tokenuser"; // имя пользователя 1С, у которого должна стоять галочка "Аутентификация токеном доступа"
  • подписать токен используя ключ, который необходимо указать в файле default.vrd в параметре keyInformation
    ТокенДоступа.Подписать(АлгоритмПодписиТокенаДоступа.HS256, Константы.КлючПодписи.Получить()); // ключ, он должен быть указан в default.vrd

 

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    15745    10    17    

11

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    17548    6    15    

13

Интеграция с сервисом vetmanager

WEB-интеграция Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия 3.0 Бытовые услуги, сервис Платные (руб)

Внешняя обработка разрабатывалась для загрузки документов из Ветменеджер в 1С: Бухгалтерия 3.0

12000 руб.

02.02.2021    16359    42    49    

23

[Расширение] БОР-Навигатор.Культура

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

Расширение конфигурации, включающее в себя объекты, необходимые для подготовки и сдачи отчета "Штатная численность" системы "БОР-Навигатор.Культура" в программе "1С:Зарплата и кадры государственного учреждения", редакция 3.1.

8400 руб.

01.02.2019    25741    9    0    

7

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    88579    160    215    

318
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. gzharkoj 502 01.03.23 10:55 Сейчас в теме
Про keyInformation есть особенность, с форума партнеров: "...зависит от алгоритма. Если это симметричный алгоритм, то строка в base64, если используется алгоритм асимметричного шифрования, то указывается сертификат в PEM формате..."; - вы подписываете HS256, он симметричный.
2. efin 25.03.23 00:50 Сейчас в теме
(0) Подскажите, почему в default.vrd authenticationUserPropertyName="tokenuser", а не = "name" как пишет 1С в документации? Тут нужно указать не имя конкретного пользователя, а имя поля, в котором хранится имя, которое будет сопоставляться с полем из токена.
3. tav13 6 13.04.23 14:53 Сейчас в теме
(2) Потому что с конструкцией authenticationUserPropertyName="name" не работает (проверено на 8.3.21.1624), выдает ошибку: Токен доступа недействителен.Некорректное значение параметра 'iss'
А если указать вместо "name" конкретного пользователя с токен авторизацией - сразу начинает работать.
8. gygabites12 26.01.24 19:19 Сейчас в теме
(3) Не соглашусь (проверено на 8.3.22.2106), имеется настройка authenticationUserPropertyName="name" и все работает.
Фирма 1С в значение атрибута "authenticationUserPropertyName" заложила другую логику.
Пруфы тут: https://its.1c.ru/db/v8321doc#bookmark:adm:TI000001106
В вашем случае, возможно, ошибка возникала потому, что один из параметров блока "Полезной нагрузки" был задан неверно.
Указывая значение отличное от name, OSUser или email, скорее всего платформа игнорирует их и производит поиск по значению по умолчанию, т.е. name.
4. portal80 04.08.23 07:56 Сейчас в теме
Зачем такие токены, в которых можно раскодировать имя пользователя? ПРосто берешь и сам сообщаешь злоумышленнику о том , что у тебя есть такой то пользователь.
5. user2025888 26.12.23 13:19 Сейчас в теме
Подскажите, пожалуйста. По требованиям яндекса должен быть один хост сервера для всех запросов, а при такой реализации, когда получение токена происходит в отдельной базе, разве это возможно?
6. pavlushov 29 11.01.24 13:41 Сейчас в теме
(5) Да, конечно. Вы на одном хосте публикуете http-сервис обработки заказов и сервис авторизации. Примеры URL: myhost.ru/order - для заказов, myhost.ru/security/oauth/token - для получения токена.
7. i_dubrivin 19.01.24 16:39 Сейчас в теме
Какой длины вы получаете токен?
Использовал схему для интеграции с Афишей, у них требование к токену длина до 36 символов. Мб знаете, как добиться такого результата?
9. gygabites12 26.01.24 19:45 Сейчас в теме
Пожалуй, это самая полная инструкция, из тех что я нашел на ресурсе.
Дополню только несколько моментов:
1. На схеме сказано, что в МассивПолучателей нужно добавлять строку с именем сервиса (значение атрибута "name" элемента "service"). На самом деле, нужно добавлять значение элемента "accessTokenRecepientName", который вложен в элемент "accessTokenAuthentication", а тот в свою очередь в элемент "service". Т.к. они могут быть разные, но в данном примере они одинаковые.

2. В документации опущено важное уточнение: элемент "accessTokenAuthentication" должен быть вложен в элемент <point> для ws и <service> для http, иначе будет ошибка.

3. Данной информации нигде не нашел и пришел эмпирическим путем (кто доберется до вашей статьи, найдет и этот комментарий):
Для аутентификации в веб-клиенте необходимо:
- описать элемент "accessTokenAuthentication" для корневого объекта "point";
- в качестве получателя (в указанном примере "МассивПолучателей") нужно добавить новый пустой массив, а если вы хотите сделать "универсальный" токен, то массив со значениями: "" (пустая строка) и <имя сервиса> (в файле публикации default.vrd значение элемента "accessTokenRecepientName").
Иначе будет ошибка.

4. Как авторизоваться через Тонкого клиента, так и не разобрался. Написал обращение в фирму 1С, как ответят и разберусь, дополню комментарий.

з.ы.: Если кому-то будет интересно, могу приложить обработку по генерации (она же разбору) токенов доступа.
Прикрепленные файлы:
10. gygabites12 14.02.24 11:30 Сейчас в теме
(9) п.4 Для авторизации токеном доступа в тонком клиенте необходимо использовать командную строку, а не стандартный "запускатор", т.к.в нем длина поля "Дополнительные параметры запуска" ограничена и строка токена доступа обрезается.
Командная строка запуска имеет вид: "C:\Program Files\1cv8\<version>\bin\1cv8c.exe" /WS "http://localhost/<имя_публикации>" /AccessToken <токен_доступа>
11. gygabites12 14.02.24 12:02 Сейчас в теме
(9) п.3 оказался не точен, описанный сценарий будет работать, но как опять же подсказали в поддержке фирмы 1С, не смотря на документацию, тег <accessTokenRecepientName> все таки применим к авторизации тонкого клиента. Указанное значение в файле публикации будет сверяться со значением из массива получателей.
Прикрепленные файлы:
Оставьте свое сообщение