【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
问题描述
在APIM中配置对传入的Token进行预验证,确保传入后端被保护的API的Authorization信息正确有效,可以使用validate-jwt策略。validate-jwt
策略强制要求从指定 HTTP 标头或指定查询参数提取的 JSON Web 令牌 (JWT) 必须存在且有效。validate-jwt
策略支持 HS256 和 RS256 签名算法。
- 对于 HS256,必须在策略中以 base64 编码形式提供内联方式的密钥。
- 对于 RS256,密钥可以通过 Open ID 配置终结点来提供,或者通过提供包含公钥或公钥的模数指数对的已上传证书的 ID 来提供。
HS256配置
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unvalid authorization" require-expiration-time="true" require-signed-tokens="true">
<issuer-signing-keys>
<key>在HS256算法中使用的密钥,进行base64编码后的值</key>
</issuer-signing-keys>
<audiences>
<audience>在生成JWT Token时设置的aud值</audience>
</audiences>
</validate-jwt>
RS256配置(附带错误消息)
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unvalid authorization" require-expiration-time="true" require-signed-tokens="true">
<issuer-signing-keys>
<key><RS256 公钥内容通过base64编码后的值></key>
</issuer-signing-keys>
<audiences>
<audience>在生成JWT Token时设置的aud值</audience>
</audiences>
</validate-jwt>
在进行验证时错误消息(文末附录中包含如何在APIM门户中通过Test功能检测策略的执行结果及错误)
validate-jwt (-0.132 ms)
{
"message": "JWT Validation Failed: IDX10503: Signature validation failed.
Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '', InternalId: 'HuvkEY3HBhujvk2qeDfgPFD2iYc-GYrnlDX6Yd1LsYQ'. ,
KeyId: \r\n'.\nExceptions caught:\n 'System.NotSupportedException: IDX10634: Unable to create the SignatureProvider.\nAlgorithm: 'RS256',
SecurityKey: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey, KeyId: '',
InternalId: 'HuvkEY3HBhujvk2qeDfgPFD2iYc-GYrnlDX6Yd1LsYQ'.'\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,
TokenValidationParameters validationParameters)\r\n'.
\ntoken: '{\"typ\":\"jwt\",\"alg\":\"RS256\"}.{\"aud\":\"xxxxx.azure-api.cn\",\"user_id\":123456,\"username\":\"lutpython\",\"exp\":1631786725}'.."
}
那么, 如何来解决RS256 JWT的验证问题呢?
解决方案
正如APIM官网中特别提醒的一句话“对于 RS256,密钥可以通过 Open ID 配置终结点来提供,或者通过提供包含公钥或公钥的模数指数对的已上传证书的 ID 来提供 (英文原文:For RS256 the key may be provided either via an Open ID configuration endpoint, or by providing the ID of an uploaded certificate that contains the public key or modulus-exponent pair of the public key.)” , 所以APIM 中的validate-jwt是不支持使用直接配置公钥(Public Key)。 目前的方案有两种:
1) 使用openid configuration, OpenID Configuration中包含了公钥的内容,是有提供Token的权限服务器管理提供(如 Azure AD中就自动包含OpenID Configuration Endpoint). 注:这部分的详细介绍可以参考官网:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#azure-active-directory-token-validation
2) 把有证书机构(CA)颁发的包含公钥(Publick Key)的 .pfx证书上传到APIM中,然后配置 key certificate-id="<上传在APIM证书中的ID值>"
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unvalid authorization" require-expiration-time="true" require-signed-tokens="true">
<issuer-signing-keys>
<key certificate-id="<上传在APIM证书中的ID值>" />
</issuer-signing-keys>
<audiences>
<audience>在生成JWT Token时设置的aud值</audience>
</audiences>
</validate-jwt>
方案步骤
可以使用以下的步骤来验证RS256 JWT:
1) 使用 openssl 指令创建 证书 (Local.pfx)
openssl.exe req -x509 -nodes -sha256 -days 3650 -subj "/CN=Local" -newkey rsa:2048 -keyout Local.key -out Local.crt
openssl.exe pkcs12 -export -in Local.crt -inkey Local.key -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out Local.pfx
openssl.exe 下载地址:https://slproweb.com/products/Win32OpenSSL.html, 使用时需要 cd到 openssl.exe所在的bin目录中
2)上传 Local.pfx 文件到APIM,并自定义证书ID, 如:apim-rs256-01
3)在APIM的策略中(API级,单个操作级别,或者一组API[产品], 或者全部的APIs)。validate-jwt 内容如下:
<policies>
<inbound>
<base />
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="401 unauthorized">
<issuer-signing-keys>
<key certificate-id="apim-rs256-01" />
</issuer-signing-keys>
</validate-jwt>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
4) 使用以下的C#代码生成 Token
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks; namespace ConsoleAppjwt
{
class Program
{
static void Main(string[] args)
{ // Token Generation
var CLIENT_ID = "Local";
var ISSUER_GUID = "b0123cec-86bb-4eb2-8704-dcf7cb2cc279"; var filePath = @"C:\Users\xxxx\source\repos\ConsoleAppjwt\ConsoleAppjwt\Cert\Local.pfx";
var x509Certificate2 = new X509Certificate2(filePath, "123456789"); var signingCredentials = new X509SigningCredentials(x509Certificate2, SecurityAlgorithms.RsaSha256Signature); //, SecurityAlgorithms.Sha256Digest
var tokenHandler = new JwtSecurityTokenHandler(); var originalIssuer = $"{CLIENT_ID}";
var issuer = originalIssuer; DateTime utcNow = DateTime.UtcNow;
DateTime expired = utcNow + TimeSpan.FromHours(1); var claims = new List<Claim> {
new Claim("aud", "https://login.microsoftonline.com/{YOUR_TENENT_ID}/oauth2/token", ClaimValueTypes.String, issuer, originalIssuer),
new Claim("exp", "1460534173", ClaimValueTypes.DateTime, issuer, originalIssuer),
new Claim("jti", $"{ISSUER_GUID}", ClaimValueTypes.String, issuer, originalIssuer),
new Claim("nbf", "1460533573", ClaimValueTypes.String, issuer, originalIssuer),
new Claim("sub", $"{CLIENT_ID}", ClaimValueTypes.String, issuer, originalIssuer)
}; ClaimsIdentity subject = new ClaimsIdentity(claims: claims); var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = subject,
Issuer = issuer,
Expires = expired,
SigningCredentials = signingCredentials,
}; JwtSecurityToken jwtToken = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;
jwtToken.Header.Remove("typ");
var token = tokenHandler.WriteToken(jwtToken); Console.WriteLine(token);
//Start to Verify Token
Console.WriteLine("Start to Verify Token");
ValidationToken(token); Console.ReadLine();
} static void ValidationToken(string token)
{
try
{
JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
var filePath = @"C:\Users\xxxx\source\repos\ConsoleAppjwt\ConsoleAppjwt\Cert\Local.pfx"; TokenValidationParameters tvParameter = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new X509SecurityKey(new X509Certificate2(filePath, "123456789")),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
};
SecurityToken stoken;
jwtHandler.ValidateToken(token, tvParameter, out stoken);
Console.WriteLine(stoken);
Console.WriteLine("Validate Token Success");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
5) 调用APIM接口对Authorization验证
当然,也可以直接在调用APIM的客户端中进行验证。
附录一:在APIM的接口配置页中,Test页面点击Send按钮,发送API的请求,通过页面中的Trace部分查看每一部分的耗时,处理结果,或错误详情。
参考资料
验证 JWT:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#validate-jwt
How to validate JWT signed with RS256 Algorithm with validate-jwt policy in Azure API management :https://stackoverflow.com/questions/37050233/how-to-validate-jwt-signed-with-rs256-algorithm-with-validate-jwt-policy-in-azur
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token的更多相关文章
- 【Azure API 管理】在APIM 中添加 log-to-eventhub 策略,把 Request Body 信息全部记录在Event Hub中
问题描述 根据文档 https://docs.azure.cn/zh-cn/api-management/api-management-howto-log-event-hubs, 可以将Azure A ...
- 【Azure API 管理】APIM集成内网虚拟网络后,启用自定义路由管理外出流量经过防火墙(Firewall),遇见APIs加载不出来问题
问题描述 使用 Azure 虚拟网络,Azure APIM 可以管理无法通过 Internet 访问的 API,达到以保护企业内部的后端API的目的.在虚拟网络中,启用网络安全组(NSG:Networ ...
- 【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."
API 管理 (APIM) 是一种为现有后端服务创建一致且现代化的 API 网关的方法. 问题描述 在设置了APIM客户端证书,用户保护后端API,让请求更安全. 但是,最近发现使用客户端证书的API ...
- 【Azure API 管理】Azure APIM服务集成在内部虚拟网络后,在内部环境中打开APIM门户使用APIs中的TEST功能失败
问题描述 使用微软API管理服务(Azure API Management),简称APIM. 因为公司策略要求只能内部网络访问,所以启用了VNET集成.集成方式见: (在内部模式下使用 Azure A ...
- 【Azure API 管理】为调用APIM的请求启用Trace -- 调试APIM Policy的利器
问题描述 在APIM中,通过门户上的 Test 功能,可以非常容易的查看请求的Trace信息,帮助调试 API 对各种Policy,在Inbound,Backend, Outbound部分的耗时问题, ...
- 【API管理 APIM】如何查看APIM中的Request与Response详细信息,如Header,Body中的参数内容
问题描述 通过APIM门户或者是Developer门户,我们可以通过Test功能测试某一个接口,通过Trace可以获取非常详细的Request,Response的信息,包含Header,X-Forwa ...
- 【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
问题描述 Azure 的APIM集成虚拟网络有两种方式,外部VNET, 内部VNET. 外部VNET,要求低,可以通过APIM访问VNET中的VM等资源,不需要配置自定义DNS服务器,这种方式下,AP ...
- 【Azure API 管理】解决API Management添加AAD Group时遇见的 Failed to query Azure Active Directory graph due to error 错误
问题描述 为APIM添加AAD Group时候,等待很长很长的时间,结果添加失败.错误消息为: Write Groups ValidationError :Failed to query Azure ...
- 【Azure API 管理】从微信小程序访问APIM出现200的空响应的问题中发现CORS的属性[terminate-unmatched-request]功能
问题描述 使用微信小程序调用APIM(API Management)中的接口,发现POST和PUT请求被拦截,返回的状态码为200,但是无消息内容. 在小程序中的调用JS代码如: 通过浏览器测试得到的 ...
随机推荐
- Linux文件系统与日志文件
目录 一.inode和block 1.1.inode和block概述 1.2.inode的内容 inode包含文件的元信息: 查看inode号两种方式 目录文件的结构 1.3.inode的号码 用户通 ...
- netty系列之:自定义编码和解码器要注意的问题
目录 简介 自定义编码器和解码器的实现 ReplayingDecoder 总结 简介 在之前的系列文章中,我们提到了netty中的channel只接受ByteBuf类型的对象,如果不是ByteBuf对 ...
- 超硬核 Web 前端学霸笔记,学完就去找工作!
文章和教程 Vue 学习笔记 Node 学习笔记 React 学习笔记 Angular 学习笔记 RequireJS 学习笔记 Webpack 学习笔记 Gulp 学习笔记 Python 学习笔记 E ...
- SpringCloud升级之路2020.0.x版-19.Eureka的服务端设计与配置
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford Eureka Se ...
- Xilinx约束学习笔记(一)—— 约束方法学
<Xilinx约束学习笔记>为自己阅读 Xilinx 官方 UG903 文档后的学习笔记,大多数为翻译得来,方便大家学习. 1 约束方法学 1.1 组织约束文件 Xilinx 建议将时序约 ...
- NB-IoT四大关键特性及实现告诉你,为啥NB
摘要:NB- IoT 网络是基于4G网络演进过来的,所以它在上行和下行的复用技术上还是沿用了4G的OFDMA和SC-FDMA. 本文分享自华为云社区<一文了解NB-IoT四大关键特性以及实现技术 ...
- Qt学习笔记(2)-利用StackWidget实现选项卡式页面
学习笔记第二篇,利用Qt实现选项卡式的页面,效果如图1.1-图1.3所示.程序实现的功能是通过点击状态栏实现不同页面的切换,实际上Qt中自带有Tab选项卡式的控件,本文利用StackWidge实现类似 ...
- WPF日积月累之文件监测与DataGrid指定Row的颜色
一.概述 关于DataGrid指定Row的颜色,我们可以使用转换器和DataGridRow的Style来实现.对于文件的检测,我们可以使用FileSystemWatcher来实现. 二.Demo Co ...
- 聊聊 PC 端自动化最佳方案 - Pywinauto
1. 前言 大家好,我是安果! 上一篇文章,聊到 PC 端的一种自动化方案:WinAppDriver 聊聊 PC 端自动化最佳方案 - WinAppDriver 有小伙伴后台给我留言,说「 pywin ...
- ES6——简单的多态
简单的多态 多态: 1.同一个接口,在不同情况下做不一样的事情:相同的接口,不同的表现: 2.接口本身只是一组定义,实现都是子类里面:需要子类去实现的方法(子类只需重写与父类同名的方法,即可达到覆盖的 ...