📮 Контакты 🇧🇷 🇺🇸 🇫🇷

Твиттер
LinkedIn


Это пример того, как клиентское приложение извлекает токен с сервера идентификации и использует его в WebApi для использования конечной точки.

Этот пример был построен на основе Документация Дуэнде

Поставщик удостоверений для нашего образца.


Установите шаблоны Duende

dotnet new --install Duende.IdentityServer.Templates
Войти в полноэкранный режим

Выйти из полноэкранного режима


Создать пустое решение

dotnet new sln -n IdentityServerDemo
Войти в полноэкранный режим

Выйти из полноэкранного режима


Создать проект сервера идентификации

dotnet new isempty -n IdentityServer
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавьте проект IdendityServer в пустое решение.

dotnet sln add .\IdentityServer\IdentityServer.csproj
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавить область в config.cs

public static IEnumerable<ApiScope> ApiScopes =>
    new ApiScope[]
        { new ApiScope(name: "campelo-api", displayName: "CampeloAPI") };
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавить клиента в config.cs

public static IEnumerable<Client> Clients =>
    new Client[]
        { new Client
        {
            ClientId = "client",
            // no interactive user, use the clientid/secret for authentication
            AllowedGrantTypes = GrantTypes.ClientCredentials,
            // secret for authentication
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            // scopes that client has access to
            AllowedScopes = { "campelo-api" }
        } };
Войти в полноэкранный режим

Выйти из полноэкранного режима


Openid-конфигурация

Теперь вы можете получить доступ к конфигурации openid с сервера идентификации. Запустите решение и перейдите к https://localhost:5001/.well-known/openid-configuration. Таким образом, вы можете получить что-то вроде этого.

{
   "issuer":"https://localhost:5001",
   "jwks_uri":"https://localhost:5001/.well-known/openid-configuration/jwks",
   "authorization_endpoint":"https://localhost:5001/connect/authorize",
   "token_endpoint":"https://localhost:5001/connect/token",
   "userinfo_endpoint":"https://localhost:5001/connect/userinfo",
   "end_session_endpoint":"https://localhost:5001/connect/endsession",
   "check_session_iframe":"https://localhost:5001/connect/checksession",
   "revocation_endpoint":"https://localhost:5001/connect/revocation",
   "introspection_endpoint":"https://localhost:5001/connect/introspect",
   "device_authorization_endpoint":"https://localhost:5001/connect/deviceauthorization",
   "backchannel_authentication_endpoint":"https://localhost:5001/connect/ciba",
   "frontchannel_logout_supported":true,
   "frontchannel_logout_session_supported":true,
   "backchannel_logout_supported":true,
   "backchannel_logout_session_supported":true,
   "scopes_supported":[
      "openid",
      "campelo-api",
      "offline_access"
   ],
   "claims_supported":[
      "sub"
   ],
   "grant_types_supported":[
      "authorization_code",
      "client_credentials",
      "refresh_token",
      "implicit",
      "urn:ietf:params:oauth:grant-type:device_code",
      "urn:openid:params:grant-type:ciba"
   ],
   "response_types_supported":[
      "code",
      "token",
      "id_token",
      "id_token token",
      "code id_token",
      "code token",
      "code id_token token"
   ],
   "response_modes_supported":[
      "form_post",
      "query",
      "fragment"
   ],
   "token_endpoint_auth_methods_supported":[
      "client_secret_basic",
      "client_secret_post"
   ],
   "id_token_signing_alg_values_supported":[
      "RS256"
   ],
   "subject_types_supported":[
      "public"
   ],
   "code_challenge_methods_supported":[
      "plain",
      "S256"
   ],
   "request_parameter_supported":true,
   "request_object_signing_alg_values_supported":[
      "RS256",
      "RS384",
      "RS512",
      "PS256",
      "PS384",
      "PS512",
      "ES256",
      "ES384",
      "ES512",
      "HS256",
      "HS384",
      "HS512"
   ],
   "authorization_response_iss_parameter_supported":true,
   "backchannel_token_delivery_modes_supported":[
      "poll"
   ],
   "backchannel_user_code_parameter_supported":true
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

Проект веб-API.


Создайте новый проект веб-API

dotnet new webapi -n WebApi
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавление webapi в решение

dotnet sln add .\WebApi\WebApi.csproj
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавление аутентификации носителя JWT

dotnet add .\WebApi\WebApi.csproj package Microsoft.AspNetCore.Authentication.JwtBearer
Войти в полноэкранный режим

Выйти из полноэкранного режима


Установите JWT Bearer в качестве схемы аутентификации по умолчанию.

Обновите файл Program.cs или Startup.cs.

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = "https://localhost:5001";

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false
        };
    });

/// UseAuthentication right before UseAuthorization
app.UseAuthentication();
app.UseAuthorization();
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавить новый контроллер для тестирования

[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}
Войти в полноэкранный режим

Выйти из полноэкранного режима


Настройте WebAPI для прослушивания порта 6001.

Отредактируйте файл launchSettings.json в папке «Свойства».

"applicationUrl": "
Войти в полноэкранный режим

Выйти из полноэкранного режима


Запустите проект WebAPI

Теперь у вас есть ответ об ошибке 401 (несанкционированный доступ) при попытке доступа


Создание консольного клиентского проекта

dotnet new console -n Client
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавьте клиентский проект в решение

dotnet sln add .\Client\Client.csproj
Войти в полноэкранный режим

Выйти из полноэкранного режима


Добавьте IdentityModel в клиентский проект.

dotnet add .\Client\Client.csproj package IdentityModel
Войти в полноэкранный режим

Выйти из полноэкранного режима


Обнаружение конечных точек из метаданных

var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001");
if (disco.IsError)
{
    Console.WriteLine(disco.Error);
    return;
}
Войти в полноэкранный режим

Выйти из полноэкранного режима


Токен запроса

var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "client",
    ClientSecret = "secret",
    Scope = "campelo-api"
});

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return;
}

Console.WriteLine(tokenResponse.AccessToken);
Войти в полноэкранный режим

Выйти из полноэкранного режима


Вызов WebAPI

var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);

var response = await apiClient.GetAsync("");
if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
    Console.WriteLine(JsonSerializer.Serialize(doc, new JsonSerializerOptions { WriteIndented = true }));
}
Войти в полноэкранный режим

Выйти из полноэкранного режима


Запустить клиент

Убедитесь, что IdentityServer и WebAPI запущены, и запустите проект Client, чтобы увидеть что-то вроде этого
Изображение 1

Исходный код


Опечатки или предложения?

Если вы обнаружили опечатку, предложение, которое можно было бы улучшить, или что-то еще, что следует обновить в этом сообщении блога, вы можете получить к нему доступ через репозиторий git и сделать запрос на вытягивание. Если вы чувствуете себя комфортно с github, вместо того, чтобы публиковать комментарий, перейдите непосредственно к и откройте новый запрос на вытягивание с вашими изменениями.