![](/img/trans.png)
[英]How to pass an integer as the Claim value when creating a new System.Security.Claim in C# (.NET6)?
[英]How to mock "aud" claim in c# Moq
我正在尝试为使用最小起订量的 Azure AD 客户端凭据流实现的身份验证逻辑编写单元测试。
第一个测试用例是检查"Audience"
是否有效。 我正在尝试模拟声明以使用ClaimTypes
设置"aud"
或"appId"
声明,但无法找到ClaimTypes.Aud
类的内容
var identity = new ClaimsIdentity(new Claim[] {
new Claim(ClaimTypes.Name, "Sahil")
});
var mockPrincipal = new Mock<ClaimsPrincipal>(identity);
mockPrincipal.Setup(x => x.Identity).Returns(identity);
mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);
我如何在 C# 中设置“aud”和“appId”声明,或者只需设置 mockPrincipal 以便当它尝试检查“aud”是否有效时返回 false。
我正在尝试为以下代码编写单元测试。
public void Authenticate(JwtBearerOptions options)
{
_configuration.Bind("AzureAD", options);
options.TokenValidationParameters.ValidateAudience = true;
options.TokenValidationParameters.ValidateIssuerSigningKey = true;
options.TokenValidationParameters.ValidateIssuer = true;
options.Events ??= new JwtBearerEvents();
var existingHandlers = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
string appId = GetAppIdFromToken(context);
bool isAllowed = await CheckAppIdIsAllowedAsync(context, appId);
if (isAllowed)
{
_logger.LogInformation($"[{nameof(Authenticate)}] AppId in allow list");
}
else
{
_logger.LogError($"[{nameof(Authenticate)}] AppId {appId} not in allowed list");
}
await Task.CompletedTask.ConfigureAwait(false);
};
options.Events.OnTokenValidated += existingHandlers;
}
private string GetAppIdFromToken(TokenValidatedContext context)
{
string appId = context.Principal.Claims.FirstOrDefault(x => x.Type == "appid" || x.Type == "azp")?.Value;
return appId;
}
private async Task<bool> CheckAppIdIsAllowedAsync(TokenValidatedContext context, string appId)
{
IEnumerable<string> AllowedApps = _configuration.GetSection("AllowedAppPrincipals").Get<string[]>();
var FoundAppId = AllowedApps.FirstOrDefault(a => a == appId);
if (FoundAppId == null)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.ContentType = "application/json";
const string message = "{\"error\" : \"Unacceptable app principal\"}";
byte[] arr = Encoding.ASCII.GetBytes(message);
await context.Response.BodyWriter.WriteAsync(arr);
context.Fail(message);
return false;
}
return true;
}
如何使用 Moq 模拟aud
和appId
声明?
我试图重现如何让观众在我的环境中无效。
当颁发者端点不同或 scope 未正确给出或 scope 与所提及的不同时,通常会发生这种情况。
https://login.microsoftonline.com/xx/oauth2/v2.0/token
在这里我给了 scope 作为 api 而不是 microsoft graph。
但是下一步我正在调用图形端点,所以我收到了无效的观众错误。
https://graph.microsoft.com/v1.0/users/xxx
要检查 mocking 测试,您可以考虑以下几点,因为无法获得 c# 中针对“aud”观众的直接声明 AFAIK。
Aud 声明是
Application ID URI or GUID
标识令牌的预期受众。 在 v2.0 令牌中,受众必须是 API 的客户端 ID ,而在v1.0 令牌中,它可以是请求中使用的客户端 ID 或资源 URI 。
验证它的一种方法是与发行者/观众核对以下方式
您可以根据授权端点提供自定义值
代码:
string AUDIENCE = "<GUID of your Audience according to the app>";
string TENANT = "<GUID of your Tenant>";
private static async Task<SecurityToken> validateJwtTokenAsync(string token)
{
// URL based on your AAD-TenantId
var stsDiscoveryEndpoint = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", TENANT);
//To Get tenant information
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint)
// Get Config from AAD:
var config = await configManager.GetConfigurationAsync();
// Validate token:
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidAudience = AUDIENCE,
ValidIssuer = config.Issuer,
IssuerSigningTokens = config.SigningTokens,
CertificateValidator = X509CertificateValidator.ChainTrust,
};
var validatedToken = (SecurityToken)new JwtSecurityToken();
tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
return validatedToken;
}
或者
var TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
....
ValidIssuer = configuration["JwtAuthentication:Issuer"],
ValidAudience = configuration["JwtAuthentication:Audience"]
};
因此,从验证参数中,您可以了解我们的受众是否有效,这主要发生在发行者与我们预期的不同或范围不正确时。
您可以尝试让那些验证为声明以检查 mocking
public virtual ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { if (string.IsNullOrWhiteSpace(securityToken)) { throw new ArgumentNullException("securityToken"); } if (validationParameters == null) { throw new ArgumentNullException("validationParameters"); } if (validationParameters.ValidateAudience) { if (validationParameters.AudienceValidator.= null) { if (.validationParameters,AudienceValidator(jwt,Audiences. jwt. validationParameters)) { throw new SecurityTokenInvalidAudienceException(string,Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10231; jwt.ToString())). } } else { this,ValidateAudience(jwt,Audiences; jwt. validationParameters), } } ClaimsIdentity identity = this,CreateClaimsIdentity(jwt; issuer. validationParameters). if (validationParameters;SaveSigninToken) { identity;BootstrapContext = new BootstrapContext(securityToken); } validatedToken = jwt; return new ClaimsPrincipal(identity); }
还要检查参考: c# - 如何使用最小起订量模拟 ConfigurationManager.AppSettings - 堆栈内存溢出
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.