Search code examples
jwtasp.net-identityasp.net-core-webapimulti-tenantasp.net-core-3.1

How to set JwtBearerOptions dynamically?


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!


Solution

  • 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;
                    }