2

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.

Mark Bennetts
  • 183
  • 1
  • 10
  • Are you confirming that the code is absolutely the same in both places? Did you check the urls? Is everything fine with them? – m3n7alsnak3 Feb 13 '18 at 16:13
  • Yes I publish the code directly out of VStudio, deploy to the server and just change the urls in the config files to ensure they are pointing at the right port for the Identity Server. If I make a separate call from postman to the token introspection endpoint, then the token validates just fine. The problem is just with the auto-validation of the token in the IdentityServer OWIN middleware but I cant figure out how to fix it – Mark Bennetts Feb 13 '18 at 17:12
  • Are you using IdSrv3 for validating the JWT's you get from IdSrv4? – huysentruitw Feb 15 '18 at 16:33
  • The server is Identity Server 4, and I am using IdentityServer3.AccessTokenValidation in the WebAPI which is the middleware created by the IdServer team. So its not exactly IdentityServer 3, its just OWIN middleware so it should be irrelevant what target Identity Server version being used. – Mark Bennetts Feb 15 '18 at 17:11
  • @MarkBennetts did you solve this problem eventually? I'm struggling with the same, couldn't find any solution yet. – Márton Balassa Apr 16 '18 at 14:35
  • The only way I could get it to work was to use a full DNS name for the authservers url as per my submitted answer – Mark Bennetts Apr 18 '18 at 09:38

2 Answers2

0

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.

Mark Bennetts
  • 183
  • 1
  • 10
-1

As far as I understand your WebAPI project is used as an API resource.

If so - remove the 'clientId' and 'clientSecret' from the UseIdentityServerBearerTokenAuthentication, keep the 'RequiredScopes' and the authority (you may also need to set ValidationMode = ValidationMode.Both).

You need them, when you are using reference tokens. From what you've said - you are using a JWT one. Check here, here and here.

m3n7alsnak3
  • 3,026
  • 1
  • 15
  • 24
  • Ok, I'm out of the office today, so I'll try removing the ClientID and Secret, although I dont understand why this would make a difference to the JWT validation. The validation mode defaults to Both, I changed it to Local to ensure Local validation is performed in case the IDP validation was being attempted and was failing (its not so I'll revert that too). – Mark Bennetts Feb 14 '18 at 11:21
  • Ok as I suspected this made no difference - the ClientID and Secret are not used during the local validation of the JWT so it makes no difference if I supply them or not. – Mark Bennetts Feb 15 '18 at 09:38