Windows: Client Certificate Authentication Bug

Коллеги всем привет.

Пару дней назад столкнулся с пренеприятнейшим багом (а возможно фичей, кто его знает), суть которого в том, что Windows (IIS/IIS Express) не хочет делать Client Certificate Authentication. Баг пофикшен, однако достаточно нетривиальным путём. Собственно поэтому и решил разшарить опыт, вдруг кто-то столкнётся с подобным и вспомнит этот пост.

Итак по порядку.

Суть задачи была в следующем — создать клиентское .NET Core приложение, которое умеет цеплять к реквесту клиентский сретификат и делать запрос на сервер. Подробности функционала приложения опущу ибо не суть важно.

Приложение было создано, созданы два сертификата, самоподписанный CA Root, который был установлен на сервере в Local Machine/Trusted Root Certificates Authority. А затем клиентский, который подписан рутовым и который собственно цеплялся к реквесту:

using(var cert = new X509Certificate2(pathToCertificate, "cert_password"))
{
  // Create request
  // ...
  request.ClientCertificates.Add(cert);
  // Get response
  //...
}

В IIS был включён SSL, в SSL Settings взведён флаг Require SSL и выбран Require для Client Certificates (хотя можно и просто Accept, но не суть).

Т.е. всё было сделано по науке, но, не через данный клиент, ни через Google Chrome (при выборе клентского сертификата), ни через другие тули типа Postman, RESTlet сервер не хотел аутентифицировать запрос. Отваливался с такими ошибками.

  • 403.7 — Client certificate required
  • 403.16 — Client certificate is untrusted or invalid

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

Внимание, если в «Trusted Root Certification Authorities» есть хотя бы один не самоподписанный серитфикат, то аутентификация с клиентским сертификатом не будет работать.

Вот PowerShell script который находит такие сертификаты:

Get-ChildItem cert:\LocalMachine\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject}

Их необходимо удалить и тогда внезапно всё заработает, покрайней мере в моём случае это помогло (когда до по ошибке, на одном из проектов, добавил не туда несколько сертиков и потом не подчистил).

Т.е. если Вы случайно на сервере добавите такой сертик, то все Ваши приложения перестанут работать.

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

Оригинальная статья, в которой нашёл фикс

👍НравитсяПонравилось0
В избранноеВ избранном0
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
X509Certificate2 cert = new X509Certificate2

По хорошему советую — заверни вот это вот в using или сделай ему dispose.
snede.net/...​erous-constructor-in-net

Этот код приведён только для иллюстрации, только что бы показать идею. А так до да, если объект реализует IDisposable, то по хорошему его нужно заворачивать в using...

UPD. Спасибо за ссылку, не знал этого нюанса. Код поправил, дабы не подавать дурной пример.

Я тоже не знал. Пока терабайт данных не пропал куда-то в никуда :) (виновником была опен-сорсная библиотека)

Насколько я понял работа с сертификатами ведётся средствами .NET Core, без использования дополнительных библиотек.
Или это какой-то другой кейс?

Подписаться на комментарии