img3

© 2014 - 2024 esia.pro

Библиотека авторизации через ЕСИА (C# .NET)

1 Общее описание

Библиотека содержит набор функций реализованных на языке программирования C# позволяющих организовать взаимодействие с сервисами Единой системы идентификации и аутентификации (ЕСИА) по протоколу OAuth 2.0. Подробную информацию о данном протоколе и принципах взаимодействия с ЕСИА можно получить в методических рекомендациях по использованию ЕСИА

2 Перечень поставляемых файлов

В состав файлов, поставляемых с библиотекой, входят следующие:

  • OAuth2 - директория, в которой содержатся основные файлы библиотеки;
    • ScopeUsr - директория моделей физ. лица;
      • PersonDocument.cs - модель для представления данных по документам физ. лица;
      • PersonInfo.cs - модель для представления базового набора данных о пользователе (ФИО, СНИЛС, ИНН и т.п.);
      • PersonContact.cs - модель для представления контактных данных пользователя;
      • PersonAddress.cs - модель для представления данных по адресам пользователя;
      • PersonOrg.cs - модель для представления базового набора данных по организациям пользователя;
      • PersonVehicle.cs - модель для представления данных по транспортным средствам пользователя;
      • PersonKid.cs - сведения об отдельной записи в перечне детей физического лица
    • ScopeOrg - директория моделей организации;
      • OrgDetails.cs - данные об организации;
    • LoginRequest.cs - информация для выполнения запроса авторизации;
    • IAuthService.cs - сервис, отвечающий за авторизацию, получение токена доступа, его обновление и выход;
    • AuthState.cs - текущее состояние авторизации;
    • IAuthStateStorage.cs - интерфейс хранилища авторизационных данных
    • EsiaException.cs - ошибки ЕСИА;
    • AuthorizationRequiredException.cs - ошибка, возникающая, если необходимо авторизоваться;
    • EsiaAuthService.cs - реализация сервиса авторизации для ЕСИА;
    • Configuration.cs - конфигурация сервисов библиотеки;
    • AccessTokenRefresher.cs - обновление токена доступа;
    • AccessTokenResponse.cs - ответ от ЕСИА с результатами аутентификации;
    • AccessTokenRequester.cs - получение токена доступа;
    • AccessTokenVerifier.cs - проверка токена доступа на валидность;
    • IStateGenerator.cs - интерфейс генератора идентификаторов state;
    • IDateProvider.cs - интерфейс поставщика времени;
    • EsiaDomain.cs - основные домены ЕСИА;
    • Scope.cs - предоставляемые наборы данных;
    • AccessType.cs - тип доступа к ресурсам;
    • UuidStateGenerator.cs - state генератор, основанный на UUID;
    • RealtimeDateProvider.cs - поставщик реального времени;
    • LoginUrlBuilder.cs - формирование URL для запроса авторизационного кода;
    • Parameters.cs - набор различных констант параметров для авторизации в ЕСИА;
    • LoginUrlBuilderV1.cs - формирование URL для запроса авторизационного кода V1 (устаревшее);
    • Utils.cs - различные вспомогательные функции;
    • LoginUrlBuilderV2.cs - формирование URL для запроса авторизационного кода V2;
    • AccessTokenRequesterV1.cs - реализация получения токена доступа V1 (устаревшее);
    • AccessTokenRefresherV1.cs - обновление токена доступа V1;
    • TokenEndpointV1.cs - общий код для формирования URL получения и обновления маркера доступа;
    • PersonInfoService.cs - возвращает внутренний код пользователя ЕСИА;
    • AuthorizedHttpClient.cs - HTTP клиент с поддержкой авторизации;
    • AccessTokenRequesterV3.cs - реализация получения токена доступа V3;
    • EsiaTokenVerifier.cs - проверка маркера доступа ЕСИА на валидность. Используемые алгоритмы ГОСТ 3410-2012-256, RSA 256;
    • ParametrizedScope.cs - разрешение на получения набора данных с поддержкой параметров;
    • SimpleScope.cs - разрешение на получение набора даных без дополнительных параметров;
    • IScope.cs - интерфейс разрешения на получение набора данных;
  • Utils - различные утилитарные классы;
    • IRequest.cs - адаптер к объекту запроса платформы приложения;
    • BaseException.cs - базовое исключение библиотеки;
    • ParameterRequiredException.cs - ошибка, возникающая при отсутствии требуемого параметра;
    • CustomDateTimeConverter.cs - конвертация строки в дату в моделях данных;
    • AutoToStringExtension.cs - преобразование объекта в строку для отладки;
  • Http - классы, относящиеся к HTTP запросам;
    • HttpResponse.cs - HTTP ответ;
    • Params.cs - список параметров “ключ-значение”;
    • Constants.cs - различные константы используемые с протоколом HTTP;
    • HttpRequest.cs - HTTP запрос;
    • HttpMethod.cs - HTTP методы;
    • IHttpClient.cs - интерфейс HTTP клиента;
    • SystemHttpClient.cs - стандартная реализация HTTP клиента;
    • HttpClientLogWrapper.cs - прокси, который логирует HTTP запросы, проходящие через HTTP клиент;
    • HttpResponseException.cs - HTTP исключение;
  • Crypto - крипросервисы;
    • ICryptoService.cs - интерфейс крипто-сервиса.
    • SignAlgorithm.cs - поддерживаемые алгоритмы подписания
    • VerifyAlgorithm.cs - поддерживаемые алгоритмы верификации подписи
    • HashAlgorithm.cs - поддерживаемые алгоритмы хеширования
    • OpenSsl - Криптосервис использующий openssl;
      • OpenSslCryptoService.cs - крипто сервис, использующий openssl с плагином GOST;
      • ICertWithKey.cs - сертификат и приватный ключ;
      • CertWithKey.cs - указывает на внешние файлы сертификата и ключа. Без владения;
      • TempCertWithKey.cs - указывает на временно сгенерированные файлы сертификата и ключа. Владеет ими, в Dispose удаляет;
      • KeyStoreLoader.cs - загрузка сертификата и ключа из pkcs12. Создает временные файлы с сертификатом и ключом;
      • OpenSslExecutor.cs - стандартная реализация исполнителя команд openssl;
      • IOpenSslExecutor.cs - исполнитель команд openssl;
      • Utils.cs - утилитарные функции;
    • Signer - криптосервис, использующий сетевой сервис подписания Signer;
      • SignerCryptoService.cs - сетевой крипто сервис Signer;
      • SignerException.cs - ошибка Signer;
  • Logging - логирование;
    • LogLevel.cs - уровень логирования;
    • Logger.cs - логгер, который использует предоставленный делегат для вывода сообщений;
    • ILoggerDelegate.cs - делегат логирования;

3 Основные функции

Основными функциями библиотеки авторизации являются:

  • получение авторизационного кода ЕСИА;
  • обмен авторизационного кода на маркер доступа;
  • обмен маркера обновления на маркер доступа (без запроса авторизации пользователя на стороне ЕСИА);
  • получение данных пользователя из ЕСИА (в приложении Б перечислены скоупы, которые может получать базовая и расширенная версии библиотеки);
  • выход (логаут) на стороне ЕСИА.

4 Интеграция библиотеки

4.1 Подготовка

Перед началом интеграции необходимо:

  1. Настроить для вашей системы HTTPS (это обязательное требование, поскольку данные между вашей системой и ЕСИА передаются в открытом виде);
  2. Выполнить экспорт ключевой пары (сформированной по ГОСТ-2012) из криптоконтейнера (экспорт можно сделать с помощью нашей утилиты);
  3. Настроить систему на технологическом портале тестовой/промышленной ЕСИА. На технологическом портале в окне редактирования параметров системы (см. рисунок 1) указать URL возврата после авторизации и логаута, а также установить алгоритм подписания запросов GOST3410_2012_256.

img1

img2

Поля в окне редактирования параметров системы

  1. В подходящую директорию положить ключ и сертификат в PEM формате (для извлечения ключа и сертификата из криптоконтейнера можно воспользоваться нашей утилитой), сформированные по ГОСТ-2012 с длиной ключа 256 бит, и удостовериться, что тот же сертификат загружен на технологическом портале тестовой/промышленной ЕСИА.
  2. В подходящую директорию положить файл сертификата ЕСИА в PEM формате с именем esia-test.crt или esia-prod.crt в зависимости от окружения (тестовое/промышленное), в котором запускается код.
  3. ВАЖНО!!! Настроить доступ к директориям для размещения файлов сертификата, ключа и логов библиотеки таким образом, чтобы их файлы нельзя было получить извне.

4.2 Подключение библиотеки к проекту

Поскольку библиотека поставляется в виде модулей с открытым исходным кодом она может быть интегрирована в кодовую базу любого проекта на С# (при соблюдении требований к зависимостям, которые описаны в разделе 5).

Возможны следующие варианты подключения библиотеки к целевому проекту:

  1. Сборка библиотеки и деплой в репозиторий NuGet и подключение к целевому проекту в виде зависимости;
  2. Добавление папки библиотеки в решение (solution);

4.2.1 Сборка библиотеки и деплой в репозиторий NuGet

Для подключения библиотеки к .Net проекту в виде зависимости NuGet библиотеку следует собрать и опубликовать в приватный NuGet репозиторий.

Сборка библиотеки:

dotnet pack -c Release

Публикация пакета в приватный NuGet репозиторий:

dotnet nuget push core/bin/Release/Esia.OAuth2.Core.3.0.0.nupkg --api-key <ваш ключ API> --source <URL приватного репозитория NuGet>

Подробно публикация описана в этой статье: https://learn.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package-using-the-dotnet-cli

Для использования в проекте необходимо предварительно добавить источник получения пакетов, указывающий на приватный репозиторий:

nuget sources Add -Name "Имя приватного репозитория" -Source <URL приватного репозитория>

Подробная инструкция по настройки источников получения пакетов находится здесь:

https://learn.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-sources .

Далее следует добавить пакет Esia.OAuth2.Core 3.0.0 в проект как обычно:

dotnet add package Esia.OAuth2.Core --version 3.0.0

4.2.2 Добавление папки библиотеки в решение (solution)

Данный вариант подключения предполагает копирование исходников библиотеки внутрь решения (solution) и подключение его к решению в вашем IDE (Visual Studio, Rider и т.д.) как существующий проект. За подробными инструкциями обратитесь к документации своей IDE.

4.3. Реализация необходимых интеграционных классов

Необходимо реализовать следующие интерфейсы:

  • IAuthStateStorage - интерфейс хранилища авторизационных данных
  • IRequest - адаптер к объекту запроса платформы / фреймворка приложения
  • ILoggerDelegate - делегат логирования (не обязательно)
  • IHttpClient - HTTP клиент (не обязательно)

IAuthStateStorage

При выполнении каждого запроса необходимо получить авторизационные данные, такие как маркер доступа, маркер обновления маркера доступа. Также в процессе запроса маркеры могут быть обновлены и их необходимо сохранить для выполнения последующих запросов. Для этих целей предназначен этот интерфейс. Реализация может хранить данные в сессии пользователя, либо в любом другом хранилище (БД). Важно реализовать механизм блокировки хранилища, так как запросы могут выполняться параллельно и может возникнуть ситуация когда два параллельных запроса начнут одновременно обновлять маркер доступа. Без блокировки последний запрос получит ошибку AuthorizationRequiredException.

Пример реализации данного интерфейса при работе с механизмом сервлетов находится в демонстрационном приложении по пути: sample_app/Utils/MvcAuthStateStorage.cs.

IRequest

При обработке запроса от ЕСИА об успешной авторизации (HandleLoginRedirect) необходимо получение определённых параметров из запроса. Данный интерфейс адаптирует запрос платформы (MvcRequest) для библиотеки.

Пример реализации данного интерфейса при работе с механизмом сервлетов находится в демонстрационном приложении по пути: sample_app/Utils/MvcRequest.cs.

ILoggerDelegate

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

Пример реализации данного интерфейса при работе с MVC находится в демонстрационном приложении по пути: sample_app/Utils/MvcLoggerDelegate.cs.

IHttpClient

Библиотека использует встроенный System.Net.Http.HttpClient, но при необходимости возможно добавить реализацию основанную на любом другом HTTP клиенте, на том например, который используется в целевом проекте.

Интерфейс HTTP клиента библиотеки находится в core/Http/IHttpClient.cs.

Реализация Apache HTTP клиента находится в core/Http/SystemHttpClient.cs.

4.4 Инициализация библиотеки

Способ инициализации зависимостей зависит от используемого фреймворка или платформы целевого приложения. Рассмотрим инициализацию на примере сервлетов.

В результате инициализации будут получены настроенные классы EsiaAuthService и PersonInfoService при помощи которых в дальнейшем будут производиться действия по авторизации и получению персональных данных.

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

Формирование запроса авторизации производится классами LoginUrlBuilderV1 (API v1) и LoginUrlBuilderV2 (API v2), которые реализуют интерфейс ILoginUrlBuilder. На данный момент актуальным является API v2. API v1 считается устаревшим и не рекомендуется к использованию.

Получение маркера доступа производится классами AccessTokenRequesterV1 (API v1) и AccessTokenRequesterV3 (API v3), которые реализуют интерфейс IAccessTokenRequester. На данный момент актуальным является API v3. API v1 считается устаревшим и не рекомендуется к использованию.

Обновление маркера доступа производится классом AccessTokenRefresherV1 (API v1), который реализуют интерфейс IAccessTokenRequester.

Инициализация библиотеки производится в файле инициализации приложения sample_app/Program.cs:

// Задаем делегат логирования
builder.Services.AddSingleton(serviceProvider =>
   (ILoggerDelegate)new MvcLoggerDelegate(serviceProvider.GetRequiredService<ILogger<MvcLoggerDelegate>>())
);

// Задаем HTTP клиент
builder.Services.AddSingleton(serviceProvider =>
   // Помимо задания системного HTTP клиента, добавляем логирующий запросы прокси
   (IHttpClient)new HttpClientLogWrapper(
       new SystemHttpClient(),
       serviceProvider.GetService<ILoggerDelegate>()
   )
);

// Задаем крипто-сервис
builder.Services.AddSingleton(serviceProvider =>
{
   var loggerDelegate = serviceProvider.GetService<ILoggerDelegate>();
   // получаем имя крипто-провайдера (сервиса) из переменной среды
   var provider = Envs.Require("PROVIDER");
   ICryptoService service;
   switch (provider)
   {
       // Инициализируем OpenSSL крипто-сервис
       case "OPENSSL":
           var certFile = Envs.Require("OPENSSL_CERT");
           var keyFile = Envs.Require("OPENSSL_KEY");
           var esiaCertFile = Envs.Get("OPENSSL_ESIA_CERT");
service = new OpenSslCryptoService(new OpenSslExecutor(loggerDelegate), certFile, keyFile, esiaCertFile);
           break;
       // Инициализируем крипто-сервис, использующий Signer
       case "SIGNER":
           service = new SignerCryptoService(
               Envs.Require("SIGNER_URL"),
               Envs.Get("SIGNER_LOGIN"),
               Envs.Get("SIGNER_PASSWORD"),
               Envs.Require("SIGNER_CERT"),
               Envs.Get("SIGNER_ESIA_CERT"),
               serviceProvider.GetRequiredService<IHttpClient>()
           );
           break;
       default:
           throw new ArgumentException($"<4a03fbf7> Unsupported provider: {provider}");
   }

   return service;
});

// Задаем конфигурацию сервиса авторизации
builder.Services.AddSingleton(serviceProvider =>
   {
       var loggerDelegate = serviceProvider.GetService<ILoggerDelegate>();
       var baseUrl = Envs.Get("BASE_URL") ?? "http://localhost:8080";
       var cryptoService = serviceProvider.GetRequiredService<ICryptoService>();

       // Если криптосервис поддерживает верификацию подписи сертификатом ЕСИА - инициализируем верификатор маркера доступа
       IAccessTokenVerifier? tokenVerifier =
           cryptoService.IsTokenVerificationSupported ? new EsiaTokenVerifier(cryptoService) : null;

       // Создаем конфигурацию для сервиса авторизации ЕСИА
       return Configuration.GetBuilder()
           // Используем тестовый домен ЕСИА
           .Domain(EsiaDomain.Test)
           // Задаем мнемонику ЕСИА из переменной среды
           .ClientId(Envs.Require("CLIENT_ID"))
           // Предполагается работа только онлайн
           .AccessType(AccessType.Online)
           // Задаем путь получения результата авторизации
           .LoginRedirectUri($"{baseUrl}/OAuth2/LoginResponse")
           // Задаем путь получения результата выхода из учетной записи 
           .LogoutRedirectUri($"{baseUrl}/OAuth2/LogoutSuccess")
           // Задаем первоначальные необходимые разрешения на получения данных
           .Scopes(Scope.Fullname, Scope.IdDoc, Scope.Inn, Scope.Snils, Scope.Addresses, Scope.Vehicles, Scope.UsrOrg,
               Scope.Birthdate, Scope.Birthplace, Scope.Gender,
               Scope.Email, Scope.Mobile, Scope.KidFullname, Scope.KidBirthdate, Scope.KidInn, Scope.KidGender,
               Scope.KidSnils, Scope.KidMedicalDoc, Scope.KidBirthCertDoc)
           // Задаем сконфигурированный крипто-сервис
           .CryptoService(cryptoService)
           // Задаем сконфигурированный делегат логирования
           .LoggerDelegate(loggerDelegate)
           // Задаем сконфигурированный верификатор подписи маркера доступа ЕСИА
           .AccessTokenVerifier(tokenVerifier)
           // Задаем сконфигурированный HTTP клиент
           .HttpClient(serviceProvider.GetService<IHttpClient>())
           // Собираем объект конфигурации
           .Build();
   }
);

// Задаем сервис авторизации
builder.Services.AddSingleton(serviceProvider => (IAuthService)new EsiaAuthService(
   serviceProvider.GetService<Configuration>(),
   // Используем API авторизации v2 (последняя актуальная версия)
   new LoginUrlBuilderV2(),
   // Используем API получения маркера доступа v3 (последняя актуальная версия)
   new AccessTokenRequesterV3(),
   // Используем API обновления маркера доступа v1 (последняя актуальная версия)
   new AccessTokenRefresherV1()));

// Задаем сервис получения пользовательской информации
builder.Services.AddSingleton(serviceProvider =>
   new PersonInfoService(serviceProvider.GetService<Configuration>(), serviceProvider.GetService<IAuthService>())
);

4.5 Процесс авторизации в ЕСИА

Получение URL для прохождения авторизации производится вызовом метода CreateLoginRequest интерфейса IAuthService. В результате (LoginRequest) помимо Uri также возвращается State (ID состояния запроса), который следует сохранить в сессии пользователя для дальнейшей проверки запроса на возможные атаки CSRF. Если такая проверка не нужна, полученный State можно проигнорировать.

Пример реализации находится в классе OAuth2Controller:

public async Task<IActionResult> Login()
{
   var request = await _authService.CreateLoginRequest();
   HttpContext.Session.Set("state", Encoding.UTF8.GetBytes(request.State));
   return Redirect(request.Uri);
}

После завершения авторизации ЕСИА производит перенаправление на сконфигурированный путь возврата (LoginRedirectUri) в котором передает дополнительными параметрами необходимые данные для завершения процесса авторизации на стороне приложения. Обработка данных завершения производится вызовом метода HandleLoginRedirect интерфейса IAuthService.

Дополнительно, если используется проверка на CSRF, необходимо восстановить идентификатор состояния запроса (State), ранее сохраненный в сессии пользователя, и передать его в вызов метода HandleLoginRedirect. Если проверка на CSRF не требуется, в State передается null.

Пример реализации находится в классе OAuth2Controller:

public async Task<IActionResult> LoginResponse()
{
   var state = HttpContext.Session.TryGetValue("state", out var value) ? Encoding.UTF8.GetString(value) : null;
   await _authService.HandleLoginRedirect(new MvcRequest(Request), GetAuthStateStorage(),
       state);
   var result = AdditionalScopeRequester.HandleRedirectAfterLogin(HttpContext);
   return result ?? RedirectToAction("Index", "PersonInfo");
}

4.6 Выход из ЕСИА

Получение URL для выхода (логаута) пользователя производится методом CreateLogoutUrl интерфейса IAuthService. Для выхода следует перенаправить пользователя на полученный URL, также стоит зачистить объект сессии пользователя.

Пример реализации запуска процесса выхода находится в классе OAuth2Controller:

public IActionResult Logout()
{
   var url = _authService.CreateLogoutUrl();
   return Redirect(url);
}

После завершения процесса выхода ЕСИА производит перенаправление на сконфигурированный путь возврата (LogoutRedirectUri). Обработка завершения производится вызовом метода HandleLogoutRedirect интерфейса IAuthService.

Пример реализации на сервлетах находится в классе OAuth2Controller:

public async Task<IActionResult> LogoutSuccess()
{
   await _authService.HandleLogoutRedirect(GetAuthStateStorage());
   return View();
}

4.7 Обновление маркера доступа

Маркер доступа обновляется автоматически при любых запросах маркера доступа методами GetAccessToken или RequireAccessToken интерфейса IAuthService. Для принудительного обновления маркера доступа используется метод RefreshAccessToken. Стоит отметить, что в продуктовой эксплуатации явный вызов этого метода не требуется, он предназначен исключительно для тестирования.

Пример реализации обновления маркера доступа находится в классе OAuth2Controller:

public async Task<IActionResult> RefreshToken()
{
   await _authService.RefreshAccessToken(GetAuthStateStorage());
   return RedirectToAction("Index", "PersonInfo");
}

4.8 Получение дополнительных разрешений

Для получения некоторых наборов данных необходимо получение дополнительных разрешений с указанием идентификаторов полученных в процессе запросов (например при запросе детальной информации об организации). Для этих целей служит метод RequestScopes в интерфейсе IAuthService.

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

Пример реализации запроса дополнительных разрешений находится в классе AdditionalScopeRequester:

public static async Task<IActionResult?> Request(IAuthService authService, IAuthStateStorage storage, HttpContext context,
   params string[] scopes)
{
   var loginRequest = await authService.RequestScopes(storage, scopes);
   if (loginRequest == null) return null;
   var session = context.Session;
   var request = context.Request;
   var uri = request.Path.ToUriComponent() + request.QueryString.ToUriComponent();
   session.Set(RedirectAfterLoginAttr, Encoding.UTF8.GetBytes(uri));
   session.Set("state", Encoding.UTF8.GetBytes(loginRequest.State));
   return new RedirectResult(loginRequest.Uri);
}

Пример использования AdditionalScopeRequester находится в классе OrgDetailsController:

var additionalScopesResult = await AdditionalScopeRequester.Request(_authService, storage, HttpContext,
   new[]
   {
       Scope.OrgFullname, Scope.OrgShortname, Scope.OrgAddrs, Scope.OrgType,
       Scope.OrgOgrn, Scope.OrgInn, Scope.OrgKpp, Scope.OrgLeg, Scope.OrgAgencyType,
       Scope.OrgEmps, Scope.OrgBrhs
   }.Select(s => s.AddParam("org_oid", orgId))
);
if (additionalScopesResult != null) return additionalScopesResult;

4.9 Получение персональных данных

За получение персональных данных отвечает класс PersonInfoService. Данный сервис предоставляет следующие методы для получения данных:

  • GetPersonId - получение идентификатора пользователя;
  • GetPersonInfo - получение персональной информации (ФИО, СНИЛС, гражданство, пол, дату, место рождения и т.д.);
  • GetPersonDocuments - документы пользователя (паспорт, водительские права и т.д.);
  • GetPersonContacts - контактные данные пользователя (телефон, email);
  • GetPersonOrgs - сводные данные об организациях, сотрудником которых является пользователь;
  • GetPersonAddesses - список адресов пользователя;
  • GetPersonKids - перечень записей о детях физ. лица;
  • GetPersonKidDocuments - список документов ребенка;
  • GetPersonVehicles - список зарегистрированных транспортных средств пользователя;
  • GetOrgDetails - получение детальной информации об организации пользователя. Необходимо получение дополнительного разрешения.

Пример получения информации находится в классах PersonInfoController:

var storage = new MvcAuthStateStorage(HttpContext.Session);
var requester = _personInfoService.GetRequester(storage);
var personId = await requester.GetPersonId();
var authState = storage.GetState();
var infoTask = requester.GetPersonInfo(personId);
var documentsTask = requester.GetPersonDocuments(personId);
var contactsTask = requester.GetPersonContacts(personId);
var addressesTask = requester.GetPersonAddresses(personId);
var orgsTask = requester.GetPersonOrgs(personId);
var vehiclesTask = requester.GetPersonVehicles(personId);
var kids = await requester.GetPersonKids(personId);
var kidDocumentTasks = kids.Select(k => requester.GetPersonKidDocuments(personId, k.Id));
await Task.WhenAll(infoTask, documentsTask, addressesTask, orgsTask, vehiclesTask, contactsTask);
var kidDocuments = kids.Zip(await Task.WhenAll(kidDocumentTasks), KeyValuePair.Create);
var model = new PersonInfoModel
{
   PersonInfo = await infoTask,
   Documents = await documentsTask,
   Contacts = await contactsTask,
   Addresses = await addressesTask,
   Orgs = await orgsTask,
   Vehicles = await vehiclesTask,
   Kids = kids,
   KidDocuments = kidDocuments,
   AuthState = authState != null ? JsonConvert.SerializeObject(authState, Formatting.Indented) : ""
};
return View(model);

И OrgDetailsController:

var requester = _personInfoService.GetRequester(storage);
var orgDetails = await requester.GetOrgDetails(orgId);
return View(orgDetails);

5. Зависимости

Библиотека авторизации предъявляет следующие языковые требования

C# 5.0 (.Net Framework >= 4.5) либо .Net Core >= 2.0

Остальные необходимые зависимости подтягиваются менеджером пакетов NuGet при сборке или открытии проекта:

  • Newtonsoft.Json 13.01
  • System.IdentityModel.Tokens.Jwt 6.24.0

ПРИЛОЖЕНИЕ А. Описание конфигурационных параметров

Библиотека авторизации принимает на вход набор параметров (класс Configuration), описанных в таблице А.1.

Таблица А.1 - Описание параметров

Наименование параметра Обязательный Описание параметра
1 Domain да URL системы - поставщика услуг (ЕСИА)
2 ClientId да Мнемоника, полученная при регистрации ИС в минкомсвязи
3 LoginRedirectUri да Определяет адрес возврата в ИС после авторизации пользователя в ЕСИА
4 LogoutRedirectUri нет Определяет адрес возврата в ИС после логаута пользователя в ЕСИА
5 Scopes нет Перечень областей данных, к которым предоставляется доступ для ИС после авторизации
6 AccessType да Определяет тип доступа к защищенному хранилищу ЕСИА предоставляемому для ИС
7 AccessTokenVerifier нет Определяет реализацию проверки маркера доступа
8 LoggerDelegate нет Определяет реализацию логирования
9 DateProvider нет Определяет реализацию поставщика текущего времени
10 StateGenerator нет Определяет реализацию генератора идентификаторов для state
11 HttpClient нет Определяет реализацию HttpClient
12 СryptoService да Определяет крипто-сервис

Пример формирования конфигурационного объекта, задающего необходимый набор параметров для библиотеки, приведен ниже.

Для тестовой среды ЕСИА:

Configuration.GetBuilder()
   // Используем тестовый домен ЕСИА
   .Domain(EsiaDomain.Test)
   // Задаем мнемонику ЕСИА из переменной среды
   .ClientId(Envs.Require("CLIENT_ID"))
   // Предполагается работа только онлайн
   .AccessType(AccessType.Online)
   // Задаем путь получения результата авторизации
   .LoginRedirectUri($"{baseUrl}/OAuth2/LoginResponse")
   // Задаем путь получения результата выхода из учетной записи 
   .LogoutRedirectUri($"{baseUrl}/OAuth2/LogoutSuccess")
   // Задаем первоначальные необходимые разрешения на получения данных
   .Scopes(Scope.Fullname, Scope.IdDoc, Scope.Inn, Scope.Snils, Scope.Addresses, Scope.Vehicles, Scope.UsrOrg,
       Scope.Birthdate, Scope.Birthplace, Scope.Gender,
       Scope.Email, Scope.Mobile, Scope.KidFullname, Scope.KidBirthdate, Scope.KidInn, Scope.KidGender,
       Scope.KidSnils, Scope.KidMedicalDoc, Scope.KidBirthCertDoc)
   // Задаем сконфигурированный крипто-сервис
   .CryptoService(cryptoService)
   // Задаем сконфигурированный делегат логирования
   .LoggerDelegate(loggerDelegate)
   // Задаем сконфигурированный верификатор подписи маркера доступа ЕСИА
   .AccessTokenVerifier(tokenVerifier)
   // Задаем сконфигурированный HTTP клиент
   .HttpClient(serviceProvider.GetService<IHttpClient>())
   // Собираем объект конфигурации
   .Build();

Для промышленной среды ЕСИА:

Configuration.GetBuilder()
   // Используем тестовый домен ЕСИА
   .Domain(EsiaDomain.Prod)
   // Задаем мнемонику ЕСИА из переменной среды
   .ClientId(Envs.Require("CLIENT_ID"))
   // Предполагается работа только онлайн
   .AccessType(AccessType.Online)
   // Задаем путь получения результата авторизации
   .LoginRedirectUri($"{baseUrl}/OAuth2/LoginResponse")
   // Задаем путь получения результата выхода из учетной записи 
   .LogoutRedirectUri($"{baseUrl}/OAuth2/LogoutSuccess")
   // Задаем первоначальные необходимые разрешения на получения данных
   .Scopes(Scope.Fullname, Scope.IdDoc, Scope.Inn, Scope.Snils, Scope.Addresses, Scope.Vehicles, Scope.UsrOrg,
       Scope.Birthdate, Scope.Birthplace, Scope.Gender,
       Scope.Email, Scope.Mobile, Scope.KidFullname, Scope.KidBirthdate, Scope.KidInn, Scope.KidGender,
       Scope.KidSnils, Scope.KidMedicalDoc, Scope.KidBirthCertDoc)
   // Задаем сконфигурированный крипто-сервис
   .CryptoService(cryptoService)
   // Задаем сконфигурированный делегат логирования
   .LoggerDelegate(loggerDelegate)
   // Задаем сконфигурированный верификатор подписи маркера доступа ЕСИА
   .AccessTokenVerifier(tokenVerifier)
   // Задаем сконфигурированный HTTP клиент
   .HttpClient(serviceProvider.GetService<IHttpClient>())
   // Собираем объект конфигурации
   .Build();

ПРИЛОЖЕНИЕ Б. Перечень запрашиваемых областей доступа

Перечень областей данных (scope) библиотеки приведён в таблице Б.1.

Таблица Б.1 - Перечень запрашиваемых областей доступа

Название scope Состав набора данных Запрашивается(+)/Не запрашивается(-)
1. fullname Просмотр фамилии, имени и отчества:
• фамилия;
• имя;
• отчество.
+
2. birthdate дата рождения, указанная в учетной записи +
3. gender пол, указанный в учетной записи +
4. snils СНИЛС, указанный в учетной записи +
5. inn ИНН, указанный в учетной записи +
6. id_doc Просмотр данных о документе, удостоверяющем личность:
• серия и номер документа, удостоверяющего личность;
• дата выдачи;
• кем выдан;
• код подразделения;
• гражданство.
+
7. birthplace место рождения. +
8. medical_doc Просмотр данных полиса ОМС:
• номер полиса ОМС;
• срок действия.
+
9. military_doc Просмотр данных военного билета:
• серия и номер военного билета;
• дата выдачи;
• орган, выдавший документ.
+
10. foreign_passport_doc Просмотр данных заграничного паспорта:
• фамилия, имя, отчество буквами латинского алфавита;
• серия и номер заграничного паспорта;
• дата выдачи;
• срок действия;
• орган, выдавший документ;
• гражданство.
+
11. drivers_licence_doc Просмотр данных водительского удостоверения:
• серия и номер водительского удостоверения;
• дата выдачи;
• срок действия.
+
12. birth_cert_doc Просмотр данных свидетельства о рождении:
• серия и номер свидетельства;
• дата выдачи;
• место государственной регистрации.
+
13. residence_doc Просмотр данных вида на жительство:
• серия и номер вида на жительство;
• дата выдачи.
+
14. temporary_residence_doc Просмотр данных разрешения на временное проживание:
• серия и номер разрешения на временное проживание;
• дата выдачи.
+
15. vehicles Просмотр данных транспортных средств:
• государственный регистрационный знак;
• серия и номер свидетельства о регистрации.
+
16. email адрес электронной почты, указанный в учетной записи +
17. mobile номер мобильного телефона +
18. contacts Просмотр данных о контактах и адресах:
• номер домашнего телефона;
• номер мобильного телефона;
• адрес электронной почты;
• адрес регистрации;
• адрес места проживания.
+
19. usr_org список организаций пользователя. +
20. usr_avt Просмотр изображения (аватара) пользователя:
• получения изображения (аватара);
• создание и обновление изображения (аватара);
• получение исходного изображения (аватара)
-
21. self_employed Просмотр данных о самозанятых;
• признак самозанятого;
• категория (вид деятельности).
-
22. kid_fullname Просмотр фамилии, имени и отчества:
• фамилия;
• имя;
• отчество.
-
23. kid_birthdate дата рождения ребенка -
24.. kid_gender Пол ребенка -
25. kid_snils СНИЛС ребенка -
26. kid_inn ИНН ребенка -
27. kid_birth_cert_doc Просмотр данных свидетельства о рождении:
• серия свидетельства;
• номер свидетельства;
• дата выдачи свидетельства;
• кем выдано свидетельство.
-
28. kid_medical_doc Просмотр данных полиса ОМС:
• номер полиса ОМС;
• действителен до ОМС.
-
1. org_shortname Сокращенное наименование организации +
2. org_fullname Полное наименование организации +
3. org_type Тип организации +
4. org_ogrn ОГРН организации +
5. org_inn ИНН организации +
6. org_leg ОПФ организации +
7. org_kpp КПП организации +
8. org_agencyterrange Территориальная принадлежность ОГВ +
9. org_agencytype Тип ОГВ +
10. org_oktmo ОКТМО организации +
11. org_ctts Контакты организации: номер телефона, номер факса, адрес электронной почты +
12. org_addrs Адреса организации (почтовый адрес, юридический адрес): индекс, идентификатор страны, адрес в виде строки (не включая дом, строение, корпус, номер квартиры), строение, корпус, дом, квартира, код ФИАС, регион,город, внутригородской район, район, поселение, доп. территория, улица на доп. территории, улица +
13. org_vhls Транспортные средства организации: название, государственный регистрационный знак, серия и номер свидетельства о регистрации -
14. org_grps Группы, владельцем которых является организация -
15. org_emps Данные о сотрудниках организации -
16. org_brhs Данные о филиалах организации (название, КПП, ОПФ, контакты, адреса) -
17. org_brhs_ctts Контакты филиалов организации -
18. org_brhs_addrs Адреса филиалов организации -
19. org_rcs Центры регистрации организации -
20. org_stms Системы, владельцем которых является организация -
21. org_invts Приглашения, направленные организацией -
22. categories Данные присвоенных организации видов деятельности -
  • Библиотека авторизации через ЕСИА (C# .NET)
  • 1 Общее описание
  • 2 Перечень поставляемых файлов
  • 3 Основные функции
  • 4 Интеграция библиотеки
  • 4.1 Подготовка
  • 4.2 Подключение библиотеки к проекту
  • 4.2.1 Сборка библиотеки и деплой в репозиторий NuGet
  • 4.2.2 Добавление папки библиотеки в решение (solution)
  • 4.3. Реализация необходимых интеграционных классов
  • IAuthStateStorage
  • IRequest
  • ILoggerDelegate
  • IHttpClient
  • 4.4 Инициализация библиотеки
  • 4.5 Процесс авторизации в ЕСИА
  • 4.6 Выход из ЕСИА
  • 4.7 Обновление маркера доступа
  • 4.8 Получение дополнительных разрешений
  • 4.9 Получение персональных данных
  • 5. Зависимости
  • ПРИЛОЖЕНИЕ А. Описание конфигурационных параметров
  • ПРИЛОЖЕНИЕ Б. Перечень запрашиваемых областей доступа