Библиотека IdentityModel для OAuth 2.0 и OpenID Connect в C# (.NET)
При разработке современных веб-приложений, мобильных клиентов или серверных API на платформе .NET практически всегда возникает необходимость интеграции с внешними провайдерами аутентификации (Google, GitHub, Microsoft и др.) или собственным сервером авторизации. IdentityModel — это легковесная, но мощная библиотека для C#, которая предоставляет удобный OAuth клиент для работы с протоколами OAuth 2.0 и OpenID Connect. Она является де-факто стандартом в экосистеме .NET для реализации потоков авторизации.
В этой статье мы подробно разберем, как использовать IdentityModel для создания OAuth клиента, получения токенов доступа и их обновления. Примеры кода будут на C# (.NET 6+).
Установка и подключение
Для начала работы установите пакет через NuGet Package Manager:
dotnet add package IdentityModel
Или через консоль менеджера пакетов:
Install-Package IdentityModel
После установки вы получаете доступ к классам HttpClient extensions, DiscoveryClient, TokenClient и другим вспомогательным утилитам.
Базовый сценарий: получение токена через Client Credentials
Этот поток используется для сервер-серверной аутентификации, когда клиент (ваше приложение) запрашивает токен от имени самого себя, а не пользователя.
Пример настройки OAuth клиента:
using IdentityModel.Client;
using System.Net.Http;
using System.Threading.Tasks;
public async Task<string> GetAccessTokenAsync()
{
var client = new HttpClient();
// 1. Получаем документ обнаружения (discovery) от сервера авторизации
var disco = await client.GetDiscoveryDocumentAsync("https://your-auth-server.com");
if (disco.IsError)
{
throw new Exception($"Ошибка получения discovery: {disco.Error}");
}
// 2. Запрашиваем токен, используя client_id и client_secret
var tokenResponse = await client.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "your-client-id",
ClientSecret = "your-client-secret",
Scope = "api1 api2" // запрашиваемые разрешения
});
if (tokenResponse.IsError)
{
throw new Exception($"Ошибка получения токена: {tokenResponse.Error}");
}
return tokenResponse.AccessToken;
}
В этом примере мы используем методы расширения из пространства имен IdentityModel.Client. Библиотека автоматически обрабатывает сериализацию JSON, заголовки и парсинг ответов.
Поток Authorization Code (с участием пользователя)
Для приложений с пользовательским интерфейсом (ASP.NET Core MVC, Blazor, десктоп) чаще используется код авторизации. IdentityModel интегрируется с Microsoft.AspNetCore.Authentication.OpenIdConnect, но также предоставляет низкоуровневые средства для ручной реализации.
Пример получения токена после редиректа с кодом:
public async Task<TokenResponse> ExchangeCodeForTokenAsync(string authorizationCode, string redirectUri)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://your-auth-server.com");
var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(
new AuthorizationCodeTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "your-client-id",
ClientSecret = "your-client-secret",
Code = authorizationCode,
RedirectUri = redirectUri
});
return tokenResponse;
}
Обновление токена (Refresh Token)
Access token'ы обычно живут недолго (например, 1 час). Для продления сессии используется refresh token. IdentityModel делает этот процесс тривиальным:
public async Task<TokenResponse> RefreshAccessTokenAsync(string refreshToken)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://your-auth-server.com");
var tokenResponse = await client.RequestRefreshTokenAsync(
new RefreshTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "your-client-id",
ClientSecret = "your-client-secret",
RefreshToken = refreshToken
});
return tokenResponse;
}
Работа с JWT и проверка токенов
IdentityModel включает утилиты для работы с JWT (JSON Web Tokens). Вы можете декодировать payload без проверки подписи:
using IdentityModel.Jwt;
var token = "eyJhbGciOiJSUzI1NiIs...";
var payload = JwtToken.Decode(token);
Console.WriteLine(payload["sub"]); // идентификатор пользователя
Для полной верификации токена (проверка подписи, срока действия, аудитории) рекомендуется использовать Microsoft.IdentityModel.Tokens вместе с IdentityModel.