Search code examples
jwtidentityserver4identityserver3owin-middleware

Identity Server 4 issued JWT Validation failure


I have an Identity Server running based on IdentityServer 4 (.Net Core v2) targeting the full .Net framework, and I have an ASP.NET WebAPI built against ASP.Net Web API 2 (i.e. NOT .Net Core) that is using the Identity Server 3 OWIN middleware for token authentication.

When running locally, everything works just fine - I can use Postman to request an Access Token from the Identity Server using a RO Password flow, and I can then make a request to the WebAPI sending the token as a Bearer token - all works fine.

Now, when everything is hosted on our test servers, I get a problem when calling the WebAPI - I simply get an Unauthorized response. The token returned from the Identity server is ok (checked using http://jwt.io), but validation of the JWT is failing in the WebAPI. On further investigation, after adding Katana logging, I see that a SecurityTokenInvalidAudienceException is being reported.

Audience validation failed. Audiences: 'https://11.22.33.44:1234/resources, XXXWebApi'. Did not match: validationParameters.ValidAudience: 'https://localhost:1234/resources' or validationParameters.ValidAudiences: 'null'

Looking at the JWT audience, we have:

aud: "https://11.22.33.44:1234/resources", "XXXWebApi"

In the WebAPI Startup, I have the call to

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = , // path to our local ID Server
            ClientId = "XXXWebApi",
            ClientSecret = "XXX_xxx-xxx-xxx-xxx",
            RequiredScopes = new[] { "XXXWebApi" }
        });

So the JWT audience looks ok, but its obviously not matching with what is supplied by the middleware (built from the IdP discovery end point). I would have thought that because I am specifying the RequiredScopes to include XXXWebApi that would have been enough to match the JWTs audience but that seems to be ignored.

I'm unsure what to change in the WebAPI authentication options to make this work.

EDIT: I changed the WebAPI Token auth options to use the validation endpoint, and this also fails in the IdentityServer with the same error. If I call the Identity Server introspection endpoint directly from Postman with the same token though, it succeeds.


Solution

  • Ok, so after a lot of head scratching and trying various things out I at least have something working.

    I had to ensure the Identity Server was hosted against a publicly available DNS, and configure the Authority value in the IdentityServerBearerTokenAuthenticationOptions to use the same value.

    That way, any tokens issued have the xx.yy.zz full domain name in the JWT audience (aud), and when the OWIN validation middleware in the WebAPI verifies the JWT it uses the same address for comparison rather than localhost.

    I'm still slightly confused why the middleware cant just use the scope value for validation because the token was issued with the API resource scope (XXXWebAPi) in the audience, and the API is requesting the same scope id/name in the options as shown.