使用ASP.NET Core 2中的令牌或Open ID Connect进行身份验证

时间:2018-01-05 00:50:06

标签: c# asp.net authentication asp.net-core asp.net-core-2.0

类似于应用程序如何通过内置表单或外部身份提供商提供身份验证,我希望为我的网站提供两种身份验证选项;在这种情况下,在Authorization标头中传递的自定义标记(例如API密钥)将在验证时使用,如果没有找到或无效,则打开ID Connect。然后,两者的Cookie Auth将保持会话。

我可以单独工作,但如何将它们结合起来实现上述目标呢?

以下是单独的实施。

Startup.cs中的app.UseAuthentication();方法中都有Configure

Open ID实现在Startup.cs中的ConfigureServices方法中只有以下内容,以及我想要授权的每个控制器方法的[Authorize]属性:

services.AddAuthorization(options =>
{
    options.AddPolicy(OpenIdConnectDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, OpenIdConnectDefaults.AuthenticationScheme));
    options.AddPolicy(CookieAuthenticationDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, CookieAuthenticationDefaults.AuthenticationScheme));
});

services.AddAuthentication(o =>
{
    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(o =>
{
    o.LoginPath = "/security/accessdenied";
    o.AccessDeniedPath = "/security/accessdenied";
})
.AddOpenIdConnect(o =>
{
    o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.ClientId = oidcClientId;
    o.Authority = oidcAuthority;
    o.Scope.Add("openid");
    o.Scope.Add("profile");
    o.Scope.Add("email");
    o.TokenValidationParameters = new TokenValidationParameters
    {
        // Set what is populated in User.Identity.Name
        NameClaimType = ClaimTypes.Email
    };
});

这是Open ID Connect实施的结束。

对于自定义SAS令牌实施,有几件...... 我有一个自定义AuthenticationHandler,如此:

public class SasTokenAuthHandler : AuthenticationHandler<SasTokenAuthOptions>
{
    public SasTokenAuthHandler(IOptionsMonitor<SasTokenAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // get token and parse
        // ...

        if (tokenExists)
        {
            // verify token
            // ...

            if (isVerifiedAndCurrent)
            {
                var identity = new ClaimsIdentity(new[] {
                    new Claim(ClaimTypes.Authentication, SasTokenAuthOptions.Scheme)
                });

                var claimsPrincipal = new ClaimsPrincipal(identity);
                result = AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, SasTokenAuthOptions.Scheme));

                // Create cookie
                var authProperties = new AuthenticationProperties()
                {
                    ExpiresUtc = DateTime.UtcNow.AddDays(10)
                };
                await Context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, authProperties);
            }
            else
            {
                result = AuthenticateResult.Fail("Could not verify signed data");
            }
        }

        return await Task.FromResult(result);
    }
}

在Startup.cs文件中:

services.AddScheme<SasTokenAuthOptions, SasTokenAuthHandler>(SasTokenAuthOptions.Scheme, options =>
{
    var provider = services.BuildServiceProvider();
    options.Logger = provider.GetService<Serilog.ILogger>();
    options.SasTokenService = provider.GetService<SasTokenService>();
    options.CustomApiAuthSettings = provider.GetService<SasTokenAuthSettings>();
});
services.AddAuthorization(options =>
{
    options.AddPolicy(SasTokenAuthOptions.Scheme, policy => 
        policy.RequireClaim(ClaimTypes.Authentication, SasTokenAuthOptions.Scheme));
    options.AddPolicy(CookieAuthenticationDefaults.AuthenticationScheme, policy =>
        policy.RequireClaim(ClaimTypes.Authentication, CookieAuthenticationDefaults.AuthenticationScheme));
});
services.AddAuthentication(o =>
{
    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    o.DefaultAuthenticateScheme = SasTokenAuthOptions.Scheme;
})
.AddCookie(o =>
{
    o.LoginPath = "/security/accessdenied";
    o.AccessDeniedPath = "/security/accessdenied";
})

在每个控制器方法上,我需要进行身份验证:

[Authorize(SasTokenAuthOptions.Scheme)]

也许值得注意:我已经注意到我是否只有[Authorize]然后SAS令牌身份验证无效,但我不确定原因。

这是自定义SAS令牌实现的结束。

我尝试在Startup.cs中添加两组代码,但Open ID Connect始终是使用的。

2 个答案:

答案 0 :(得分:0)

授权构造函数获取策略名称,但您需要自定义身份验证。 使用AuthenticationSchemes属性

更新: 试试这个

[Authorize(AuthenticationSchemes= SasTokenAuthOptions.Scheme)]

答案 1 :(得分:0)

所有auth处理程序代码都已从问题中的代码更改,但一旦更正,则代替使用策略将auth服务配置为指定here。也就是说,不要包含默认方案,而是使用逗号分隔指定Authorize属性中的所有方案。例如

 [None, None, None, 'Mary', None, None, None, None, None, None]

我注意到你要挑战用户的方案(例如重定向)应该是最后一个。