1

My application is an ASP.NET Core 1.0 Web API.

I would like to test my controllers with the TestServer. I have a controller class decorated with the Authorize attribute.

If Iam testing the controller without being decorated with theAuthorize attribute, eveything works fine. Therefore my TestServer setup is correct.

Iam doing the following to set the AuthenticationHeader :

client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", this.RequestToken(client).Result);

and request the Bearer-Token from my TestServer:

private async Task<string> RequestToken(HttpClient client)
  {
     var requestTokenUri = "secret";
     var tokenModel = new List<KeyValuePair<string, string>>
                         {
                            new KeyValuePair<string, string>("tokendata", "secret"),
                            new KeyValuePair<string, string>("tokendata", "secret"),
                            new KeyValuePair<string, string>("tokendata", "secret"),
                            new KeyValuePair<string, string>("tokendata", "secret")
                         };

     var tokenPostData = new FormUrlEncodedContent(tokenModel);
     var tokenRequestResult = await client.PostAsync(requestTokenUri, tokenPostData);

     tokenRequestResult.EnsureSuccessStatusCode();

     var body = JObject.Parse(tokenRequestResult.Content.ReadAsStringAsync().Result);
     var token = (string)body["access_token"];

     return token;
  }

This also works. If i print the Result of RequestToken(HttpClient) it gives me a valid Bearer token and the call tokenRequestResult.EnsureSuccessStatusCode(); also works.

Now, if I then decorate my controllers with Authorize and try to test my controllers like this (snipped) it fails:

  [TestMethod]
  public async Task ShouldDoSomething()
  {
     // Arrange
     var data = JsonConvert.SerializeObject("Just some data");

     // Test
     var response = await this.client.PostAsync(this.requestUri, jsonContent);

     // Assert
     response.EnsureSuccessStatusCode();
  }

remember: this works, if the controller is not decorated with the Authorize attribute.

But if Iam doing this with the Bearer-token and the AuthenticationHeadervalue, Iam getting the following error, as soon as its calling await this.client.PostAsync(this.requestUri, jsonContent);:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Error: Exception occurred while processing message.

System.InvalidOperationException: IDX10803: Unable to obtain configuration from: 'http://localhost:5000/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'http://localhost:5000/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.WinHttpException: Die Serververbindung konnte nicht hergestellt werden at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.WinHttpHandler.d__105.MoveNext() --- End of inner exception stack trace ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.HttpClient.d__58.MoveNext() --- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.d__8.MoveNext() --- End of inner exception stack trace ---

at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.d__8.MoveNext() --- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.d__3.MoveNext() --- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext() --- End of inner exception stack trace ---

at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext() --- End of stack trace from previous location where exception was thrown ---

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.d__1.MoveNext() Ausnahme ausgelöst: "System.InvalidOperationException" in System.Private.CoreLib.ni.dll Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 2204.6107ms 200

I tried to set the BackchannelHttpHandler from the JWTBearerOptions to the one i get from the TestServer. But this is not possible since I need a WebHostBuilder object to create my TestServer:

protected HttpClient GetClient(IWebHostBuilder builder)
  {
     if (builder == null)
     {
        builder = new WebHostBuilder().UseContentRoot(GetDirPath())
           .UseStartup<Startup>()
           .UseEnvironment("Development")
           .ConfigureServices(services =>
              {
                 services.AddTransient<IAuthRepo, TestAuthRepo>();
                 services.AddTransient<IOtherRepo, TestOtherRepo>();
              });
     }
     var server = new TestServer(builder);
...

Now how should I set the BackChannelHandler inside the process of creating the TestServer, without having a TestServer yet?

Can anyone help me?

Thank you

Moritz Schmidt
  • 2,635
  • 3
  • 27
  • 51

0 Answers0