I'm developing a multi-tenant application with asp.net core 3.1 as the backend. I used JWT to authenticate users. I'm passing the tenantId along with the http request and I would like to validate JWT against tenantIds. To do this, I must pass the tenantIds to JwtBearerOptions.ValidAudience at each client request.
I set options at startup as follows...
public void ConfigureServices(IServiceCollection services){
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtOptions["Issuer"];
configureOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = jwtOptions["Issuer"],
ValidAudience = tenantId,
ValidateIssuerSigningKey = true,
IssuerSigningKey = accessKey,
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
}
Please note that I don't want to pass all tenantIds to ValidateAudiences because each tenant should receive an unique token. e.g. I don't want tenant X's token works for tenant Y.
How do I achieve this?
Thanks in advance!
I ended up using below for validating tenderid and I'm quite happy with the outcome. please let me know if there are drawbacks to approch below, thanks!
ValidAudiences = tenants.Value.Select(x=>x.TenantId).ToList(),
IssuerSigningKeyResolver = (string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) =>
{
var tenant = tenants.Value.Where(t => t.TenantId == kid).FirstOrDefault();
List<SecurityKey> keys = new List<SecurityKey>();
if (tenant != null && kid == tenantsResolver.GetCurrentTenantId())
{
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tenant.SecretKey));
keys.Add(signingKey);
}
return keys;
}