我正在使用Microsoft.AspNetCore.Authentication.OpenIdConnect
和Microsoft.AspNetCore.Authentication.JwtBearer
来验证ASP.NET核心应用中的OAuth令牌。如果我禁用了内置的受众群体验证并自行验证了aud
声明,除了字符串比较之外还有什么必要,例如校验和或签名检查吗?
我的具体方案是我有一个纯客户端SPA应用程序使用msal.js(Azure AD OpenId Connect Workflow V2)与具有不同应用程序注册的.NET API交谈(因此不同的ApplicationId / ClientId / Audidence取决于抽象层)。即使使用原始POST
调用,v2 Oauth工作流也不允许我使用具有受众A的访问令牌与受众B交谈.V1不允许我暴露客户端密钥或私钥在浏览器中。我更愿意让API接受多个受众,然后共享应用注册,直到流程存在。
答案 0 :(得分:0)
查看Microsoft.IdentityModel.Tokens的代码,实际执行的验证只是字符串比较。似乎没有任何校验和签名检查。
/// <summary>
/// Determines if the audiences found in a <see cref="SecurityToken"/> are valid.
/// </summary>
/// <param name="audiences">The audiences found in the <see cref="SecurityToken"/>.</param>
/// <param name="securityToken">The <see cref="SecurityToken"/> being validated.</param>
/// <param name="validationParameters"><see cref="TokenValidationParameters"/> required for validation.</param>
/// <exception cref="ArgumentNullException">If 'vaidationParameters' is null.</exception>
/// <exception cref="ArgumentNullException">If 'audiences' is null and <see cref="TokenValidationParameters.ValidateAudience"/> is true.</exception>
/// <exception cref="SecurityTokenInvalidAudienceException">If <see cref="TokenValidationParameters.ValidAudience"/> is null or whitespace and <see cref="TokenValidationParameters.ValidAudiences"/> is null.</exception>
/// <exception cref="SecurityTokenInvalidAudienceException">If none of the 'audiences' matched either <see cref="TokenValidationParameters.ValidAudience"/> or one of <see cref="TokenValidationParameters.ValidAudiences"/>.</exception>
/// <remarks>An EXACT match is required.</remarks>
public static void ValidateAudience(IEnumerable<string> audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
if (validationParameters == null)
throw LogHelper.LogArgumentNullException(nameof(validationParameters));
if (!validationParameters.ValidateAudience)
{
IdentityModelEventSource.Logger.WriteWarning(LogMessages.IDX10233);
return;
}
if (audiences == null)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAudienceException(LogMessages.IDX10207) { InvalidAudience = null });
if (string.IsNullOrWhiteSpace(validationParameters.ValidAudience) && (validationParameters.ValidAudiences == null))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidAudienceException(LogMessages.IDX10208) { InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences) });
foreach (string audience in audiences)
{
if (string.IsNullOrWhiteSpace(audience))
{
continue;
}
if (validationParameters.ValidAudiences != null)
{
foreach (string str in validationParameters.ValidAudiences)
{
if (string.Equals(audience, str, StringComparison.Ordinal))
{
IdentityModelEventSource.Logger.WriteInformation(LogMessages.IDX10234, audience);
return;
}
}
}
if (!string.IsNullOrWhiteSpace(validationParameters.ValidAudience))
{
if (string.Equals(audience, validationParameters.ValidAudience, StringComparison.Ordinal))
{
IdentityModelEventSource.Logger.WriteInformation(LogMessages.IDX10234, audience);
return;
}
}
}
throw LogHelper.LogExceptionMessage(
new SecurityTokenInvalidAudienceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10214, Utility.SerializeAsSingleCommaDelimitedString(audiences), (validationParameters.ValidAudience ?? "null"), Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidAudiences)))
{ InvalidAudience = Utility.SerializeAsSingleCommaDelimitedString(audiences) });
}