类似于应用程序如何通过内置表单或外部身份提供商提供身份验证,我希望为我的网站提供两种身份验证选项;在这种情况下,在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始终是使用的。
答案 0 :(得分:0)
授权构造函数获取策略名称,但您需要自定义身份验证。 使用AuthenticationSchemes属性
更新: 试试这个
[Authorize(AuthenticationSchemes= SasTokenAuthOptions.Scheme)]
答案 1 :(得分:0)
所有auth处理程序代码都已从问题中的代码更改,但一旦更正,则代替使用策略将auth服务配置为指定here。也就是说,不要包含默认方案,而是使用逗号分隔指定Authorize属性中的所有方案。例如
[None, None, None, 'Mary', None, None, None, None, None, None]
我注意到你要挑战用户的方案(例如重定向)应该是最后一个。