Схемы политик в ASP.NET Core
Схемы политики проверки подлинности упрощают использование одной логической схемы проверки подлинности. Например, схема политики может использовать проверку подлинности Google для проблем и cookie проверку подлинности для всего остального. Схемы политики проверки подлинности делают его следующими:
- Легко перенаправить любое действие проверки подлинности в другую схему.
- Переадресация динамически на основе запроса.
Все схемы проверки подлинности, использующие производные AuthenticationSchemeOptions и связанные AuthenticationHandler<TOptions>:
- Автоматически используются схемы политики в ASP.NET Core 2.1 и более поздних версий.
- Можно включить с помощью настройки параметров схемы.
public class AuthenticationSchemeOptions
{
/// <summary>
/// If set, this specifies a default scheme that authentication handlers should
/// forward all authentication operations to, by default. The default forwarding
/// logic checks in this order:
/// 1. The most specific ForwardAuthenticate/Challenge/Forbid/SignIn/SignOut
/// 2. The ForwardDefaultSelector
/// 3. ForwardDefault
/// The first non null result is used as the target scheme to forward to.
/// </summary>
public string ForwardDefault { get; set; }
/// <summary>
/// If set, this specifies the target scheme that this scheme should forward
/// AuthenticateAsync calls to. For example:
/// Context.AuthenticateAsync("ThisScheme") =>
/// Context.AuthenticateAsync("ForwardAuthenticateValue");
/// Set the target to the current scheme to disable forwarding and allow
/// normal processing.
/// </summary>
public string ForwardAuthenticate { get; set; }
/// <summary>
/// If set, this specifies the target scheme that this scheme should forward
/// ChallengeAsync calls to. For example:
/// Context.ChallengeAsync("ThisScheme") =>
/// Context.ChallengeAsync("ForwardChallengeValue");
/// Set the target to the current scheme to disable forwarding and allow normal
/// processing.
/// </summary>
public string ForwardChallenge { get; set; }
/// <summary>
/// If set, this specifies the target scheme that this scheme should forward
/// ForbidAsync calls to.For example:
/// Context.ForbidAsync("ThisScheme")
/// => Context.ForbidAsync("ForwardForbidValue");
/// Set the target to the current scheme to disable forwarding and allow normal
/// processing.
/// </summary>
public string ForwardForbid { get; set; }
/// <summary>
/// If set, this specifies the target scheme that this scheme should forward
/// SignInAsync calls to. For example:
/// Context.SignInAsync("ThisScheme") =>
/// Context.SignInAsync("ForwardSignInValue");
/// Set the target to the current scheme to disable forwarding and allow normal
/// processing.
/// </summary>
public string ForwardSignIn { get; set; }
/// <summary>
/// If set, this specifies the target scheme that this scheme should forward
/// SignOutAsync calls to. For example:
/// Context.SignOutAsync("ThisScheme") =>
/// Context.SignOutAsync("ForwardSignOutValue");
/// Set the target to the current scheme to disable forwarding and allow normal
/// processing.
/// </summary>
public string ForwardSignOut { get; set; }
/// <summary>
/// Used to select a default scheme for the current request that authentication
/// handlers should forward all authentication operations to by default. The
/// default forwarding checks in this order:
/// 1. The most specific ForwardAuthenticate/Challenge/Forbid/SignIn/SignOut
/// 2. The ForwardDefaultSelector
/// 3. ForwardDefault.
/// The first non null result will be used as the target scheme to forward to.
/// </summary>
public Func<HttpContext, string> ForwardDefaultSelector { get; set; }
}
JWT с несколькими схемами
Метод AddPolicyScheme может определять несколько схем проверки подлинности и реализовывать логику, чтобы выбрать соответствующую схему на основе свойств токена (например, издателя, утверждений). Такой подход обеспечивает большую гибкость в рамках одного API.
services.AddAuthentication(options =>
{
options.DefaultScheme = Consts.MY_POLICY_SCHEME;
options.DefaultChallengeScheme = Consts.MY_POLICY_SCHEME;
})
.AddJwtBearer(Consts.MY_FIRST_SCHEME, options =>
{
options.Authority = "https://your-authority";
options.Audience = "https://your-audience";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidAudiences = Configuration.GetSection("ValidAudiences").Get<string[]>(),
ValidIssuers = Configuration.GetSection("ValidIssuers").Get<string[]>()
};
})
.AddJwtBearer(Consts.MY_AAD_SCHEME, jwtOptions =>
{
jwtOptions.Authority = Configuration["AzureAd:Authority"];
jwtOptions.Audience = Configuration["AzureAd:Audience"];
})
.AddPolicyScheme(Consts.MY_POLICY_SCHEME, displayName: null, options =>
{
options.ForwardDefaultSelector = context =>
{
string authorization = context.Request.Headers[HeaderNames.Authorization];
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer "))
{
var token = authorization.Substring("Bearer ".Length).Trim();
var jwtHandler = new JsonWebTokenHandler();
if(jwtHandler.CanReadToken(token)) // it's a self contained access token and not encrypted
{
var issuer = jwtHandler.ReadJsonWebToken(token).Issuer; //.Equals("B2C-Authority"))
if (issuer == Consts.MY_THIRD_PARTY_ISS) // Third party identity provider
{
return Consts.MY_THIRD_PARTY_SCHEME;
}
if (issuer == Consts.MY_AAD_ISS) // AAD
{
return Consts.MY_AAD_SCHEME;
}
}
}
// We don't know with it is
return Consts.MY_AAD_SCHEME;
};
});
Примеры
В следующем примере показана схема более высокого уровня, которая объединяет схемы более низкого уровня. Проверка подлинности Google используется для вызовов, а cookie проверка подлинности используется для всего остального:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => options.ForwardChallenge = "Google")
.AddGoogle(options => { });
}
В следующем примере показано, как включить динамический выбор схем на основе каждого запроса. Таким образом, как смешивать файлы cookie и проверку подлинности API:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
// For example, can foward any requests that start with /api
// to the api scheme.
options.ForwardDefaultSelector = ctx =>
ctx.Request.Path.StartsWithSegments("/api") ? "Api" : null;
})
.AddYourApiAuth("Api");
}
ASP.NET Core