Azure APIM中JWT令牌验证失败,报错信息不明确
Azure API Management JWT校验策略报错分析与解决
问题场景
在Azure API Management中配置了JWT令牌校验策略,策略代码如下:
<policies> <inbound> <base /> <validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-expiration-time="false" require-scheme="Bearer" require-signed-tokens="true"> <issuer-signing-keys> <key>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmwIDAQAB</key> </issuer-signing-keys> </validate-jwt> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
测试请求携带的Authorization Header为:
Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.NHVaYe26MbtOYhSKkoKYdFVomg4i8ZJd8_-RU8VNbftc4TSMb4bXP3l3YlNWACwyXPGffz5aXHc6lty1Y2t4SWRqGteragsVdZufDn5BlnJl9pdR_kdVFUsra2rWKEofkZeIC4yWytE58sMIihvo9H1ScmmVwBcQP6XETqYd0aSHp1gOa9RdUPDvoXQ5oqygTqVtxaDr6wUFKrKItgBMzWIdNZ6y7O9E0DhEPTbE9rfBo6KTFsHAZnMg4k68CDp2woYIaXbmYTWcvbzIuHO7_37GT79XdIwkm95QJ7hYC9RiwrV7mesbY4PAahERJawntho0my942XheVLmGwLMBkQ
将公钥添加-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标记后,在jwt.io中验证签名通过,但在APIM中启用跟踪测试时,出现如下错误:
validate-jwt (-1.088 ms) { "message": "JWT Validation Failed: IDX10503: Signature validation failed. Token does not have a kid. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '', InternalId: 'D3UHVKlh_cCYIRkkI3Amxvzr2mtlzxMVD-ZG6JwNQqs'. , KeyId: \r\n'. Number of keys in TokenValidationParameters: '1'. \n Number of keys in Configuration: '0'. \nExceptions caught: \n 'System.NotSupportedException: IDX10634: Unable to create the SignatureProvider.\nAlgorithm: 'RS256', SecurityKey: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '', InternalId: 'D3UHVKlh_cCYIRkkI3Amxvzr2mtlzxMVD-ZG6JwNQqs'.'\n is not supported. The list of supported algorithms is available here: https://aka.ms/IdentityModel/supported-algorithms\r\n at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider (SecurityKey key, String algorithm, Boolean willCreateSignatures, Boolean cacheProvider)\r\n at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForVerifying (SecurityKey key, String algorithm, Boolean cacheProvider)\r\n at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature (Byte[] encodedBytes, Byte[] signature, SecurityKey key, String algorithm, SecurityToken securityToken, TokenValidationParameters validationParameters)\r\n at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature (String token, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)\r\n'.\ntoken: 'hidden'..", }
错误原因分析
- 密钥类型识别错误:APIM的
<key>元素默认会将传入的字符串解析为对称密钥(SymmetricSecurityKey),但你的JWT使用的是RS256算法,该算法需要非对称密钥对中的公钥(AsymmetricSecurityKey)来验证签名。对称密钥无法用于RS256的签名验证,因此抛出IDX10634错误。 - jwt.io验证通过的原因:jwt.io会自动识别你提供的是RSA公钥(因为添加了PEM格式的首尾标记),并正确按照非对称密钥逻辑验证签名,而APIM的
<key>标签没有这个自动识别能力。
修正方案
需要将RSA公钥以APIM能识别的非对称密钥格式配置到策略中,有两种常用方式:
方式一:使用XML格式的RSAKeyValue
将你的PEM格式公钥转换为XML格式的RSAKeyValue,替换原策略中的<key>元素:
- 把公钥的PEM格式(带首尾标记)转换为XML格式,可通过在线工具或本地代码完成转换。
- 在策略中用
<rsaKeyValue>标签包裹XML内容,示例如下:
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-expiration-time="false" require-scheme="Bearer" require-signed-tokens="true"> <issuer-signing-keys> <rsaKeyValue> <Modulus>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmwIDAQAB</Modulus> <Exponent>AQAB</Exponent> </rsaKeyValue> </issuer-signing-keys> </validate-jwt>
(注:上述示例中的Modulus和Exponent是从你提供的公钥中提取的,可通过转换工具准确获取对应值)
方式二:使用OpenID Connect元数据端点
如果你的身份提供者支持OpenID Connect,可以直接配置元数据端点,让APIM自动获取公钥,无需手动配置密钥:
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-expiration-time="false" require-scheme="Bearer" require-signed-tokens="true"> <openid-config url="https://your-identity-provider/.well-known/openid-configuration" /> </validate-jwt>
这种方式更易于维护,公钥更新时无需手动修改APIM策略。
内容的提问来源于stack exchange,提问作者finisinfinitatis
相关产品推荐
相关产品推荐

