Невозможно проверить JWT или access_token в API с IdentityServer4 - PullRequest
0 голосов
/ 18 марта 2019

Я работаю над созданием некоторой новой функциональности там, где у нас есть существующая система. Наша цель - обеспечить взаимодействие Angular SPA с API-интерфейсами, чтобы представить новый интерфейс для нашего унаследованного приложения. Команда настроила IdentityServer4 для использования устаревшего приложения для проверки учетных данных.

SPA, написанный на Angular 7, использует неявный поток для аутентификации. Тип ответа "token id_token" Мне удалось заставить этот поток работать так, как я могу позволить неаутентифицированному пользователю зайти на сайт, получить доступ к экранам аутентификации IdentityServer, войти с правильным учетные данные, а затем перенаправлены обратно в приложение. Когда я получаю токен обратно, объект заявок имеет одно значение для aud, client_id для SPA, например, spa-client . Access_token и id_token оба являются JWT с RS256 в качестве метода подписи. Наконец, я создал перехватчик в SPA для отправки JWT (в действительности он просто использует любое значение, отправленное обратно как access_token) в качестве токена «Bearer» в запросах API.

Теперь я создал приложение .NET Core 2.2 WebApi для построения API службы, который будет использоваться SPA. Это приложение использует пакет IdentityServer4.AccessTokenValidation для «защиты» API . Я прочитал раздел в документации IdentityServer4. В моем методе ConfigureServices я написал следующее для настройки аутентификации:

services    
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
    {
        if (string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.Authority)) throw new ConfigurationException("", nameof(serviceConfiguration.Authentication.Authority), "An authority must be defined.");
        if (string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.ApiName)) throw new ConfigurationException("", nameof(serviceConfiguration.Authentication.ApiName), "An api name must be defined.");

        options.Authority = serviceConfiguration.Authentication.Authority;
        options.ApiName = serviceConfiguration.Authentication.ApiName;

        if (!string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.ApiSecret))
        {
            options.ApiSecret = serviceConfiguration.Authentication.ApiSecret;
        }

        options.RequireHttpsMetadata = false;
        options.SupportedTokens = SupportedTokens.Both;
    }

serviceConfiguration - строго типизированное представление моего JSON appsettings.json

Насколько я понимаю, options.SupportedTokens = SupportedTokens.Both проверит JWT и проведет самоанализ.

Теперь, когда все это настроено, я взял простой пример ValuesController, который создается шаблоном API, и добавил к нему атрибут [Authorize]. Выполнение простого запроса GET к этой конечной точке в Postman возвращает 401, как я и ожидал.

Затем я пытаюсь войти в SPA и перейти на тестовую страницу, которая будет делать то же самое, но с перехватчиком будет иметь токен-носитель, access_token или, в основном, JWT. Я все еще получаю 401 от службы.

Глядя на журналы, которые выдает служба, я не вижу ничего полезного:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost [1] Запросить начало HTTP / 1.1 ОПЦИИ http://localhost:5001/api/values info: Microsoft.AspNetCore.Hosting.Internal.WebHost [1] Запросить начало HTTP / 1.1 ОПЦИИ http://localhost:5001/api/values info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] Выполнение политики CORS успешно. информация: Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] Выполнение политики CORS успешно. информация: Microsoft.AspNetCore.Hosting.Internal.WebHost [2] Запрос завершен в 61.1352ms 204 info: Microsoft.AspNetCore.Hosting.Internal.WebHost [2] Запрос завершен в 61.1272ms 204 info: Microsoft.AspNetCore.Hosting.Internal.WebHost [1] Запросить запуск HTTP / 1.1 GET http://localhost:5001/api/values application / json info: Microsoft.AspNetCore.Hosting.Internal.WebHost [1] Запросить запуск HTTP / 1.1 GET http://localhost:5001/api/values application / json info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] Выполнение политики CORS успешно. информация: Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] Выполнение политики CORS успешно. информация: Microsoft.AspNetCore.Routing.EndpointMiddleware [0] Выполнение конечной точки examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) 'info: Microsoft.AspNetCore.Routing.EndpointMiddleware [0] Выполнение конечной точки (Examples.TestApp.API.Web) 'info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [1] Маршрут соответствует {action = "Get", controller = "Values"}. Выполнение действия Examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [1]Маршрут соответствует {action = "Get", controller = "Values"}. Выполнение действия Examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService [2] Авторизация не удалась. информация: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService [2] Авторизация не удалась. информация: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [3] Авторизация не выполнена для запроса в фильтре «Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter». Информация: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [3] Авторизация не выполнена для запроса в фильтре «Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter». Информация: Microsoft.AspNetCore.Mvc.ChallengeResult [1] Выполнение ChallengeResult со схемами аутентификации (). информация: Microsoft.AspNetCore.Mvc.ChallengeResult [1] Выполнение ChallengeResult со схемами аутентификации (). информация: IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler [12] Схема аутентификации: на предъявителя был поставлен вызов. информация: IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler [12] Схема аутентификации: на предъявителя был поставлен вызов. информация: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [2] Выполненное действие examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) в 166.3038ms информация: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [2] Выполненное действие examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) в 162.8827ms информация: Microsoft.AspNetCore.Routing.EndpointMiddleware [1] Выполненная конечная точка 'examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) 'info: Microsoft.AspNetCore.Routing.EndpointMiddleware [1] Выполненная конечная точка 'examples.TestApp.API.Web.Controllers.ValuesController.Get (Examples.TestApp.API.Web) 'info: Microsoft.AspNetCore.Hosting.Internal.WebHost [2] Запрос завершен в 459.6677 мс. 401 info: Microsoft.AspNetCore.Hosting.Internal.WebHost [2] Запрос завершен в 473,7648мс 401

Установка логирования на Трассировка больше ничего не показала.

Я попытался пойти к Почтальону, чтобы посмотреть, смогу ли я сделать самоанализ на токене вручную. Я установил базовую авторизацию и установил имя пользователя «test-api», идентификатор api и пароль, которые я установил в секретном ключе клиента. В теле указан набор x-www-form-urlencoded с ключом «token» и значением access_token. Я получаю 200 OK с претензиями вместе с "active: true". Похоже, это должно быть хорошо, верно?

Мне не принадлежит реализация IdentityServer, поэтому я не совсем уверен, что происходит на этом этапе, за исключением возможности входа в интерфейс администратора. Я вошел в интерфейс администратора для сервера идентификации и дважды проверил настройки для клиента и API. Клиенту предоставляется область действия «API», а API получает такую ​​же область «API». Это показано в области, которая отправляется обратно в ответе на самоанализ, а также в токене, который я получаю от клиента.

Я также пытался установить options.SupportedTokens = SupportedTokens.Reference и options.SupportedTokens = SupportedTokens.JWT. Ни один не имел никаких изменений. (

Что я делаю не так? Это проблема конфигурации или я идиот (возможно, последний).

РЕДАКТИРОВАТЬ : RE access_token и id_token

Я ошибся в исходном вопросе. Токены разные (мне нужно взглянуть не только на часть заголовка).

Аудитория странная. Я никогда не обращал внимания на возможную разницу здесь при декодировании. Мои способности восприятия должны сосать!

Токен доступа имеет aud: "http: /// resources" У id_token есть aud: "spa-client"

1 Ответ

2 голосов
/ 18 марта 2019

access_token и id_token одинаковы и являются JWT с RS256 в качестве метода подписи.

access_token и id_token не должны совпадать. Для id_token утверждение aud в токене должно быть именем клиента, но в токене доступа ваше имя API должно быть включено в aud, чтобы ваш ресурс API мог проверить, что выдан токен доступа для создания " мои "API звонки. Вы можете использовать онлайн-инструмент, такой как jwt.io, для декодирования заявок в токенах JWT. Поскольку вы не опубликовали конфигурацию клиента и IDS4, вам следует проверить тип ответа, область действия ... Если вы используете Fiddler для отслеживания запроса, он должен выглядеть следующим образом:

GET /connect/authorize/callback?client_id=js&redirect_uri=http%3A%2F%2Flocalhost%3A5003%2Fcallback.html&response_type=id_token%20token&scope=openid%20profile%20api1&state=xxxxxxxxxxxxxxx&nonce=xxxxxxxxxxxxxxxxxxx

Кроме того, из документа: http://docs.identityserver.io/en/latest/topics/grant_types.html

Для приложений на основе JavaScript, Implicit больше не рекомендуется. Вместо этого используйте код авторизации с PKCE.

Вы можете нажать здесь для примера кода потока кода.

Обновление:

аудитория маркера доступа также должна включать имя API, кроме "http:///resources:

enter image description here

Вы можете нажать здесь для примеров кода.

...