MtsIdNet 0.1.0-preview.1

This is a prerelease version of MtsIdNet.
dotnet add package MtsIdNet --version 0.1.0-preview.1
                    
NuGet\Install-Package MtsIdNet -Version 0.1.0-preview.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MtsIdNet" Version="0.1.0-preview.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MtsIdNet" Version="0.1.0-preview.1" />
                    
Directory.Packages.props
<PackageReference Include="MtsIdNet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MtsIdNet --version 0.1.0-preview.1
                    
#r "nuget: MtsIdNet, 0.1.0-preview.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MtsIdNet@0.1.0-preview.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MtsIdNet&version=0.1.0-preview.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=MtsIdNet&version=0.1.0-preview.1&prerelease
                    
Install as a Cake Tool

<table> <tr> <td width="170" align="center" valign="middle"> <img src="https://raw.githubusercontent.com/ai-iskuzhin/MtsIdNet/main/assets/icon.png" width="140" alt="Логотип MtsIdNet" /> </td> <td valign="middle"> <h1>MtsIdNet</h1> <p><em>Read this in <a href="./README.en.md">English</a>.</em></p> <p>.NET SDK для API <strong>МТС «Мобильный ID» (Mobile ID)</strong> (OIDC/OAuth2): формирование подписанного объекта <code>request</code> для <code>si-authorize</code>, публикация JWKS, серверная (CIBA) аутентификация, обработка SMS-OTP и итоговых нотификаций, валидация <code>id_token</code>, получение данных пользователя (<code>premiuminfo</code>) и верификация (<code>kyc-match-split</code>).</p> <p> <a href="https://github.com/ai-iskuzhin/MtsIdNet/actions/workflows/ci.yml"><img src="https://github.com/ai-iskuzhin/MtsIdNet/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI" /></a> <a href="https://github.com/ai-iskuzhin/MtsIdNet/actions/workflows/release.yml"><img src="https://github.com/ai-iskuzhin/MtsIdNet/actions/workflows/release.yml/badge.svg" alt="Release" /></a> <a href="https://github.com/ai-iskuzhin/MtsIdNet/blob/main/LICENSE"><img src="https://img.shields.io/github/license/ai-iskuzhin/MtsIdNet?style=flat-square" alt="License" /></a> <a href="https://dotnet.microsoft.com/"><img src="https://img.shields.io/badge/targets-netstandard2.0%20%7C%20net8.0%20%7C%20net10.0-512BD4?logo=dotnet&style=flat-square" alt="Targets" /></a> </p> <p> <a href="https://www.nuget.org/packages/MtsIdNet"><img src="https://img.shields.io/nuget/v/MtsIdNet?logo=nuget&style=flat-square" alt="Версия NuGet" /></a> <a href="https://www.nuget.org/packages/MtsIdNet"><img src="https://img.shields.io/nuget/dt/MtsIdNet?style=flat-square" alt="Загрузки NuGet" /></a> </p> </td> </tr> </table>

Единственная зависимость — System.Text.Json. Подпись/проверка RS256, JWKS и шифрование JWE (KYC) сделаны на встроенном System.Security.Cryptography, без цепочки Microsoft.IdentityModel.

Установка

dotnet add package MtsIdNet

Как устроен поток

«Аутентификация» Mobile ID работает по схеме Server Initiated (SI / CIBA): ваш бэкенд общается со шлюзом, пользователь остаётся у вас. Есть два асинхронных коллбэка, которые размещаете вы, а Mobile ID их вызывает:

  1. Вы формируете подписанный объект request (JWT, RS256) и отправляете POST /oidc/si-authorize.
  2. Mobile ID проверяет подпись по вашему опубликованному JWKS и отправляет пользователю push (или SMS).
  3. При откате на SMS Mobile ID вызывает ваш sms_otp_notification_uri; вы запрашиваете код и отправляете его на динамический endpoint проверки.
  4. При успехе Mobile ID вызывает ваш notification_uri с id_token; вы его валидируете и читаете sub.

Быстрый старт

1. Конфигурация

using System.Security.Cryptography;
using MtsIdNet;

// Ваша пара RSA-ключей. На net8.0+ можно загрузить из PEM:
var signingKey = MtsKeys.RsaFromPem(File.ReadAllText("sp-private.pem"));

var options = new MtsIdClientOptions
{
    ClientId = "mts_test_service",            // выдаётся при регистрации
    SigningKey = signingKey,
    SigningKeyId = "rsa_kid",                  // должен совпадать с kid в вашем JWKS
    NotificationUri = "https://service-provider.io/notification_uri/",
    // BaseAddress по умолчанию https://idgw.mobileid.mts.ru
    // EncryptionKey / EncryptionKeyId — нужны только для KYC (см. ниже)
};

var client = new MtsIdClient(httpClient, options);

2. Публикация JWKS

Отдавайте этот JSON по адресу JWKS, который вы зарегистрировали, чтобы Mobile ID мог проверить подпись request (и зашифровать KYC, если задан enc-ключ):

string jwksJson = client.BuildPublishedJwks().ToJson();

3. Запуск аутентификации

var result = await client.SiAuthorizeAsync(new RequestObjectParameters
{
    Scope = $"{MtsIdConstants.Scopes.OpenId} {MtsIdConstants.Scopes.Authn}",
    LoginHint = RequestObjectParameters.ForMsisdn("+7 915 000 00 00"),
    ClientNotificationToken = Guid.NewGuid().ToString(),   // проверяйте этот bearer в коллбэках
});

// Сохраните по auth_req_id — понадобится для валидации id_token:
//   result.Request.Nonce, result.Request.CorrelationId, result.Request.AcrValues, result.Request.Scope
//   result.Response.AuthReqId, result.Response.ExpiresIn, result.Response.HheUri (для seamless)

4. Откат на SMS-OTP (опционально)

Когда Mobile ID вызовет ваш sms_otp_notification_uri:

var sms = JsonSerializer.Deserialize<MtsSmsOtpNotification>(requestBody)!;
await client.VerifySmsCodeAsync(sms.SmsOtpEndpoint!, codeFromUser);

5. Итоговая нотификация и валидация id_token

Когда Mobile ID вызовет ваш notification_uri (Authorization: bearer {client_notification_token} — проверьте его):

var note = JsonSerializer.Deserialize<MtsNotification>(requestBody)!;

var jwks = await client.GetJwksAsync();   // кешируйте
var idToken = IdTokenValidator.Validate(note.IdToken!, jwks, new IdTokenValidationParameters
{
    ExpectedIssuer = client.Issuer,
    ExpectedClientId = options.ClientId,
    ExpectedNonce = nonceByAuthReqId,
    ExpectedAcrValues = acrValuesByAuthReqId,
});

// Связывайте idToken.Subject (sub) с аккаунтом пользователя — не номер телефона.

Данные пользователя — premiuminfo

С токеном доступа из нотификации (scope mc_identity_*):

PremiumInfo info = await client.GetPremiumInfoAsync(note.AccessToken!);
// info.GivenName, info.FamilyName, info.Birthdate, info.Email, info.Address, info.Raw

Верификация — kyc-match-split (требует .NET 8+)

Сверка введённых данных с данными оператора (scope mc_kyc_plain). Запрос шифруется enc-ключом оператора (из jwks_uri в KYC-нотификации), ответ расшифровывается вашим EncryptionKey:

var options = new MtsIdClientOptions
{
    // ... + KYC-ключ:
    EncryptionKey = MtsKeys.RsaFromPem(File.ReadAllText("sp-enc-private.pem")),
    EncryptionKeyId = "enc_kid",
};

var operatorJwks = await client.GetJwksAsync(new Uri(kycNotification.JwksUri!));
KycMatchResult match = await client.KycMatchAsync(note.AccessToken!, new KycMatchRequest
{
    GivenName = "ИВАН", MiddleName = "ИВАНОВИЧ", FamilyName = "ИВАНОВ", Birthdate = "1995-11-28",
}, operatorJwks);

// match.GivenName == MtsMatchStatus.Match, match.Birthdate == MtsMatchStatus.NotMatchAvailable, …

Шифрование JWE A256GCM требует System.Security.Cryptography.AesGcm (net8.0+). На netstandard2.0 методы KYC бросают PlatformNotSupportedException.

Модель ошибок

Все исключения наследуют MtsIdException:

  • MtsIdTransportException — сеть/TLS/таймаут, ответа нет.
  • MtsIdApiException — ошибка OAuth2 от шлюза (Error, ErrorDescription, StatusCode).
  • MtsIdProtocolException — ответ не удалось разобрать.
  • MtsIdTokenValidationException — id_token не прошёл проверку.
  • MtsIdUnsupportedValueException — Mobile ID вернул значение перечисления (amr/acr/статус KYC), которое SDK ещё не поддерживает. Текст ошибки содержит ссылку на issue-трекер — сообщите о новом значении.

Поля с фиксированным набором значений (amr, acr, статусы KYC) представлены enum-ами; неизвестное значение приводит к MtsIdUnsupportedValueException (а не к «тихому» Unknown).

Целевые платформы

netstandard2.0 (.NET Framework 4.6.1+ и .NET Core 2.0+), net8.0, net10.0. На netstandard2.0 загрузите RSA-ключ через RSAParameters (MtsKeys.RsaFromPem и KYC доступны на net8.0+).

Лицензия

MIT — см. LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.1 60 6/24/2026