配置不同的授权/认证方案

时间:2016-10-28 20:07:32

标签: c# authentication asp.net-core jwt azure-active-directory

我正在ASP.NET Core 1.0.1应用程序上实现安全性,该应用程序用作Web 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 个答案:

答案 0 :(得分:3)

添加授权策略时以及添加身份验证中间件时使用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。如果删除该错误行,则代码将automatically use the appropriate default.

编辑:样本评论

第二个合理的解决方案

The linked sample application from the comments拨打services.AddAuthentication并将SignInScheme设置为" Cookie"。这会更改所有身份验证中间件的默认登录方案。结果:对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"
});