MtsIdNet 0.1.0-preview.1
dotnet add package MtsIdNet --version 0.1.0-preview.1
NuGet\Install-Package MtsIdNet -Version 0.1.0-preview.1
<PackageReference Include="MtsIdNet" Version="0.1.0-preview.1" />
<PackageVersion Include="MtsIdNet" Version="0.1.0-preview.1" />
<PackageReference Include="MtsIdNet" />
paket add MtsIdNet --version 0.1.0-preview.1
#r "nuget: MtsIdNet, 0.1.0-preview.1"
#:package MtsIdNet@0.1.0-preview.1
#addin nuget:?package=MtsIdNet&version=0.1.0-preview.1&prerelease
#tool nuget:?package=MtsIdNet&version=0.1.0-preview.1&prerelease
<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 их вызывает:
- Вы формируете подписанный объект
request(JWT, RS256) и отправляетеPOST /oidc/si-authorize. - Mobile ID проверяет подпись по вашему опубликованному JWKS и отправляет пользователю push (или SMS).
- При откате на SMS Mobile ID вызывает ваш
sms_otp_notification_uri; вы запрашиваете код и отправляете его на динамический endpoint проверки. - При успехе 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 | Versions 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. |
-
.NETStandard 2.0
- System.Net.Http.Json (>= 8.0.1)
- System.Text.Json (>= 8.0.6)
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
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 |