我正在尝试通过从 CallingApi 到 MinApi 创建 JWT 令牌来测试我的
.RequireAuthorization()
是否在我的自定义最小 api 端点中工作。
在我的 CallingApi 中,我将生成的令牌添加到 auth 标头中。
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", TokenGenerator.GenerateToken());
var url = $"https://localhost:7215/api/users";
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return Ok(await response.Content.ReadAsStringAsync());
令牌生成代码如下所示:
public static String GenerateToken()
{
var key = Encoding.UTF8.GetBytes("CallMinApiKey-ThisNeedsToBePrettyLong");
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "TestUser")
}),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = "TestIssuer",
Audience = "TestAudience",
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
当我调用 MinApi 时,我收到 401 状态代码。 为了弄清楚原因是什么,我在 CallingApi 中添加了一个令牌验证方法,如下所示:
public static String GenerateToken()
{
var key = Encoding.UTF8.GetBytes("CallMinApiKey-ThisNeedsToBePrettyLong");
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "TestUser")
}),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = "TestIssuer",
Audience = "TestAudience",
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
var testTokenString = tokenHandler.WriteToken(token);
TestValidateToken(testTokenString);
return testTokenString;
}
public static Boolean TestValidateToken(String testTokenString)
{
var token = testTokenString;
var key = Encoding.UTF8.GetBytes("CallMinApiKey-ThisNeedsToBePrettyLong");
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "TestIssuer",
ValidAudience = "TestAudience",
IssuerSigningKey = new SymmetricSecurityKey(key)
};
try
{
tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
Console.WriteLine("Token is valid.");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Unknown error: {ex.Message}");
}
return false;
}
每次验证都会抛出异常,消息为:
IDX10206: Unable to validate audience. The 'audiences' parameter is empty.
但是,我将我的令牌放入 jwt.io,它有一个“aud”值,请参阅: 我的令牌在 jwt.io 上解析
--更新 这是我的 MinApi 的 Program.cs 中的身份验证设置。
var key = Encoding.UTF8.GetBytes("CallMinApiKey-ThisNeedsToBePrettyLong");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "TestIssuer",
ValidAudience = "TestAudience",
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
builder.Services.AddAuthorization();
我做错了什么?
问题是您使用
JwtSecurityTokenHandler
而不是使用 JsonWebTokenHandler
验证令牌。在偶然发现https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/8.0/securitytoken-events之前,我花了几个小时用头撞墙解决同样的问题。这让我发现了问题。