Настройка различных схем авторизации / аутентификации

Я реализую безопасность в приложении ASP.NET Core 1.0.1, которое используется в качестве веб-API. Я пытаюсь понять, если и как реализовать 2 разные схемы аутентификации.
В идеале я хотел бы разрешить аутентификацию через Azure Active Directory или через имя пользователя / пароль для определенных внутренних служб, которые связываются с приложением.
Можно ли настроить ASP.NET Core для такой настройки, при которой конечная точка проходит аутентификацию через Azure AD или токен JWT?

Я пробовал что-то подобное, но после вызова конечной точки генерирования токена я получаю 500 без какой-либо информации. Удаление конфигурации Azure AD позволяет конечной точке работать идеально:

services.AddAuthorization(configuration =>
{
    configuration.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser().Build());

    configuration.AddPolicy("OpenIdConnect", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser().Build());
});

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    ClientId = Configuration["Authentication:AzureAD:ClientId"],
    Authority 
        = Configuration["Authentication:AzureAd:AADInstance"] 
        + Configuration["Authentication:AzureAd:TenantId"],
    ResponseType = OpenIdConnectResponseType.IdToken,
    SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme
});

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    TokenValidationParameters = new TokenValidationParameters
    {
        ClockSkew = TimeSpan.FromMinutes(1),
        IssuerSigningKey = TokenAuthenticationOptions.Credentials.Key,
        ValidateAudience = true,
        ValidateIssuer = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidAudience = TokenAuthenticationOptions.Audience,
        ValidIssuer = TokenAuthenticationOptions.Issuer
     }
});

1 ответ

Решение

Использовать OpenIdConnectDefaults.AuthenticationScheme постоянная при добавлении политики авторизации и при добавлении промежуточного программного обеспечения для аутентификации.

Здесь вы используете OpenIdConnectDefaults, Хорошо. Держите эту линию.

services.AddAuthorization(configuration =>
{
    ...

    configuration.AddPolicy("OpenIdConnect", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme) // keep
        .RequireAuthenticatedUser().Build());
 });

Здесь вы используете CookieAuthenticationDefaults, Удалить эту строку.

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    ...

    SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme // delete
});

Зачем?

Когда ваша политика авторизации OpenIdConnect запускается, она будет искать схему аутентификации с именем OpenIdConnectDefaults.AuthenticationScheme, Он не найдет его, потому что зарегистрированное промежуточное ПО OpenIdConnect называется CookieAuthenticationDefaults.AuthenticationScheme, Если вы удалите эту ошибочную строку, то код будет автоматически использовать соответствующую настройку по умолчанию.

Редактировать: Комментарий к образцу

Второе разумное решение

Связанный пример приложения из комментариев звонков services.AddAuthentication и устанавливает SignInScheme в "печенье". Это изменяет схему входа по умолчанию для всего промежуточного программного обеспечения аутентификации. Результат: вызов app.UseOpenIdConnectAuthentication теперь эквивалентно этому:

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions 
{
    SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme
}

Это именно то, что Камило имел в первую очередь. Так почему мой ответ сработал?

Мой ответ сработал, потому что не важно, что SignInScheme имя мы выбираем; важно то, что эти имена соответствуют друг другу. Если мы установим нашу схему входа для аутентификации OpenIdConnect в "Cookies", то при добавлении политики авторизации нам нужно будет запросить эту схему по имени, например так:

services.AddAuthorization(configuration =>
{
    ...

    configuration.AddPolicy("OpenIdConnect", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme) <----
        .RequireAuthenticatedUser().Build());
});

Третье разумное решение

Чтобы подчеркнуть важность согласованности, вот третье разумное решение, которое использует произвольный знак в имени схемы.

services.AddAuthorization(configuration =>
{
    configuration.AddPolicy("OpenIdConnect", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes("Foobar")
        .RequireAuthenticatedUser().Build());
});

Здесь вы используете CookieAuthenticationDefaults, Удалить эту строку.

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    SignInScheme = "Foobar"
});
Другие вопросы по тегам