Как настроить авторизацию на предъявителя для мультитенантного приложения?
Это одностраничное приложение. В браузере сайта приложения используйте Adal.js для аутентификации пользователей. После аутентификации приложение отправляет запрос на серверную часть 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 возвращает неавторизованный ответ.
UPDATE
Post Общая конечная точка: ходит как арендатор, говорит как арендатор ... но не является арендатором описывает причину проблемы с общим органом.
Вкратце: токен (который отправляется в качестве заголовка канала авторизации и должен быть проверен на стороне сервера) содержит строку «эмитента», например: https://sts.windows.net/<TENAT_ID>
. <TENAT_ID>
- будет реальным <TENAT_ID>
, а не "обычной" строкой.
Таким образом, при проверке заголовка Авторизационного канала строка «эмитента» сравнивается с настроенными параметрами. Параметр разрешения.
Для решения проблемы можно отключить проверку эмитента. И сделай сам:
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}";
}
Я не уверен, что это правильный способ проверки эмитента. Пожалуйста, дайте мне знать, правильно это или нет.