Search code examples
c#integration-testingidentityserver4

Using IdentityServer4 with WebApplicationFactory Integration Tests


I am trying to get my integration tests working against a protected api endpoint. My test call the IDS connect/token endpoint and gets a valid token. When I use that to call the protected api I always get a failure with invalid_token. (the api is local to the IDS too)

If I manually debug the IDS and use postman to get a token and then manually set it and call the protected api with postman it works fine.

I suspect that the internals of the IDS validation code can't hit the discovery endpoint because it is spinning up its own HttpClient. I know that the WebApplicationFactory Client is a special implementation of HttpClient.

Is there a way that I can inject the WebApplicationFactory client into the IDS during configuration/startup so that it will work?

Or is there a way that I can make a fake authorization endpoint that just validates any token sent in the Auth header?

I would just like my integration tests to be able to work against the api, it would be great if it actually validated the token but if it can't I can fake it.

Thanks.


Solution

  • In usual fashion, right after I ask about something I've been stumped on for hours I figure it out. Here is the simple solution based on this other question which has a somewhat more convoluted answer (How can I set my IdentityServer4 BackChannelHandler from within an xUnit integration test using WebApplicationFactory?).

    In your Startup.cs add a static property:

    /// <summary>
    /// For integrationtesting set this to Factory.Server.CreateHandler()
    /// </summary>
    public static HttpMessageHandler JwtBackChannelHandler { get; set; }
    

    Then add this to your .AddIdentityServerAuthentication() options:

    if (JwtBackChannelHandler != null)
    {
        options.JwtBackChannelHandler = JwtBackChannelHandler;
    }
    

    In your constructor for your test class that implements IClassFixture<WebApplicationFactory<Startup>> add this:

    Startup.JwtBackChannelHandler = Factory.Server.CreateHandler();
    

    This will allow you to call the token endpoint and receive a real token and use that as an authentication header in your integration tests. Hot diggity.