3

У меня есть приложение ASP.Net Core, настроенное для выдачи и аутентификации токенов-носителей JWT. Клиенты могут успешно извлекать токены на предъявителя и аутентифицироваться с помощью токена, когда сайт размещен в Kestrel.Как настроить ASP.Net TestHost для работы с OpenId Connect?

У меня также есть набор интеграционных тестов, в которых используется Microsoft.AspNetCore.TestHost.TestServer. Перед добавлением проверки подлинности тесты смогли успешно выполнить запросы к приложению. После добавления аутентификации я начал получать ошибки, связанные с доступом к конфигурации открытого идентификатора. Конкретное исключение я вижу это:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] 
     Request starting HTTP/1.1 GET http:// 
fail: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[3] 
     Exception occurred while processing message. 
System.InvalidOperationException: IDX10803: Unable to obtain configuration from: 'http://localhost/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'http://localhost/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found). 

На основании своих исследований, это иногда срабатывает, когда орган установлен на другой хост, чем хостинг-сервер. Например, Kestrel работает по умолчанию по умолчанию http://localhost:5000, и это то, на что я установил свой авторитет сначала, но при настройке на то, что эмулятор TestServer (http://localhost), он по-прежнему дает ту же ошибку. Вот моя конфигурация аутентификации:

app.UseJwtBearerAuthentication(new JwtBearerOptions 
    { 
     AutomaticAuthenticate = true, 
     AutomaticChallenge = true, 
     RequireHttpsMetadata = false, 
     TokenValidationParameters = new TokenValidationParameters 
     { 
      ValidateIssuerSigningKey = true, 
      IssuerSigningKey = signingKey, 
      ValidateAudience = true 
     }, 
     Audience = "Anything", 
     Authority = "http://localhost" 
    }); 

Что нечетное является то, что пытается ударить URL непосредственно из теста Integration работает отлично:

enter image description here

Так как же настроить ASP.Net TestServer и инфраструктуру OpenId Connect для совместной работы?

=== EDIT ====

Размышляя об этом немного, мне пришло в голову, что проблема в том, что внутренние авторизации JWT пытается сделать запрос на http://localhost порт 80, но это ISN Не пытайтесь сделать запрос с помощью TestServer и поэтому ищете настоящий сервер. Поскольку его нет, он никогда не будет аутентифицироваться. Похоже, следующий шаг - посмотреть, есть ли способ отключить проверку полномочий или каким-то образом расширить инфраструктуру, чтобы позволить ему использовать TestServer в качестве хоста.

+0

Ваши правильные изменения. Вы пытались предоставить конфигурацию в своих тестах, которая не устанавливает полномочия? Технически, все ваши тесты должны нуждаться в аутентифицированном Пользователе, который вы можете импровизировать/издеваться - без необходимости использовать аутентификацию JWT вообще. – Brad

+0

Я считаю, что я пытался не устанавливать полномочия, но, похоже, я помню, что он выдавал ошибку. Я закончил поиск решения и отправлю ответ. –

ответ

0

Инфраструктура JWT действительно пытается сделать запрос HTTP по умолчанию. Я был в состоянии получить работу, установив свойство JwtBearerOptions.ConfigurationManager на новый экземпляр OpenIdConnectionConfigurationRetriever(), который поставляется в IDocumentResolver предоставленный DI:

 ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
      authority + "/.well-known/openid-configuration", 
      new OpenIdConnectConfigurationRetriever(), 
      _documentRetriever), 

В производстве код, я просто зарегистрировать по умолчанию с моим контейнером (Autofac):

builder.RegisterType<HttpDocumentRetriever>().As<IDocumentRetriever>(); 

Я уже использовал производный класс настройки для моих интеграционных тестов, которые по образцу метод шаблона для настройки контейнера, так что я смог переопределить экземпляр IDocumentRetriever с той, которая возвращает результаты из экземпляр TestServer.

Я столкнулся с дополнительным препятствием, которое, по-видимому, было связано с тем, что клиент TestServer зависал, когда был сделан запрос (тот, который был инициирован JWT, вызывающим мой IDocumentRetriever), в то время как другой запрос уже выдался (тот, который инициировал запрос для начала с), поэтому я должен был сделать запрос заранее и предоставить результаты кэширования из моего IDocumentRetriever:

public class TestServerDocumentRetriever : IDocumentRetriever 
{ 
    readonly IOpenIdConfigurationAccessor _openIdConfigurationAccessor; 

    public TestServerDocumentRetriever(IOpenIdConfigurationAccessor openIdConfigurationAccessor) 
    { 
     _openIdConfigurationAccessor = openIdConfigurationAccessor; 
    } 

    public Task<string> GetDocumentAsync(string address, CancellationToken cancel) 
    { 
     return Task.FromResult(_openIdConfigurationAccessor.GetOpenIdConfiguration()); 
    } 
} 
+1

Привет @Derek Надеюсь, вы не против, чтобы я захватил эту тему для других людей, использующих IdentityServer4 и пытаясь выполнить интеграционные тесты. Я нашел решение в этой теме http://stackoverflow.com/questions/39390339/integration-testing-with-in-memory-identityserver – JimiSweden

 Смежные вопросы

  • Нет связанных вопросов^_^