如何在YARP路由中验证不同API的JWT受众(Audience)?
在YARP中实现多Azure AD租户、多受众的JWT验证
这个场景完全可以实现,不少开发者在构建跨租户API网关时都做过类似实践,以下是具体实现方案:
1. 少量租户/受众的静态配置方案
如果涉及的租户和API数量不多,可以直接为每个租户单独注册JWT认证方案,明确指定对应的租户ID和受众(API客户端ID):
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer("Tenant1Auth", options => { options.Authority = "https://login.microsoftonline.com/你的租户1ID"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = true, ValidAudiences = new[] { "租户1对应的API客户端ID" }, ValidateIssuer = true, ValidIssuer = "https://login.microsoftonline.com/你的租户1ID/v2.0" }; }) .AddJwtBearer("Tenant2Auth", options => { options.Authority = "https://login.microsoftonline.com/你的租户2ID"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = true, ValidAudiences = new[] { "租户2对应的API客户端ID" }, ValidateIssuer = true, ValidIssuer = "https://login.microsoftonline.com/你的租户2ID/v2.0" }; });
接着为每个路由绑定对应的授权策略:
builder.Services.AddAuthorization(options => { options.AddPolicy("Tenant1Policy", policy => policy.RequireAuthenticatedUser() .AddAuthenticationSchemes("Tenant1Auth")); options.AddPolicy("Tenant2Policy", policy => policy.RequireAuthenticatedUser() .AddAuthenticationSchemes("Tenant2Auth")); });
最后在YARP路由配置中关联策略:
"ReverseProxy": { "Routes": { "Tenant1Api": { "ClusterId": "Tenant1Cluster", "Match": { "Path": "/tenant1/api/{**catch-all}" }, "AuthorizationPolicy": "Tenant1Policy" }, "Tenant2Api": { "ClusterId": "Tenant2Cluster", "Match": { "Path": "/tenant2/api/{**catch-all}" }, "AuthorizationPolicy": "Tenant2Policy" } }, "Clusters": { "Tenant1Cluster": { "Destinations": { "Tenant1Service": { "Address": "https://tenant1-api.yourdomain.com/" } } }, "Tenant2Cluster": { "Destinations": { "Tenant2Service": { "Address": "https://tenant2-api.yourdomain.com/" } } } } }
2. 大量租户/受众的动态验证方案
如果租户或API数量较多,逐个配置方案效率太低,可以用自定义验证逻辑实现动态匹配:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = "https://login.microsoftonline.com/common/"; // 多租户通用端点 options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, // 自定义Issuer验证:检查租户是否在允许列表中 IssuerValidator = (issuer, token, parameters) => { var tenantId = issuer.Split('/')[3]; // 从Issuer字符串提取租户ID var allowedTenants = new List<string> { "租户ID1", "租户ID2" }; // 维护允许的租户列表 if (allowedTenants.Contains(tenantId)) { return issuer; } throw new SecurityTokenInvalidIssuerException("无效的租户"); }, // 自定义Audience验证:根据请求路由匹配对应API的客户端ID AudienceValidator = (audiences, token, parameters) => { var requestPath = parameters.HttpContext.Request.Path; string requiredAudience = string.Empty; if (requestPath.StartsWithSegments("/tenant1/api")) { requiredAudience = "租户1API客户端ID"; } else if (requestPath.StartsWithSegments("/tenant2/api")) { requiredAudience = "租户2API客户端ID"; } return !string.IsNullOrEmpty(requiredAudience) && audiences.Contains(requiredAudience); } }; });
这种方式只需要一个认证方案,通过自定义验证器动态匹配租户和受众,适合规模较大的场景。
3. 关键注意事项
- 认证中间件必须在YARP中间件之前注册,确保请求先完成认证再转发:
app.UseAuthentication(); app.UseAuthorization(); app.MapReverseProxy(); - 因为只需要验证用户已认证,所以授权策略仅保留
RequireAuthenticatedUser即可,无需额外的Scope检查。 - 验证通过后,YARP会自动转发原
Authorization头部到后端API,确保后端能正常识别身份。
内容的提问来源于stack exchange,提问作者EmilioV
相关产品推荐
相关产品推荐

