Reputation: 23
I am hosting identity server behind a reverse proxy on a subpath of the root url (example.com/subpath
).
For external api's behind the same proxy (example.com/apisubpath
) token validation is working correctly.
Now I added an api on the same service that hosts IdentityServer as documented in Adding more API endpoints.
Requesting a token with the scope IdentityServerApi
is working fine and when testing it in my local dev environment without the reverse proxy I call the api successfully.
Behind the reverse proxy I get an error: Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10205: Issuer validation failed. Issuer: 'https://example.com/subpath'. Did not match: validationParameters.ValidIssuer: 'https://example.com' or validationParameters.ValidIssuers: 'null'.
So it gets the right domain from the requests but it does'nt include the sub path when 'registering' the validationParameters.ValidIssuer
it seems.
Is there a way to set the validationParameters.ValidIssuer
manually or am I doing something else wrong?
Thanks for your help
Upvotes: 0
Views: 1221
Reputation: 855
Firstly, there is no such specific check/relation between deployment strategy, it's all about how you are validating the token. As you haven't posted the ID4 validation middleware configuration I will just explain what exactly happens while validating the token.
I think there is a lot of confusion regarding ID4 Issuer validation, So let's deep dive into it. By default ID4 includes the hosting path as an issuer, lets say if you have an ID4 app deployed in IIS and its virtual path is https://localhost/IdentityServer
then this path would be your issuer in the token. Here you can verify your token. So as it's taking issuer as your hosted application path, which means issuer would be different for each IdS4 instance which is deployed in different environments (it's helpful when you don't want to share your token with multiple environments (Staging and Production) or instances). But you can anyway set this issuer URL in the ID4 app by setting the below option.
services.AddIdentityServer(options => {
options.IssuerUri = "https://MyDNS/Common"
});
By doing this you should be able to validate your token across the environment or IdS4 instances. If you don't want a static issuer which may lead to a security loophole where the user can your pre-prod environments token to call prod API then you may be interested in the next section which is middleware configuration in consumer API.
.AddJwtBearer
:There is another middleware developed by the IdS4 team themselve (.AddIdentityServerAuthentication()
) but they are no longer maintaining the code and as per the latest documents they are suggesting .AddJwtBearer()
.
In the previous section, we covered the token provider's configuration (In our case IdS4) to set static issuer but in case you don't want to do that as it opens up security concerns then consumer configuration would be your next step to follow. Below code snippet is the basic minimum configuration required to validate the token.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://MyID4Domain/"
options.RequireHttpsMetadata = false; // Non-PROD
options.TokenValidationParameters.ValidateAudience = false;
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
Log.Logger.Error($"Authentication failed. {context.Exception.InnerException}");
return Task.CompletedTask;
}
};
});
If you have your WebApi protected using above code then .AddJwtBearer()
middleware by default expects options.Authority
URL as an issuer in our case it's https://MyID4Domain/
, but you can override that check with a valid issuer which is expected in your token.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters.ValidIssuer = "SomeOtherIssuer"; // If you have different issuer than your Authority url.
**OR**
options.TokenValidationParameters.ValidIssuers = ["Issuer1", "issuer2", "issuer3"]; // In case deployed on multiple instances and wanted to validate token which is generated from any of these instance.
// Kind of multi-tenant support. I know there is a different mechanism that is coming along with ID5.
**OR**
options.TokenValidationParameters.ValidateIssuer = false; // If you don't want to validate issuer at all.
}
Happy coding!
Upvotes: 1
Reputation: 1680
There're a few way to get this thing work, with Identity Server 4
Host
header that came from client request. Otherwise just explicitly set Issuer on Identity Server 4:// This one was on the Identity server
services.AddIdentityServer(opts => opts.IssuerUri = "The explicit Url came here!")
// This one was on the other services, If not set to the same instance of Identity Server
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false, // If set to true, It's gonna take care of the issuer
ValidIssuer = "If we just have a single Issuer, set it here",
ValidIssuers = new []{"Multiple", "Issuer", "Came", "Here"}
};
});
connect/token
have Host
header of https://example.com/subpath
, while it should be https://example.com
, so... just choose some of the options above that suit the mostUpvotes: 2