【发布时间】:2018-10-11 16:01:30
【问题描述】:
如何为多租户应用设置承载授权?
它是单页应用程序。在浏览器站点应用程序上,使用 Adal.js 对用户进行身份验证。身份验证后,应用程序使用 Authorization Bearer 标头向 ASP.Net-Core 服务器端发送请求。
ASP.Net-Core 使用Microsoft.AspNetCore.Authentication.JwtBearer 来检查请求。这是启动:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));
// ... other ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// ... other ...
}
}
这里是 AddAzureAdBearer 方法:
public static class AzureAdServiceCollectionExtensions
{
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder)
=> builder.AddAzureAdBearer(_ => { });
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureAzureOptions>();
builder.AddJwtBearer();
return builder;
}
private class ConfigureAzureOptions : IConfigureNamedOptions<JwtBearerOptions>
{
private readonly AzureAdOptions AzureOptions;
public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
{
AzureOptions = azureOptions.Value;
}
public void Configure(string name, JwtBearerOptions options)
{
options.Audience = AzureOptions.ClientId;
// this works (specific TenantId)
// options.Authority
// = "https://login.microsoftonline.com/f8811864-6950-4347-af1c-9d22bb3d0615"
// this did not work (common instead of specific TenantId)
// options.Authority
// = "https://login.microsoftonline.com/common";
options.Authority = $"{AzureOptions.Instance}{AzureOptions.TenantId}";
}
public void Configure(JwtBearerOptions options)
{
Configure(Options.DefaultName, options);
}
}
}
对于单租户,这可以按预期工作,可以使用 [Authorize] 属性标记控制器
[Route("api/[controller]")]
[Authorize]
public class CalendarController : Controller
{
对于多租户,我将 Adal.js 设置为公共端点,它正在工作(用户可以成功登录)。但是 ASP.Net-Core 服务器无法检查 Bearer 标头,对于单租户
JwtBearerOptions.Authority = "https://login.microsoftonline.com/f8811864-6950-4347-af1c-9d22bb3d0615"
对于多租户我尝试发送上去
JwtBearerOptions.Authority = "https://login.microsoftonline.com/common"
ASP.Net-Core 服务器返回未经授权的响应。
更新
发帖The Common Endpoint: Walks Like a Tenant, Talks Like a Tenant… But Is Not a Tenant用普通权限描述问题的原因。
简而言之:令牌(作为 Authorization Bearer 标头发送,并且必须在服务器端进行验证)包含“颁发者”字符串,如下所示:https://sts.windows.net/<TENAT_ID>。 <TENAT_ID> - 将是真实的 <TENAT_ID> 不是“普通”字符串。
因此,当 Authorization Bearer 标头验证后,“issuer”字符串与配置的 options.Authority 设置进行比较。
要解决此问题,可以禁用颁发者验证。自己制作:
public void Configure(string name, JwtBearerOptions options)
{
options.Audience = AzureOptions.ClientId;
options.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuer = false
};
options.Events = new JwtBearerEvents()
{
OnTokenValidated = (context) =>
{
if(!context.SecurityToken.Issuer.StartsWith("https://sts.windows.net/"))
throw new SecurityTokenValidationException();
return Task.FromResult(0);
}
};
options.Authority = $"{AzureOptions.Instance}{AzureOptions.TenantId}";
}
我不确定检查发行人的方法是否正确。请让我知道它是否正确。
【问题讨论】:
标签: azure azure-active-directory asp.net-core-webapi adal bearer-token