diff --git a/CHANGELOG.md b/CHANGELOG.md index f5997b9..8585a65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,30 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see ## [Unreleased] +## [1.3.26] - 2026-08-12 + + + +### Added + +- JWT Bearer **RS256**, **RS384**, and **RS512** via platform `ТокенДоступа` + (Closes #13): schema field `privateKey` (PEM, unencrypted); HS* still uses + `secret`. Choice button loads `.pem`/`.txt` into the private key field. + Postman `jwt` import/export round-trips `privateKey`. +- JWT Bearer **PS256**, **PS384**, and **PS512** (RSA-PSS) via the same + `privateKey` PEM field (Closes #13). +- JWT Bearer **ES256**, **ES384**, and **ES512** (ECDSA) via the same + `privateKey` PEM field (Closes #13). + +### Changed + +- JWT Bearer form shows **Secret** only for HS* and **Private key (PEM)** for + RS*/PS*/ES* (Postman-like); both keys remain in the params table for round-trip. +- JWT Bearer signing migrated from hand-rolled HMAC (`ХешированиеДанных`) to + platform `ТокенДоступа` / `АлгоритмПодписиТокенаДоступа` for **HS256**, + **HS384**, and **HS512** (Closes #13). +- Updated README demo GIF and main form screenshot for JWT Bearer. + ## [1.3.25] - 2026-08-07 @@ -237,6 +261,31 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see ## [Unreleased] +## [1.3.26] - 2026-08-12 + + + +### Добавлено + +- JWT Bearer **RS256**, **RS384** и **RS512** через платформенный `ТокенДоступа` + (Closes #13): поле схемы `privateKey` (PEM без пароля); для HS* по-прежнему + `secret`. Кнопка выбора загружает `.pem`/`.txt` в поле приватного ключа. + Импорт/экспорт Postman `jwt` сохраняет `privateKey`. +- JWT Bearer **PS256**, **PS384** и **PS512** (RSA-PSS) через то же поле + `privateKey` (Closes #13). +- JWT Bearer **ES256**, **ES384** и **ES512** (ECDSA) через то же поле + `privateKey` (Closes #13). + +### Изменено + +- В форме JWT Bearer поле **Секрет** только для HS*, **Приватный ключ (PEM)** + для RS*/PS*/ES* (как в Postman); оба ключа остаются в таблице параметров для + round-trip. +- Подпись JWT Bearer переведена с самописного HMAC (`ХешированиеДанных`) на + платформенный `ТокенДоступа` / `АлгоритмПодписиТокенаДоступа` для **HS256**, + **HS384** и **HS512** (Closes #13). +- Обновлены demo GIF и скриншот главной формы в README под JWT Bearer. + ## [1.3.25] - 2026-08-07 @@ -447,7 +496,8 @@ Versions correspond to git tags (`v_X_Y_Z` tag → `X.Y.Z` version); see - Разные исправления стабильности. -[Unreleased]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_25...HEAD +[Unreleased]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_26...HEAD +[1.3.26]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_25...v_1_3_26 [1.3.25]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_24...v_1_3_25 [1.3.24]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_23...v_1_3_24 [1.3.23]: https://github.com/LunatikDG/GetManHTTP/compare/v_1_3_22...v_1_3_23 diff --git a/README.md b/README.md index 3a99bdd..5530fea 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License](https://img.shields.io/badge/license-GPL--3.0-blue)](https://github.com/LunatikDG/GetManHTTP/blob/main/LICENSE.txt) [![1C Version](https://img.shields.io/badge/1С-8.3.26%2B-orange)](#) -[![Release](https://img.shields.io/badge/release-1.3.25-red)](https://github.com/LunatikDG/GetManHTTP/releases) +[![Release](https://img.shields.io/badge/release-1.3.26-red)](https://github.com/LunatikDG/GetManHTTP/releases) [![BSL Lint](https://github.com/LunatikDG/GetManHTTP/actions/workflows/bsl-lint.yml/badge.svg)](https://github.com/LunatikDG/GetManHTTP/actions/workflows/bsl-lint.yml)

@@ -58,7 +58,9 @@ indicator, response headers and formatted body. ![Response panel](docs/images/response-panel.png) **Authorization** — type selector (Basic / Token / Bearer Token / API Key / JWT Bearer) with fields that adapt to -the selected scheme. JWT Bearer signs HS256/HS512 locally (no crypto provider required). +the selected scheme. JWT Bearer signs HS256/HS384/HS512 (HMAC secret) and +RS256/RS384/RS512, PS256/PS384/PS512, ES256/ES384/ES512 (PEM private key, no +passphrase) via platform `ТокенДоступа`. ![Authorization fields](docs/images/auth-fields.png) @@ -223,7 +225,9 @@ GetManHTTP — это HTTP-клиент, оформленный как **вне ![Панель ответа](docs/images/response-panel.png) **Авторизация** — выбор типа (Basic / Token / Bearer Token / API Key / JWT Bearer) с полями, которые меняются в -зависимости от схемы. JWT Bearer подписывает HS256/HS512 локально (криптопровайдер не нужен). +зависимости от схемы. JWT Bearer подписывает HS256/HS384/HS512 (HMAC-секрет) и +RS256/RS384/RS512, PS256/PS384/PS512, ES256/ES384/ES512 (PEM приватный ключ без +пароля) через платформенный `ТокенДоступа`. ![Поля авторизации](docs/images/auth-fields.png) diff --git a/docs/collection-format.md b/docs/collection-format.md index 03cfecf..123e85c 100644 --- a/docs/collection-format.md +++ b/docs/collection-format.md @@ -105,7 +105,7 @@ Portable authorization object (collection, folder, or request). | `Token` | collection, folder, request | `tokenPrefix`, `token` | Sent as `Authorization: {tokenPrefix} {token}`. Default prefix when empty at apply time: `Token`. `token` is secret. | | `BearerToken` | collection, folder, request | `token` | Sent as `Authorization: Bearer {token}` (fixed prefix, RFC 6750). `token` is secret. | | `ApiKey` | collection, folder, request | `key`, `value`, `addTo` | `addTo`: `Header` (default) or `Query`. Default `key` name: `X-API-Key`. `value` is secret. | -| `JwtBearer` | collection, folder, request | `algorithm`, `secret`, `claims`, `ttlSeconds` | Builds JWT (HS256/HS512) and sends `Authorization: Bearer {jwt}`. `algorithm` default `HS256`; `claims` is a JSON object string; `ttlSeconds` > 0 sets `iat`/`exp` (Unix). `secret` is secret. | +| `JwtBearer` | collection, folder, request | `algorithm`, `secret`, `privateKey`, `claims`, `ttlSeconds` | Builds JWT via platform `ТокенДоступа` and sends `Authorization: Bearer {jwt}`. Algorithms: **HS256/HS384/HS512** (signing material: `secret`) and **RS256/RS384/RS512**, **PS256/PS384/PS512**, **ES256/ES384/ES512** (signing material: `privateKey` PEM, unencrypted; RSA or EC depending on algorithm). Default `algorithm`: `HS256`. `claims` is a JSON object string; `ttlSeconds` > 0 sets `iat`/`exp` (Unix). Both `secret` and `privateKey` are secret; empty required material omits the Authorization header. | | `InheritFromOwner` | folder, request | _(none)_ | Walk up folder → collection auth. **Not** valid as collection root auth (importers coerce unsupported types to the context default). | --- @@ -378,7 +378,7 @@ v2.1: файлы Postman определяются отдельно и преоб | `Token` | коллекция, папка, запрос | `tokenPrefix`, `token` | Заголовок `Authorization: {tokenPrefix} {token}`. Префикс по умолчанию при применении: `Token`. `token` — секрет. | | `BearerToken` | коллекция, папка, запрос | `token` | Заголовок `Authorization: Bearer {token}` (фиксированный префикс, RFC 6750). `token` — секрет. | | `ApiKey` | коллекция, папка, запрос | `key`, `value`, `addTo` | `addTo`: `Header` (по умолчанию) или `Query`. Имя ключа по умолчанию: `X-API-Key`. `value` — секрет. | -| `JwtBearer` | коллекция, папка, запрос | `algorithm`, `secret`, `claims`, `ttlSeconds` | Собирает JWT (HS256/HS512) и шлёт `Authorization: Bearer {jwt}`. `algorithm` по умолчанию `HS256`; `claims` — JSON-объект строкой; `ttlSeconds` > 0 задаёт `iat`/`exp` (Unix). `secret` — секрет. | +| `JwtBearer` | коллекция, папка, запрос | `algorithm`, `secret`, `privateKey`, `claims`, `ttlSeconds` | Собирает JWT через платформенный `ТокенДоступа` и шлёт `Authorization: Bearer {jwt}`. Алгоритмы: **HS256/HS384/HS512** (материал: `secret`) и **RS256/RS384/RS512**, **PS256/PS384/PS512**, **ES256/ES384/ES512** (материал: `privateKey` PEM без пароля; RSA или EC в зависимости от алгоритма). `algorithm` по умолчанию `HS256`. `claims` — JSON-объект строкой; `ttlSeconds` > 0 задаёт `iat`/`exp` (Unix). И `secret`, и `privateKey` — секреты; пустой нужный материал — без заголовка Authorization. | | `InheritFromOwner` | папка, запрос | _(нет)_ | Наследование папка → коллекция. На корне коллекции не используется. | --- diff --git a/docs/images/demo.gif b/docs/images/demo.gif index d1c68b7..f8a5fbc 100644 Binary files a/docs/images/demo.gif and b/docs/images/demo.gif differ diff --git a/docs/images/main-form.png b/docs/images/main-form.png index 23a22b2..8599bb9 100644 Binary files a/docs/images/main-form.png and b/docs/images/main-form.png differ diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" index 37b36ce..a1ca695 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Form.form" @@ -2,7 +2,7 @@ <key>ru</key> - <value>GetManHTTP (HTTP-клиент): v1.3.25</value> + <value>GetManHTTP (HTTP-клиент): v1.3.26</value> ГруппаЛево @@ -2155,6 +2155,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации1РасширеннаяПодсказка 334 @@ -2181,7 +2185,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -2202,6 +2210,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации2РасширеннаяПодсказка 337 @@ -2228,7 +2240,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -2249,6 +2265,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации3РасширеннаяПодсказка 340 @@ -2275,7 +2295,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -2296,6 +2320,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации4РасширеннаяПодсказка 343 @@ -2322,7 +2350,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -2343,6 +2375,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации5РасширеннаяПодсказка 346 @@ -2369,7 +2405,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -2390,6 +2430,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации6РасширеннаяПодсказка 349 @@ -2416,7 +2460,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" index 0cb7789..bac64ce 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Help/ru.html" @@ -84,7 +84,7 @@

Настройка HTTP-запроса

  • по токену (свой префикс) — заголовок Authorization (префикс по умолчанию Token);
  • Bearer Token — заголовок Authorization: Bearer … (фиксированный префикс);
  • API Key — имя и значение ключа с выбором «добавить в заголовок» или «в Query-параметр»;
  • -
  • JWT Bearer — генерация JWT (алгоритмы HS256/HS512), секрет, Claims (JSON), TTL для iat/exp; заголовок Authorization: Bearer ….
  • +
  • JWT Bearer — генерация JWT через платформенный ТокенДоступа: HS256/HS384/HS512 (поле «Секрет») и RS256/RS384/RS512, PS256/PS384/PS512, ES256/ES384/ES512 (поле «Приватный ключ (PEM)» без пароля, кнопка выбора файла .pem/.txt), Claims (JSON), TTL для iat/exp; заголовок Authorization: Bearer ….
  • Тело запроса — варианты: отсутствует, JSON, XML, form-data (текстовые и файловые поля, несколько файлов в одном multipart; лимит размера тела 50 МБ), двоичные данные (один файл целиком).
  • @@ -125,7 +125,7 @@

    Обратная связь

    Ошибки и предложения: репозиторий на GitHub, почта main@lunatikdg.ru, Telegram @LunatikDG.

    -

    Версия обработки: 1.3.25

    +

    Версия обработки: 1.3.26

    diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" index 4d075d6..dbb354c 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260/Module.bsl" @@ -98,6 +98,74 @@ Процедура ПолеАвторизацииПриИзменении(Элемент) СинхронизироватьПараметрыАвторизацииИзПолейФормы(); + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() + И Элемент.Имя = "ПолеАвторизации1" Тогда + ОтобразитьПоляАвторизацииПоСхеме(); + КонецЕсли; + +КонецПроцедуры + +&НаКлиенте +Процедура ПолеАвторизацииНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка) + + // Кнопка выпадающего списка тоже вызывает НачалоВыбора - не глушим её. + Если Не Элемент.КнопкаВыбора Тогда + Возврат; + КонецЕсли; + + СтандартнаяОбработка = Ложь; + #Если ВебКлиент Тогда + ВывестиСообщениеПользователю("Загрузка ключа из файла недоступна в веб-клиенте"); + Возврат; + #КонецЕсли + + ИмяРеквизита = СтрЗаменить(Элемент.Имя, "ПолеАвторизации", "ЗначениеАвторизации"); + Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); + Диалог.Заголовок = "Выберите файл приватного ключа (PEM)"; + Диалог.Фильтр = + "Ключ PEM/TXT (*.pem;*.txt)|*.pem;*.txt|" + + "Все файлы (*.*)|*.*"; + Диалог.МножественныйВыбор = Ложь; + ПараметрыОповещения = Новый Структура("ИмяРеквизита", ИмяРеквизита); + Оповещение = Новый ОписаниеОповещения( + "ЗагрузитьJwtПриватныйКлючИзФайлаЗавершение", + ЭтотОбъект, + ПараметрыОповещения); + Диалог.Показать(Оповещение); + +КонецПроцедуры + +&НаКлиенте +Процедура ЗагрузитьJwtПриватныйКлючИзФайлаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт + + Если ВыбранныеФайлы = Неопределено Или ВыбранныеФайлы.Количество() = 0 Тогда + Возврат; + КонецЕсли; + + ИмяРеквизита = ""; + Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда + ДополнительныеПараметры.Свойство("ИмяРеквизита", ИмяРеквизита); + КонецЕсли; + Если ПустаяСтрока(ИмяРеквизита) Тогда + Возврат; + КонецЕсли; + + ПутьКФайлу = ВыбранныеФайлы[0]; + + #Если НЕ ВебКлиент Тогда + ЧтениеТекста = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8); + ТекстКлюча = ЧтениеТекста.Прочитать(); + ЧтениеТекста.Закрыть(); + #Иначе + Возврат; + #КонецЕсли + + Если ТекстКлюча = Неопределено Тогда + ТекстКлюча = ""; + КонецЕсли; + + ЭтотОбъект[ИмяРеквизита] = ТекстКлюча; + СинхронизироватьПараметрыАвторизацииИзПолейФормы(); КонецПроцедуры @@ -1914,10 +1982,10 @@ &НаКлиенте Процедура ОтобразитьПоляАвторизацииПоСхеме() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); - КоличествоПолейСхемы = Схема.Поля.Количество(); + КоличествоПолейСхемы = ПоляСхемы.Количество(); Если КоличествоПолейСхемы > МаксимумПолей Тогда ВызватьИсключение "Схема авторизации содержит больше полей, чем поддерживает форма (" @@ -1937,10 +2005,11 @@ ЭлементПоля.СписокВыбора.Очистить(); ЭлементПоля.РежимВыбораИзСписка = Ложь; ЭлементПоля.КнопкаВыпадающегоСписка = Ложь; + ЭлементПоля.КнопкаВыбора = Ложь; Продолжить; КонецЕсли; - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ЗначениеПоля = ЗначенияПараметров.Получить(ОписаниеПоля.Ключ); Если ЗначениеПоля = Неопределено Тогда ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; @@ -1952,6 +2021,7 @@ ЭлементПоля.РежимПароля = ОписаниеПоля.Секретный; ЭлементПоля.МногострочныйРежим = ОписаниеПоля.Многострочный; ЭлементПоля.Высота = ?(ОписаниеПоля.Многострочный, 5, 1); + ЭлементПоля.КнопкаВыбора = (ОписаниеПоля.Ключ = КлючПоляАвторизацииJwtПриватныйКлюч()); НастроитьСписокВыбораПоляАвторизации(ЭлементПоля, ОписаниеПоля); КонецЦикла; @@ -1995,13 +2065,17 @@ &НаКлиенте Процедура СинхронизироватьПараметрыАвторизацииИзПолейФормы() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() Тогда + ЗначенияПараметров.Вставить(КлючПоляАвторизацииJwtАлгоритм(), ЗначениеАвторизации1); + КонецЕсли; + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); - КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолей); + КоличествоПолейСхемы = Мин(ПоляСхемы.Количество(), МаксимумПолей); Для Индекс = 1 По КоличествоПолейСхемы Цикл - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоЧислаБезГруппировки(Индекс); УстановитьЗначениеПараметраАвторизацииНаКлиенте( ПараметрыАвторизации, @@ -2039,10 +2113,10 @@ &НаСервере Процедура ЗаполнитьЗначенияПолейАвторизацииНаСервере() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизации(ПараметрыАвторизации); + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); - КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолей); + КоличествоПолейСхемы = Мин(ПоляСхемы.Количество(), МаксимумПолей); Для Индекс = 1 По МаксимумПолей Цикл @@ -2053,7 +2127,7 @@ Продолжить; КонецЕсли; - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ЗначениеПоля = ЗначенияПараметров.Получить(ОписаниеПоля.Ключ); Если ЗначениеПоля = Неопределено Тогда ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; @@ -2068,13 +2142,17 @@ &НаСервере Процедура СинхронизироватьПараметрыАвторизацииИзПолейФормыНаСервере() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизации(ПараметрыАвторизации); + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() Тогда + ЗначенияПараметров.Вставить(КлючПоляАвторизацииJwtАлгоритм(), ЗначениеАвторизации1); + КонецЕсли; + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); - КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолей); + КоличествоПолейСхемы = Мин(ПоляСхемы.Количество(), МаксимумПолей); Для Индекс = 1 По КоличествоПолейСхемы Цикл - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоЧислаБезГруппировки(Индекс); УстановитьЗначениеПараметраАвторизации( ПараметрыАвторизации, @@ -3317,7 +3395,7 @@ &НаКлиентеНаСервереБезКонтекста Функция ВерсияОбработки() - Возврат "1.3.25"; + Возврат "1.3.26"; КонецФункции @@ -6781,6 +6859,11 @@ КлючПоляАвторизацииJwtСекрет(), ЗначениеПараметраPostmanAuth(ПараметрыJwt, "secret"), Истина); + УстановитьЗначениеПараметраАвторизации( + Результат.ПараметрыАвторизации, + КлючПоляАвторизацииJwtПриватныйКлюч(), + ЗначениеПараметраPostmanAuth(ПараметрыJwt, "privateKey"), + Истина); PayloadJwt = ЗначениеПараметраPostmanAuth(ПараметрыJwt, "payload"); Если ПустаяСтрока(PayloadJwt) Тогда PayloadJwt = "{}"; @@ -6888,15 +6971,23 @@ СекретJwt = ЗначениеПараметраАвторизацииИзТаблицы( ПараметрыАвторизации, КлючПоляАвторизацииJwtСекрет()); + ПриватныйКлючJwt = ЗначениеПараметраАвторизацииИзТаблицы( + ПараметрыАвторизации, + КлючПоляАвторизацииJwtПриватныйКлюч()); ClaimsJwt = ЗначениеПараметраАвторизацииИзТаблицы( ПараметрыАвторизации, КлючПоляАвторизацииJwtClaims()); Результат = Новый Структура; Результат.Вставить(КлючType, "jwt"); МассивПараметров = Новый Массив; - МассивПараметров.Добавить(ПараметрPostmanAuth("algorithm", АлгоритмJwt, ТипСтрока)); - МассивПараметров.Добавить(ПараметрPostmanAuth("secret", СекретJwt, ТипСтрока)); - МассивПараметров.Добавить(ПараметрPostmanAuth("payload", ClaimsJwt, ТипСтрока)); + ПараметрАлгоритма = ПараметрPostmanAuth("algorithm", АлгоритмJwt, ТипСтрока); + ПараметрСекрета = ПараметрPostmanAuth("secret", СекретJwt, ТипСтрока); + ПараметрПриватногоКлюча = ПараметрPostmanAuth("privateKey", ПриватныйКлючJwt, ТипСтрока); + ПараметрPayload = ПараметрPostmanAuth("payload", ClaimsJwt, ТипСтрока); + МассивПараметров.Добавить(ПараметрАлгоритма); + МассивПараметров.Добавить(ПараметрСекрета); + МассивПараметров.Добавить(ПараметрПриватногоКлюча); + МассивПараметров.Добавить(ПараметрPayload); Результат.Вставить("jwt", МассивПараметров); Возврат Результат; КонецЕсли; @@ -7449,6 +7540,13 @@ КонецФункции +&НаКлиентеНаСервереБезКонтекста +Функция КлючПоляАвторизацииJwtПриватныйКлюч() + + Возврат "privateKey"; + +КонецФункции + &НаКлиентеНаСервереБезКонтекста Функция КлючПоляАвторизацииJwtClaims() @@ -7485,9 +7583,11 @@ КонецФункции &НаСервере -Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) +Функция ПоляСхемыАвторизацииДляОтображения(Знач ТипАвторизации, Знач ЗначенияПараметров) - Возврат ОбъектОбработкиАвторизации().ОписаниеСхемыАвторизации(ТипАвторизации); + Возврат ОбъектОбработкиАвторизации().ПоляСхемыАвторизацииДляОтображения( + ТипАвторизации, + ЗначенияПараметров); КонецФункции diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" index a2bcd75..03287ba 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Form.form" @@ -318,6 +318,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации1РасширеннаяПодсказка 151 @@ -344,7 +348,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -365,6 +373,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации2РасширеннаяПодсказка 154 @@ -391,7 +403,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -412,6 +428,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации3РасширеннаяПодсказка 157 @@ -438,7 +458,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -459,6 +483,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации4РасширеннаяПодсказка 160 @@ -485,7 +513,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -506,6 +538,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации5РасширеннаяПодсказка 163 @@ -532,7 +568,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true @@ -553,6 +593,10 @@ OnChange ПолеАвторизацииПриИзменении + + StartChoice + ПолеАвторизацииНачалоВыбора + ПолеАвторизации6РасширеннаяПодсказка 166 @@ -579,7 +623,11 @@ true true true - true + false + + StdPicture.OpenFile + + false true true diff --git "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" index f8bfdb9..54e35f0 100644 --- "a/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" +++ "b/src/ExternalDataProcessors/GetManHTTP/Forms/\320\244\320\276\321\200\320\274\320\260\320\232\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270\320\227\320\260\320\277\321\200\320\276\321\201\320\276\320\262/Module.bsl" @@ -1,4 +1,5 @@ // BSLLS:UnusedLocalVariable-off +// BSLLS:LatinAndCyrillicSymbolInWord-off #Область ОбработчикиСобытийФормы // BSLLS:UnusedLocalMethod-off @@ -69,6 +70,76 @@ Процедура ПолеАвторизацииПриИзменении(Элемент) СинхронизироватьПараметрыАвторизацииИзПолейФормы(); + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() + И Элемент.Имя = "ПолеАвторизации1" Тогда + ОтобразитьПоляАвторизацииПоСхеме(); + КонецЕсли; + +КонецПроцедуры + +&НаКлиенте +Процедура ПолеАвторизацииНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка) + + // Кнопка выпадающего списка тоже вызывает НачалоВыбора - не глушим её. + Если Не Элемент.КнопкаВыбора Тогда + Возврат; + КонецЕсли; + + СтандартнаяОбработка = Ложь; + #Если ВебКлиент Тогда + Сообщение = Новый СообщениеПользователю; + Сообщение.Текст = "Загрузка ключа из файла недоступна в веб-клиенте"; + Сообщение.Сообщить(); + Возврат; + #КонецЕсли + + ИмяРеквизита = СтрЗаменить(Элемент.Имя, "ПолеАвторизации", "ЗначениеАвторизации"); + Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); + Диалог.Заголовок = "Выберите файл приватного ключа (PEM)"; + Диалог.Фильтр = + "Ключ PEM/TXT (*.pem;*.txt)|*.pem;*.txt|" + + "Все файлы (*.*)|*.*"; + Диалог.МножественныйВыбор = Ложь; + ПараметрыОповещения = Новый Структура("ИмяРеквизита", ИмяРеквизита); + Оповещение = Новый ОписаниеОповещения( + "ЗагрузитьJwtПриватныйКлючИзФайлаЗавершение", + ЭтотОбъект, + ПараметрыОповещения); + Диалог.Показать(Оповещение); + +КонецПроцедуры + +&НаКлиенте +Процедура ЗагрузитьJwtПриватныйКлючИзФайлаЗавершение(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт + + Если ВыбранныеФайлы = Неопределено Или ВыбранныеФайлы.Количество() = 0 Тогда + Возврат; + КонецЕсли; + + ИмяРеквизита = ""; + Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда + ДополнительныеПараметры.Свойство("ИмяРеквизита", ИмяРеквизита); + КонецЕсли; + Если ПустаяСтрока(ИмяРеквизита) Тогда + Возврат; + КонецЕсли; + + ПутьКФайлу = ВыбранныеФайлы[0]; + + #Если НЕ ВебКлиент Тогда + ЧтениеТекста = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8); + ТекстКлюча = ЧтениеТекста.Прочитать(); + ЧтениеТекста.Закрыть(); + #Иначе + Возврат; + #КонецЕсли + + Если ТекстКлюча = Неопределено Тогда + ТекстКлюча = ""; + КонецЕсли; + + ЭтотОбъект[ИмяРеквизита] = ТекстКлюча; + СинхронизироватьПараметрыАвторизацииИзПолейФормы(); КонецПроцедуры @@ -206,19 +277,42 @@ КонецФункции &НаСервере -Функция ОписаниеСхемыАвторизации(Знач ТипАвторизации) +Функция ПоляСхемыАвторизацииДляОтображения(Знач ТипАвторизации, Знач ЗначенияПараметров) + + Возврат ОбъектОбработкиАвторизации().ПоляСхемыАвторизацииДляОтображения( + ТипАвторизации, + ЗначенияПараметров); + +КонецФункции + +&НаКлиентеНаСервереБезКонтекста +Функция ИдентификаторТипаАвторизацииJwtBearer() - Возврат ОбъектОбработкиАвторизации().ОписаниеСхемыАвторизации(ТипАвторизации); + Возврат "JwtBearer"; + +КонецФункции + +&НаКлиентеНаСервереБезКонтекста +Функция КлючПоляАвторизацииJwtАлгоритм() + + Возврат "algorithm"; + +КонецФункции + +&НаКлиентеНаСервереБезКонтекста +Функция КлючПоляАвторизацииJwtПриватныйКлюч() + + Возврат "privateKey"; КонецФункции &НаКлиенте Процедура ОтобразитьПоляАвторизацииПоСхеме() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); МаксимумПолей = МаксимумПолейАвторизацииНаФорме(); - КоличествоПолейСхемы = Схема.Поля.Количество(); + КоличествоПолейСхемы = ПоляСхемы.Количество(); Для Индекс = 1 По МаксимумПолей Цикл @@ -233,10 +327,11 @@ ЭлементПоля.СписокВыбора.Очистить(); ЭлементПоля.РежимВыбораИзСписка = Ложь; ЭлементПоля.КнопкаВыпадающегоСписка = Ложь; + ЭлементПоля.КнопкаВыбора = Ложь; Продолжить; КонецЕсли; - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ЗначениеПоля = ЗначенияПараметров.Получить(ОписаниеПоля.Ключ); Если ЗначениеПоля = Неопределено Тогда ЗначениеПоля = ОписаниеПоля.ЗначениеПоУмолчанию; @@ -248,6 +343,7 @@ ЭлементПоля.РежимПароля = ОписаниеПоля.Секретный; ЭлементПоля.МногострочныйРежим = ОписаниеПоля.Многострочный; ЭлементПоля.Высота = ?(ОписаниеПоля.Многострочный, 5, 1); + ЭлементПоля.КнопкаВыбора = (ОписаниеПоля.Ключ = КлючПоляАвторизацииJwtПриватныйКлюч()); НастроитьСписокВыбораПоляАвторизации(ЭлементПоля, ОписаниеПоля); КонецЦикла; @@ -291,12 +387,16 @@ &НаКлиенте Процедура СинхронизироватьПараметрыАвторизацииИзПолейФормы() - Схема = ОписаниеСхемыАвторизации(ТипАвторизации); - КоличествоПолейСхемы = Мин(Схема.Поля.Количество(), МаксимумПолейАвторизацииНаФорме()); + ЗначенияПараметров = СоответствиеЗначенийПараметровАвторизацииНаКлиенте(ПараметрыАвторизации); + Если ТипАвторизации = ИдентификаторТипаАвторизацииJwtBearer() Тогда + ЗначенияПараметров.Вставить(КлючПоляАвторизацииJwtАлгоритм(), ЗначениеАвторизации1); + КонецЕсли; + ПоляСхемы = ПоляСхемыАвторизацииДляОтображения(ТипАвторизации, ЗначенияПараметров); + КоличествоПолейСхемы = Мин(ПоляСхемы.Количество(), МаксимумПолейАвторизацииНаФорме()); Для Индекс = 1 По КоличествоПолейСхемы Цикл - ОписаниеПоля = Схема.Поля[Индекс - 1]; + ОписаниеПоля = ПоляСхемы[Индекс - 1]; ИмяРеквизита = "ЗначениеАвторизации" + ФорматЦелогоБезГруппировки(Индекс); УстановитьЗначениеПараметраАвторизацииНаКлиенте( ПараметрыАвторизации, @@ -394,3 +494,4 @@ #КонецОбласти // BSLLS:UnusedLocalVariable-on +// BSLLS:LatinAndCyrillicSymbolInWord-on diff --git a/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl b/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl index 6520f2a..e1f12e2 100644 --- a/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl +++ b/src/ExternalDataProcessors/GetManHTTP/ObjectModule.bsl @@ -156,6 +156,12 @@ КонецФункции +Функция КлючПоляАвторизацииJwtПриватныйКлюч() Экспорт + + Возврат "privateKey"; + +КонецФункции + Функция КлючПоляАвторизацииJwtClaims() Экспорт Возврат "claims"; @@ -192,12 +198,72 @@ КонецФункции +Функция АлгоритмJwtHS384() Экспорт + + Возврат "HS384"; + +КонецФункции + Функция АлгоритмJwtHS512() Экспорт Возврат "HS512"; КонецФункции +Функция АлгоритмJwtRS256() Экспорт + + Возврат "RS256"; + +КонецФункции + +Функция АлгоритмJwtRS384() Экспорт + + Возврат "RS384"; + +КонецФункции + +Функция АлгоритмJwtRS512() Экспорт + + Возврат "RS512"; + +КонецФункции + +Функция АлгоритмJwtPS256() Экспорт + + Возврат "PS256"; + +КонецФункции + +Функция АлгоритмJwtPS384() Экспорт + + Возврат "PS384"; + +КонецФункции + +Функция АлгоритмJwtPS512() Экспорт + + Возврат "PS512"; + +КонецФункции + +Функция АлгоритмJwtES256() Экспорт + + Возврат "ES256"; + +КонецФункции + +Функция АлгоритмJwtES384() Экспорт + + Возврат "ES384"; + +КонецФункции + +Функция АлгоритмJwtES512() Экспорт + + Возврат "ES512"; + +КонецФункции + Функция ВидПравилаАвторизацииComputedHeader() Экспорт Возврат "ComputedHeader"; @@ -316,6 +382,12 @@ Истина, Ложь, ""); + ПолеПриватногоКлюча = НовоеПолеСхемыАвторизации( + КлючПоляАвторизацииJwtПриватныйКлюч(), + "Приватный ключ (PEM)", + Истина, + Истина, + ""); ПолеClaims = НовоеПолеСхемыАвторизации( КлючПоляАвторизацииJwtClaims(), "Claims (JSON)", @@ -334,6 +406,7 @@ Схема.Поля.Добавить(ПолеАлгоритма); Схема.Поля.Добавить(ПолеСекрета); + Схема.Поля.Добавить(ПолеПриватногоКлюча); Схема.Поля.Добавить(ПолеClaims); Схема.Поля.Добавить(ПолеTTL); Схема.Правила.Добавить(ПравилоJwt); @@ -511,7 +584,8 @@ // Собирает JWT (header.payload.signature) по параметрам схемы JwtBearer. // // Параметры: -// ЗначенияПараметров - Соответствие - значения полей схемы (algorithm, secret, claims, ttlSeconds). +// ЗначенияПараметров - Соответствие - значения полей схемы +// (algorithm, secret, privateKey, claims, ttlSeconds). // // Возвращаемое значение: // Строка - компактный JWT или пустая строка при отсутствии данных для подписи. @@ -526,12 +600,10 @@ АлгоритмПоУмолчанию); Алгоритм = НормализованныйАлгоритмJwt(АлгоритмИзПараметров); - КлючСекрета = КлючПоляАвторизацииJwtСекрет(); - СекретИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( - ЗначенияПараметров, - КлючСекрета, - ""); - Секрет = Строка(СекретИзПараметров); + МатериалПодписи = МатериалПодписиJwtИзПараметров(ЗначенияПараметров, Алгоритм); + Если ПустаяСтрока(МатериалПодписи) Тогда + Возврат ""; + КонецЕсли; КлючClaims = КлючПоляАвторизацииJwtClaims(); ClaimsИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( @@ -550,17 +622,20 @@ Payload = ПрочитатьClaimsJwtИзJSON(ClaimsТекст); ПрименитьTTLКClaimsJwt(Payload, TTLСтрока); - ЗаголовокJwt = Новый Структура; - ЗаголовокJwt.Вставить("alg", Алгоритм); - ЗаголовокJwt.Вставить("typ", "JWT"); - - ЧастьЗаголовка = Base64URLИзСтрокиUTF8(ЗаписатьЗначениеВJSONСтрокуАвторизации(ЗаголовокJwt)); - ЧастьPayload = Base64URLИзСтрокиUTF8(ЗаписатьЗначениеВJSONСтрокуАвторизации(Payload)); - ПодписываемыеДанные = ЧастьЗаголовка + "." + ЧастьPayload; + Токен = Новый ТокенДоступа; + Для Каждого КлючИЗначение Из Payload Цикл + Токен.ПолезнаяНагрузка.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение); + КонецЦикла; - Подпись = HMACJwt(Секрет, ПодписываемыеДанные, Алгоритм); + АлгоритмПодписи = АлгоритмПодписиТокенаДоступаПоИмениJwt(Алгоритм); + Попытка + Токен.Подписать(АлгоритмПодписи, МатериалПодписи); + Исключение + ВызватьИсключение "Не удалось подписать JWT (проверьте PEM и алгоритм): " + + ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); + КонецПопытки; - Возврат ПодписываемыеДанные + "." + Base64URLИзДвоичныхДанных(Подпись); + Возврат Строка(Токен); КонецФункции @@ -570,11 +645,127 @@ Если АлгоритмНорм = АлгоритмJwtHS512() Тогда Возврат АлгоритмJwtHS512(); КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtHS384() Тогда + Возврат АлгоритмJwtHS384(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtRS512() Тогда + Возврат АлгоритмJwtRS512(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtRS384() Тогда + Возврат АлгоритмJwtRS384(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtRS256() Тогда + Возврат АлгоритмJwtRS256(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtPS512() Тогда + Возврат АлгоритмJwtPS512(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtPS384() Тогда + Возврат АлгоритмJwtPS384(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtPS256() Тогда + Возврат АлгоритмJwtPS256(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtES512() Тогда + Возврат АлгоритмJwtES512(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtES384() Тогда + Возврат АлгоритмJwtES384(); + КонецЕсли; + Если АлгоритмНорм = АлгоритмJwtES256() Тогда + Возврат АлгоритмJwtES256(); + КонецЕсли; Возврат АлгоритмJwtHS256(); КонецФункции +Функция ЭтоАлгоритмJwtHs(Знач Алгоритм) Экспорт + + Возврат Алгоритм = АлгоритмJwtHS256() + Или Алгоритм = АлгоритмJwtHS384() + Или Алгоритм = АлгоритмJwtHS512(); + +КонецФункции + +Функция ЭтоАлгоритмJwtRs(Знач Алгоритм) Экспорт + + Возврат Алгоритм = АлгоритмJwtRS256() + Или Алгоритм = АлгоритмJwtRS384() + Или Алгоритм = АлгоритмJwtRS512(); + +КонецФункции + +Функция ЭтоАлгоритмJwtPs(Знач Алгоритм) Экспорт + + Возврат Алгоритм = АлгоритмJwtPS256() + Или Алгоритм = АлгоритмJwtPS384() + Или Алгоритм = АлгоритмJwtPS512(); + +КонецФункции + +Функция ЭтоАлгоритмJwtEs(Знач Алгоритм) Экспорт + + Возврат Алгоритм = АлгоритмJwtES256() + Или Алгоритм = АлгоритмJwtES384() + Или Алгоритм = АлгоритмJwtES512(); + +КонецФункции + +Функция ЭтоАлгоритмJwtСПриватнымКлючом(Знач Алгоритм) Экспорт + + Возврат ЭтоАлгоритмJwtRs(Алгоритм) + Или ЭтоАлгоритмJwtPs(Алгоритм) + Или ЭтоАлгоритмJwtEs(Алгоритм); + +КонецФункции + +// Возвращает поля схемы авторизации для отображения на форме. +// Для JwtBearer скрывает secret на RS*/PS*/ES* и privateKey на HS* (как в Postman); +// значения скрытых ключей в таблице параметров сохраняются. +// +// Параметры: +// ТипАвторизации - Строка - идентификатор типа авторизации. +// ЗначенияПараметров - Соответствие - текущие значения полей (нужен algorithm для JwtBearer). +// +// Возвращаемое значение: +// Массив из Структура - описания полей схемы для UI-слотов. +// +Функция ПоляСхемыАвторизацииДляОтображения(Знач ТипАвторизации, Знач ЗначенияПараметров) Экспорт + + Схема = ОписаниеСхемыАвторизации(ТипАвторизации); + Если ТипАвторизации <> ИдентификаторТипаАвторизацииJwtBearer() Тогда + Возврат Схема.Поля; + КонецЕсли; + + АлгоритмИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючПоляАвторизацииJwtАлгоритм(), + АлгоритмJwtHS256()); + Алгоритм = НормализованныйАлгоритмJwt(АлгоритмИзПараметров); + ПоказыватьСекрет = Не ЭтоАлгоритмJwtСПриватнымКлючом(Алгоритм); + + Результат = Новый Массив; + КлючСекрета = КлючПоляАвторизацииJwtСекрет(); + КлючПриватногоКлюча = КлючПоляАвторизацииJwtПриватныйКлюч(); + + Для Каждого ОписаниеПоля Из Схема.Поля Цикл + + Если ОписаниеПоля.Ключ = КлючСекрета И Не ПоказыватьСекрет Тогда + Продолжить; + КонецЕсли; + Если ОписаниеПоля.Ключ = КлючПриватногоКлюча И ПоказыватьСекрет Тогда + Продолжить; + КонецЕсли; + + Результат.Добавить(ОписаниеПоля); + + КонецЦикла; + + Возврат Результат; + +КонецФункции + Функция НормализованныйРежимДобавленияApiKey(Знач Режим) Экспорт РежимНорм = ВРег(СокрЛП(Строка(Режим))); @@ -664,11 +855,41 @@ Результат = Новый Массив; АлгоритмHS256 = АлгоритмJwtHS256(); + АлгоритмHS384 = АлгоритмJwtHS384(); АлгоритмHS512 = АлгоритмJwtHS512(); + АлгоритмRS256 = АлгоритмJwtRS256(); + АлгоритмRS384 = АлгоритмJwtRS384(); + АлгоритмRS512 = АлгоритмJwtRS512(); + АлгоритмPS256 = АлгоритмJwtPS256(); + АлгоритмPS384 = АлгоритмJwtPS384(); + АлгоритмPS512 = АлгоритмJwtPS512(); + АлгоритмES256 = АлгоритмJwtES256(); + АлгоритмES384 = АлгоритмJwtES384(); + АлгоритмES512 = АлгоритмJwtES512(); ВариантHS256 = НовыйВариантВыбораПоляАвторизации(АлгоритмHS256, АлгоритмHS256); + ВариантHS384 = НовыйВариантВыбораПоляАвторизации(АлгоритмHS384, АлгоритмHS384); ВариантHS512 = НовыйВариантВыбораПоляАвторизации(АлгоритмHS512, АлгоритмHS512); + ВариантRS256 = НовыйВариантВыбораПоляАвторизации(АлгоритмRS256, АлгоритмRS256); + ВариантRS384 = НовыйВариантВыбораПоляАвторизации(АлгоритмRS384, АлгоритмRS384); + ВариантRS512 = НовыйВариантВыбораПоляАвторизации(АлгоритмRS512, АлгоритмRS512); + ВариантPS256 = НовыйВариантВыбораПоляАвторизации(АлгоритмPS256, АлгоритмPS256); + ВариантPS384 = НовыйВариантВыбораПоляАвторизации(АлгоритмPS384, АлгоритмPS384); + ВариантPS512 = НовыйВариантВыбораПоляАвторизации(АлгоритмPS512, АлгоритмPS512); + ВариантES256 = НовыйВариантВыбораПоляАвторизации(АлгоритмES256, АлгоритмES256); + ВариантES384 = НовыйВариантВыбораПоляАвторизации(АлгоритмES384, АлгоритмES384); + ВариантES512 = НовыйВариантВыбораПоляАвторизации(АлгоритмES512, АлгоритмES512); Результат.Добавить(ВариантHS256); + Результат.Добавить(ВариантHS384); Результат.Добавить(ВариантHS512); + Результат.Добавить(ВариантRS256); + Результат.Добавить(ВариантRS384); + Результат.Добавить(ВариантRS512); + Результат.Добавить(ВариантPS256); + Результат.Добавить(ВариантPS384); + Результат.Добавить(ВариантPS512); + Результат.Добавить(ВариантES256); + Результат.Добавить(ВариантES384); + Результат.Добавить(ВариантES512); Возврат Результат; КонецФункции @@ -830,136 +1051,67 @@ КонецФункции -Функция ЗаписатьЗначениеВJSONСтрокуАвторизации(Знач Значение) - - Запись = Новый ЗаписьJSON; - Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет)); - ЗаписатьJSON(Запись, Значение); - Возврат Запись.Закрыть(); - -КонецФункции - -Функция Base64URLИзСтрокиUTF8(Знач СтрокаДанных) - - Возврат Base64URLИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзСтроки(СтрокаДанных, КодировкаТекста.UTF8)); - -КонецФункции - -Функция Base64URLИзДвоичныхДанных(Знач ДвоичныеДанные) - - Результат = Base64Строка(ДвоичныеДанные); - Результат = СтрЗаменить(Результат, Символы.ПС, ""); - Результат = СтрЗаменить(Результат, Символы.ВК, ""); - Результат = СтрЗаменить(Результат, "+", "-"); - Результат = СтрЗаменить(Результат, "/", "_"); - - Пока Прав(Результат, 1) = "=" Цикл - Результат = Лев(Результат, СтрДлина(Результат) - 1); - КонецЦикла; - - Возврат Результат; - -КонецФункции - -Функция HMACJwt(Знач Секрет, Знач Данные, Знач Алгоритм) +Функция АлгоритмПодписиТокенаДоступаПоИмениJwt(Знач Алгоритм) Если Алгоритм = АлгоритмJwtHS512() Тогда - Возврат HMACПоХешФункции(Секрет, Данные, ХешФункция.SHA512, РазмерБлокаHmacSha512()); + Возврат АлгоритмПодписиТокенаДоступа.HS512; КонецЕсли; - - Возврат HMACПоХешФункции(Секрет, Данные, ХешФункция.SHA256, РазмерБлокаHmacSha256()); - -КонецФункции - -// HMAC (RFC 2104) поверх встроенного ХешированиеДанных. -// -// Параметры: -// КлючСтрока - Строка - секретный ключ. -// ДанныеСтрока - Строка - подписываемые данные. -// ТипХеша - ХешФункция - SHA256 или SHA512. -// РазмерБлока - Число - размер блока HMAC в байтах (64 для SHA256, 128 для SHA512). -// -// Возвращаемое значение: -// ДвоичныеДанные - код аутентификации сообщения. -// -Функция HMACПоХешФункции(Знач КлючСтрока, Знач ДанныеСтрока, Знач ТипХеша, Знач РазмерБлока) - - Ключ = ПолучитьДвоичныеДанныеИзСтроки(Строка(КлючСтрока), КодировкаТекста.UTF8); - Данные = ПолучитьДвоичныеДанныеИзСтроки(Строка(ДанныеСтрока), КодировкаТекста.UTF8); - - Если Ключ.Размер() > РазмерБлока Тогда - Ключ = ХешСуммаДвоичныхДанных(Ключ, ТипХеша); + Если Алгоритм = АлгоритмJwtHS384() Тогда + Возврат АлгоритмПодписиТокенаДоступа.HS384; КонецЕсли; - - КлючHex = ПолучитьHexСтрокуИзДвоичныхДанных(Ключ); - Если Ключ.Размер() < РазмерБлока Тогда - КлючHex = Лев(КлючHex + ПовторитьHexБайт("00", РазмерБлока), РазмерБлока * ДлинаHexСимволовНаБайт()); + Если Алгоритм = АлгоритмJwtRS512() Тогда + Возврат АлгоритмПодписиТокенаДоступа.RS512; + КонецЕсли; + Если Алгоритм = АлгоритмJwtRS384() Тогда + Возврат АлгоритмПодписиТокенаДоступа.RS384; + КонецЕсли; + Если Алгоритм = АлгоритмJwtRS256() Тогда + Возврат АлгоритмПодписиТокенаДоступа.RS256; + КонецЕсли; + Если Алгоритм = АлгоритмJwtPS512() Тогда + Возврат АлгоритмПодписиТокенаДоступа.PS512; + КонецЕсли; + Если Алгоритм = АлгоритмJwtPS384() Тогда + Возврат АлгоритмПодписиТокенаДоступа.PS384; + КонецЕсли; + Если Алгоритм = АлгоритмJwtPS256() Тогда + Возврат АлгоритмПодписиТокенаДоступа.PS256; + КонецЕсли; + Если Алгоритм = АлгоритмJwtES512() Тогда + Возврат АлгоритмПодписиТокенаДоступа.ES512; + КонецЕсли; + Если Алгоритм = АлгоритмJwtES384() Тогда + Возврат АлгоритмПодписиТокенаДоступа.ES384; + КонецЕсли; + Если Алгоритм = АлгоритмJwtES256() Тогда + Возврат АлгоритмПодписиТокенаДоступа.ES256; КонецЕсли; - КлючБуфер = ПолучитьБуферДвоичныхДанныхИзHexСтроки(КлючHex); - - Ipad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьHexБайт("36", РазмерБлока)); - Opad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьHexБайт("5c", РазмерБлока)); - Ipad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер); - Opad.ЗаписатьПобитовоеИсключительноеИли(0, КлючБуфер); - - ВнутренниеДанные = СоединитьДвоичныеДанныеИзБуферов( - Ipad, - ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Данные)); - ВнутреннийХеш = ХешСуммаДвоичныхДанных(ВнутренниеДанные, ТипХеша); - ВнешниеДанные = СоединитьДвоичныеДанныеИзБуферов( - Opad, - ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ВнутреннийХеш)); - - Возврат ХешСуммаДвоичныхДанных(ВнешниеДанные, ТипХеша); - -КонецФункции - -Функция ХешСуммаДвоичныхДанных(Знач ДвоичныеДанные, Знач ТипХеша) - - Хеширование = Новый ХешированиеДанных(ТипХеша); - Хеширование.Добавить(ДвоичныеДанные); - Возврат Хеширование.ХешСумма; - -КонецФункции - -Функция ПовторитьHexБайт(Знач HexБайт, Знач Количество) - - Результат = ""; - ДлинаЦели = Количество * ДлинаHexСимволовНаБайт(); - Пока СтрДлина(Результат) < ДлинаЦели Цикл - Результат = Результат + HexБайт; - КонецЦикла; - - Возврат Результат; - -КонецФункции - -Функция СоединитьДвоичныеДанныеИзБуферов(Знач Буфер1, Знач Буфер2) - - Данные1 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер1); - Данные2 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Буфер2); - Части = Новый Массив; - Части.Добавить(Данные1); - Части.Добавить(Данные2); - Возврат СоединитьДвоичныеДанные(Части); - -КонецФункции - -Функция РазмерБлокаHmacSha256() - Возврат 64; + Возврат АлгоритмПодписиТокенаДоступа.HS256; КонецФункции -Функция РазмерБлокаHmacSha512() +Функция МатериалПодписиJwtИзПараметров(Знач ЗначенияПараметров, Знач Алгоритм) - Возврат 128; + Если ЭтоАлгоритмJwtСПриватнымКлючом(Алгоритм) Тогда + КлючПоля = КлючПоляАвторизацииJwtПриватныйКлюч(); + ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючПоля, + ""); + Возврат Строка(ЗначениеИзПараметров); + КонецЕсли; -КонецФункции - -Функция ДлинаHexСимволовНаБайт() + Если ЭтоАлгоритмJwtHs(Алгоритм) Тогда + КлючПоля = КлючПоляАвторизацииJwtСекрет(); + ЗначениеИзПараметров = ЗначениеПараметраАвторизацииИзСоответствия( + ЗначенияПараметров, + КлючПоля, + ""); + Возврат Строка(ЗначениеИзПараметров); + КонецЕсли; - Возврат 2; + Возврат ""; КонецФункции