我已經指定了一個需要范圍的授權策略my_custom_value,例如
services.AddAuthorization(AuthConfig.GetAuthorizationOptions);
// ...
public static void GetAuthorizationOptions(AuthorizationOptions options)
{
options.AddPolicy("MyPolicy", policy =>
{
policy.RequireScope("my_custom_value");
});
對受保護的端點的請求MyPolicy失敗,因為 Principal 不包含任何范圍
我可以看到我的身份驗證令牌具有以下范圍:
"scope": [
"openid",
"profile",
"my_custom_value",
"offline_access"
],
看起來這些沒有被映射到委托人的宣告。當我稍后在用戶嘗試訪問受保護端點時檢查宣告時,沒有范圍。
policy.RequireAssertion(context =>
{
if (context.User.HasClaim(c => c.Type == "scope")) // <-- always false
{
if (context.User.HasClaim(c => c.Value == "my_custom_value"))
{
return true;
}
}
為什么范圍沒有被映射?我需要做什么來映射它們?
作為參考,我已經嘗試過
options.ClaimActions.MapUniqueJsonKey(JwtClaimTypes.Scope, "scope");
options.Scope.Add("my_custom_value");
我應該實作自定義 IProfileService 以在OnUserInformationReceived事件中包含范圍嗎?
uj5u.com熱心網友回復:
當使用 MVC 進行 oidc auth 時,只有 IdentityToken 宣告被映射到 ClaimsPrincipal。我想不出一種方法來映射或包含對 ClaimsPrincipal 的訪問令牌宣告。
我最終撰寫了一個授權處理程式來驗證訪問令牌并執行所需的宣告檢查。我假設您閱讀了 asp.net 5.0 中的授權策略。
public class AccessTokenAuthorizationHandler : AuthorizationHandler<AccessTokenRequirement> {
readonly IOptionsMonitor<OpenIdConnectOptions> _openIdConnectOptions;
readonly ILogger<AccessTokenAuthorizationHandler> _logger;
readonly IOptions<OpenIdOptions> _openIdOptions;
public AccessTokenAuthorizationHandler(
ILogger<AccessTokenAuthorizationHandler> logger,
IOptionsMonitor<OpenIdConnectOptions> openIdConnectOptions,
IOptions<OpenIdOptions> openIdOptions) {
_logger = logger;
_openIdConnectOptions = openIdConnectOptions;
_openIdOptions = openIdOptions;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, AccessTokenRequirement requirement) {
if (context == null) {
throw new ArgumentNullException(nameof(context));
}
if (requirement == null) {
throw new ArgumentNullException(nameof(requirement));
}
if (context.Resource is Microsoft.AspNetCore.Mvc.ActionContext actionContext) {
ClaimsPrincipal principal = await GetAccessTokenPrincipal(actionContext.HttpContext).ConfigureAwait(false);
// verify your requirement
if (condition met) {
context.Succeed(requirement);
}
}
}
private async Task<ClaimsPrincipal> GetAccessTokenPrincipal(HttpContext httpContext) {
if (httpContext == null) {
return null;
}
String accessToken = await httpContext.GetUserAccessTokenAsync().ConfigureAwait(false);
if (!String.IsNullOrWhiteSpace(accessToken)) {
try {
TokenValidationParameters validationParameters = await BuildValidationParameters();
return new JwtSecurityTokenHandler().ValidateToken(accessToken, validationParameters, out var rawValidatedToken);
}
catch (SecurityTokenValidationException validationException) {
_logger.LogWarning(validationException, "Access token not valid.");
}
catch (Exception ex) {
_logger.LogError(ex, "Access token could not be validated.");
}
}
return null;
}
private async Task<TokenValidationParameters> BuildValidationParameters() {
var options = _openIdConnectOptions.Get(OpenIdConnectDefaults.AuthenticationScheme);
var discoveryDocument = await options.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);
var signingKeys = discoveryDocument.SigningKeys;
var validationParameters = new TokenValidationParameters {
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = options.Authority,
ValidateIssuerSigningKey = true,
IssuerSigningKeys = signingKeys,
ValidateLifetime = true,
ValidateAudience = true,
ValidAudience = "your audience",
ValidateActor = false,
ValidTypes = new String[] { "at jwt" },
ClockSkew = TimeSpan.FromMinutes(2),
};
return validationParameters;
}
}
我不高興我不得不這樣做,盡管我認為它做得很好。檢索我正在使用的訪問令牌nuget package IdentityModel.AspNetCore, Version=3.0.0.0
我不明白為什么沒有更多的人有這個問題。當然,如果您的應用程式使用來自 api 的資料,您將傳遞訪問令牌,然后訪問令牌將成為宣告主體。但是,如果您的 mvc 應用程式執行直接資料庫訪問(并且可能稍后提取到 api),您需要以某種方式能夠檢查訪問令牌的宣告。也許我們有一些概念上的誤解......
關于組態檔服務。我認為嘗試將訪問令牌宣告包含到身份令牌中不是正確的方法。我認為這是不可能的,因為當為身份令牌呼叫服務時,您沒有關于請求范圍的資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/333241.html
標籤:asp.net-mvc 授权 asp.net 身份 身份 基于声明的身份
