diadoc / diadocapi-docs

HTTP API documentation - http://api-docs.diadoc.ru/
40 stars 92 forks source link

AuthenticateConfirm авторизация по сертификату #244

Closed ahw85389 closed 6 years ago

ahw85389 commented 6 years ago

Прошу помочь запустить авторизацию по сертификату. Кабинет и сертификат тестовые. Сертификат выдан "O = ЗАО ПФ СКБ Контур". При авторизации по логину и паролю подписание, отправка и патчинг работают.

  1. метод /Authenticate - выдаваемый токен будет зашифрован в адрес пользовательского сертификата. В этом случае тело ответа следует интерпретировать как структуру CMS EnvelopedData в DER-кодировке. Не понял, надо ли из этой структуры что то выдергивать и как. Расшифровывал тело сертификатом (пробовал и не расшифровывая), кодировал в base64 строку, далее использовал как ddauth_token. При первом же следующем методе с параметром ddauth_token получаю ошибку: 401: Invalid auth token

  2. метод V2/Authenticate. авторизация по сертификату является двухфазной. В этом случае ответ следует интерпретировать как зашифрованную строку... Подтвердить методом /V2/AuthenticateConfirm.

2.1. /V2/AuthenticateConfirm без thumbprint. В теле передаю base64 сертификата, в параметре token - расшифрованный ответ V2/Authenticate и закодированный в base64. Получаю: 403: Ключ не соответствует идентификатору

2.2. /V2/AuthenticateConfirm с thumbprint=jDJoyYrNOrb2lwyU2Me4Eecd1Mo=. Ругается: 403: ErrorCode: Auth.RndBytesNotFound (Http.Forbidden)

einfoman commented 6 years ago

Добрый день!

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

Во-вторых, в пункте 2.2 наверное имелся ввиду параметр token, а не thumbprint.

ahw85389 commented 6 years ago

Согласен на любую версию. Но для общего развития интересно, чем первая не угодила? Если из соображений безопасности, то злоумышленнику не тяжелее от используемого мной (клиентом) метода, в отличие от доступности (на сервере диадок) первого метода.

Пункт 2.2. аналогичен 2.1., но содержит дополнительно параметр thumbprint. Т.е. и 2.1. и 2.2. начинаются /V2/AuthenticateConfirm?token=...

thumbprint: отпечаток сертификата пользователя (опциональный). Если на сервер передается одновременно и отпечаток сертификата, и сертификат в теле запроса, то отпечаток сертификата имеет более высокий приоритет. В этом случае сертификат из тела запроса игнорируется;

ahw85389 commented 6 years ago

Удалил Vipnet - Ничего не изменилось. Удалил, установил CryptoPro - по п.1 - ошибка не изменилась, а по пунктам 2.х иногда ошибка стала такой:

400: Cannot parse token: Invalid length for a Base-64 char array or string.

Хотя длина строки в параметре token делится на 3 без остатка. Метод /Authenticate возвращает тело 755 байт. После расшифровки получается 104 байт. После преобразования в base64 строку - 354 символа. которые замечательно делятся на 3: 118 символов. Метод V2/Authenticate возвращает тело 910 байт. После расшифровки получается 256 байт. После преобразования в base64 строку - 144 символа. которые замечательно делятся на 3: 48 символов.

Какие длины должны быть?

einfoman commented 6 years ago

Я имел ввиду, что в описании проблемы вместо параметра token указан thumbprint.

Но сейчас я посмотрел, реально отправляется запрос с thumbprint=jDJoyYrNOrb2lwyU2Me4Eecd1Mo=. Так вот, это некорректное значение для отпечатка. Обычно отпечаток указывается последовательностью 16-ричных символов.

ahw85389 commented 6 years ago

Теперь вариант 2.2 V2/AuthenticateConfirm?token=7jZOlHN . . . dhQDsJxA==&thumbprint=8C3268C98ACD3AB6F6970C94D8C.... стал возвращать: 403: Ключ не соответствует идентификатору

Вероятно в описании стоит отметить ожидаемый формат thumbprint. Иначе надо следовать "Бинарный контент следует передавать с помощью base64 - строк." из http://api-docs.diadoc.ru/ru/latest/DataStructures.html

ahw85389 commented 6 years ago

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

einfoman commented 6 years ago

Добрый день! Я посмотрел логи. Расклад такой 21 сентября отправлялись запросы, которые формально были корректными, но они реально возвращали ошибку Ключ не соответствует идентификатору Начиная с 26 сентября запрос падает с ошибкой Cannot parse token: Invalid length for a Base-64 char array or string. Т.е. передается некорректное значение параметра token

ahw85389 commented 6 years ago

Это я пробовую субирать переносы строк, с которыми возвращает втроенная функция преобразования в base64. Но когда пробую авторизацию по сертификату, пробую сразу много вариантов. Потому ошибка не только "Cannot parse token", но и "Ключ не соответствует идентификатору".

Вот только что (2017-09-09 13:09) сделал несколько запросов. Получал ошибку "Ключ не соответствует идентификатору".

einfoman commented 6 years ago

А что-то я не вижу в логах предварительного вызова метода V2/Authenticate. Откуда вы получаете ключ, который надо расшифровать?

ahw85389 commented 6 years ago

Как жеж, обязательно V2/Authenticate, дальше тело ответа 30 82 03 7A 06 09 2A 86 48 86 F7 0D 01 07 03 A0 82 03 6B... расшифровываю и получаю EC CB 43 DC EF 17 C5 55 C8 08 83 BE 10 04 67 53 81 4A 3D 42, которое преобразовываю в base64 и получаю token =7MtD3O8XxVXICIO+EAR..... потом вызываю V2/AuthenticateConfirm?token="+token+"&thumbprint="+Отпечаток. Отпечаток = 31F558E70B40C4...

einfoman commented 6 years ago

Т.к. token содержит недопустимые символы (например, "/") с точки зрения url'а (https://en.wikipedia.org/wiki/Query_string#URL_encoding), то его значение нужно заенкодить с помощью функций типа urlencode(), HttpUtility.UrlEncode и т.п.

ahw85389 commented 6 years ago

Спасибо большое. Заработало. Но в 4 разах из 10. :) Не меняя код, часто получаю ошибку: 403: ErrorCode: Auth.RndBytesNotFound (Http.Forbidden)

Для тех кто на 1С:

ДвоичныеДанныеОтвета = МенеджерКриптографии.Расшифровать(ДвоичныеДанныеТелоОтветаV2Authenticate); token = Base64Строка(ДвоичныеДанныеОтвета); token = КодироватьСтроку(token, СпособКодированияСтроки.КодировкаURL) ;

einfoman commented 6 years ago

Судя по логам, у вас все получилось. Закрываю тикет

einfoman commented 6 years ago

Добрый день! Заметил закономерность, когда запросы на подтверждение аутентификации возвращают 400 ошибку.

Вот пример присылаемого токена, когда запрос успешный:

we2cxvsex3na78affwid0lgy9jjdojtcjnp%2bwdhgrhvkh2vyfalwr9jj7yxjpziy%0d%0a6ebhscbr%2b4l%2fryxrkexy7jkdwlvv3yugzfoarc%2bajit66qozblciwgdooieyowiw%0d%0axuswtg1hpn2dpxlzbxnbgkp%2bszh8fsa88qh5dutnvzn7kq4chxbvvg688bugbn3b%0d%0a3sude0wpxva7zofvlkturpbcndukwuxqhfvohxtcihn6mu1wfuiv1qo7odnvo8x7%0d%0a3ubzgnwkypugigka%2bf9ludliuuyrige1u%2f3%2fztfrpm4ljlblpfk79s%2b4q0v5koko%0d%0alu2iv0nn%2f2sd%2fxlyapjzrg%3d%3d

Если вызвать на этой строке функция url-декодинга, то получится нормальный base64:

we2cxvsex3na78affwid0lgy9jjdojtcjnp+wdhgrhvkh2vyfalwr9jj7yxjpziy
6ebhscbr+4l/ryxrkexy7jkdwlvv3yugzfoarc+ajit66qozblciwgdooieyowiw
xuswtg1hpn2dpxlzbxnbgkp+szh8fsa88qh5dutnvzn7kq4chxbvvg688bugbn3b
3sude0wpxva7zofvlkturpbcndukwuxqhfvohxtcihn6mu1wfuiv1qo7odnvo8x7
3ubzgnwkypugigka+f9ludliuuyrige1u/3/ztfrpm4ljlblpfk79s+4q0v5koko
lu2iv0nn/2sd/xlyapjzrg==

Теперь пример токена, когда запрос заканчивается ошибкой:

isqawmqnddcea89huakkxcfpd7q886c%252bmvd85t9sfevmqmqamm%252fxo4%252f9urqncs2i%250d%250avazkrob04ayk%252f4yt3jn6hf8vnlsmy0qzzf6lzdfhaacf0vgju9r6k5w0enu3l4im%250d%250aksftzfv40kohhiyhdsvqgvdvf5b2yfsv2b8%252bymt8nbqava98xyxbwwsbhnz4lcis%250d%250ad%252fs6q7hgnlhrqhkuzjwgdgop7ahgrpnfhm%252bbb55f%252flifi%252bxmcrbhrymf7wovk4wz%250d%250axdhmetwfbxhrrfmt9y%252blnlfhlpbto7kvskz8qkqxq51orox6o1vsjwewkqhqfsax%250d%250anbsqcwwfpjc7hbgnddvttq%253d%253d

Если его декодировать, то получится вот что:

isqawmqnddcea89huakkxcfpd7q886c%2bmvd85t9sfevmqmqamm%2fxo4%2f9urqncs2i%0d%0avazkrob04ayk%2f4yt3jn6hf8vnlsmy0qzzf6lzdfhaacf0vgju9r6k5w0enu3l4im%0d%0aksftzfv40kohhiyhdsvqgvdvf5b2yfsv2b8%2bymt8nbqava98xyxbwwsbhnz4lcis%0d%0ad%2fs6q7hgnlhrqhkuzjwgdgop7ahgrpnfhm%2bbb55f%2flifi%2bxmcrbhrymf7wovk4wz%0d%0axdhmetwfbxhrrfmt9y%2blnlfhlpbto7kvskz8qkqxq51orox6o1vsjwewkqhqfsax%0d%0anbsqcwwfpjc7hbgnddvttq%3d%3d

Т.е. не base64. Но! Если эту строку еще раз декодировать, то получится корректный base64:

isqawmqnddcea89huakkxcfpd7q886c+mvd85t9sfevmqmqamm/xo4/9urqncs2i
vazkrob04ayk/4yt3jn6hf8vnlsmy0qzzf6lzdfhaacf0vgju9r6k5w0enu3l4im
ksftzfv40kohhiyhdsvqgvdvf5b2yfsv2b8+ymt8nbqava98xyxbwwsbhnz4lcis
d/s6q7hgnlhrqhkuzjwgdgop7ahgrpnfhm+bb55f/lifi+xmcrbhrymf7wovk4wz
xdhmetwfbxhrrfmt9y+lnlfhlpbto7kvskz8qkqxq51orox6o1vsjwewkqhqfsax
nbsqcwwfpjc7hbgnddvttq==

Т.е. почему-то иногда происходит двойное кодирование токена.

ahw85389 commented 6 years ago

Спасибо за уточнение. Виню, платформу 1с 8.3.10.2466. На платформе 1с 8.3.9.2170 авторизация по сертификату вообще не проходит тем же кодом.

kudnayce commented 5 years ago

Спасибо большое. Заработало. Но в 4 разах из 10. :) Не меняя код, часто получаю ошибку: 403: ErrorCode: Auth.RndBytesNotFound (Http.Forbidden)

Для тех кто на 1С:

ДвоичныеДанныеОтвета = МенеджерКриптографии.Расшифровать(ДвоичныеДанныеТелоОтветаV2Authenticate); token = Base64Строка(ДвоичныеДанныеОтвета); token = КодироватьСтроку(token, СпособКодированияСтроки.КодировкаURL) ;

Спасибо вам за строчки по 1С вы очень сильно помогли.