Azure 公钥解释?
Posted
技术标签:
【中文标题】Azure 公钥解释?【英文标题】:Azure Public Keys explained? 【发布时间】:2017-04-08 07:38:44 【问题描述】:我正在更新我的应用程序以使用 Azure Active Directory 作为 OAuth 2.0 身份验证服务器。目前我已成功使用授权码授权类型并接收 access_token 和 id_token 值。
现在,我正在尝试验证返回的 id_token。我按照doco 中概述的步骤进行操作,并且能够找到用于签署 JWT 的公钥。例如,这是 Azure REST 端点返回的记录
据我了解,这些是可用的公钥。我可以将其过滤为一个(使用返回的 JWT 标头中的孩子值)。但我很难理解的是每个字段的含义。
我是否使用 n/e 字段为 SHA256 公钥创建模数和指数值?我是否打算改用 x5c 值?抱歉,如果这是一个明显的问题,但是是否有任何文档说明,给定上述值,如何为其创建公钥?我是用 Java 做的,所以任何具体的东西都会非常感激。
【问题讨论】:
上面的记录好像是 JSON Web Key 格式。如果是这种情况,希望有一些库可以创建适当的 Key 对象。 考虑到包含返回上述数据结构的 REST 端点的属性称为“jwks_uri”,这似乎表明数据元素是 JSON Web Key (JWK) 实例! 这看起来像一个可以创建密钥的相关库:connect2id.com/products/nimbus-jose-jwt 支持,因为我搜索了几个小时,但未能找到这些字段的列表或解释。我正在检索令牌并插入 jwt.io 显示密钥 ID,但是当我将相应的 x5c 或 n 值放入签名字段时,它仍然具有无效签名。我应该使用什么值来使其工作?看到有人也在使用关键页眉和页脚? @RyanD 在 x5c 值之前连接“-----BEGIN CERTIFICATE-----”,在 x5c 值之后连接“-----END CERTIFICATE-----”。跨度> 【参考方案1】:要验证 id_token 的签名,如果您使用 C# 开发,我们可以使用 JwtSecurityTokenHandler
类。您可以参考JsonWebTokenValidator.cs 的代码示例来使用此类。为了方便,我也复制了这个类:
public class JsonWebTokenValidator
public JwtSecurityToken Validate(string token)
string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint);
OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
TokenValidationParameters validationParameters = new TokenValidationParameters
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningTokens = config.SigningTokens,
ValidateLifetime = false
;
JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();
SecurityToken jwt;
var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);
return jwt as JwtSecurityToken;
【讨论】:
【参考方案2】:这是我发布的类似question 并获得了帮助,这可能会有所帮助。我认为您想使用完整的证书链 x5c,并从中获取公钥来验证 JWT 的签名。模数和指数(n 和 e)将仅生成证书链中第一个证书的公钥,但这不足以验证签名。
这是我用来从端点提取公钥的一些代码 sn-ps。 AzurePublicKey 类只是 json 的 POJO。
private PublicKey convertKey(AzurePublicKey azKey)
PublicKey publicKey = null;
BigInteger modulus = new BigInteger(1, Base64.getUrlDecoder().decode(azKey.getN()));
BigInteger exponent = new BigInteger(1, Base64.getUrlDecoder().decode(azKey.getE()));
try
publicKey = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
// load cert
CertificateFactory factory;
X509Certificate cert = null;
try
factory = CertificateFactory.getInstance("X.509");
cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(azKey.getX5c().iterator().next())));
catch (CertificateException e)
e.printStackTrace();
// grab public key
publicKey = (RSAPublicKey)cert.getPublicKey();
System.out.println("[");
System.out.println("kid : " + azKey.getKeyIdentifier());
System.out.println("e : " + azKey.getE());
System.out.println("n : " + azKey.getN());
System.out.println("Maybe this : " + DatatypeConverter.printBase64Binary(publicKey.getEncoded()) );
System.out.println("]");
catch (InvalidKeySpecException | NoSuchAlgorithmException e)
// TODO Auto-generated catch block
e.printStackTrace();
return publicKey;
以及使用该公钥使用 JJWT 库验证签名的代码。
Jws<Claims> claims = Jwts.parser()
.setSigningKeyResolver(signingKeyResolver)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""));
String issuer = claims.getBody().getIssuer();
if(issuer == null || !VALID_ISSUERS.contains(issuer))
throw new IncorrectClaimException(claims.getHeader(), claims.getBody(), "Invalid Issuer in Token.", new Throwable("Invalid Issuer in Token."));
SigningKeyResolverImpl 仅根据令牌标头的kid
提供正确的公钥。如果解析没有引发异常,您可以根据您期望的值验证令牌声明,因为我已经根据我期望的 VALID_ISSUERS
列表验证了颁发者。
已经有一段时间了,所以我很模糊,但我希望这会有所帮助。
【讨论】:
我刚刚检查了模数和指数产生的密钥与 X509 证书提取的密钥相同。但是,我无法验证 jwt.io 网站上 azure ad 生成的任何令牌的单个签名。您使用的是 2.0 版还是旧版? 原谅我,不确定什么版本?对于 jjwt 库,看起来 0.9.0 是最新的,但我使用的是 0.7.0。 mvnrepository.com/artifact/io.jsonwebtoken/jjwt 抱歉,我的意思是您用来获取密钥的 Microsoft api 版本。我的处理方式与您类似,但我提取的密钥都没有验证我的 jwt 令牌的签名。 啊,是的。 v2.0 来自这个 URL:login.microsoftonline.com/common/discovery/v2.0/keys以上是关于Azure 公钥解释?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 microsoft azure vault 中配置 RSA HSM 私钥和公钥?
通过 R 使用 Linux Azure DSVM 进行 SSH 公钥身份验证
如何在 azure-pipelines 中使用公钥对某些内容进行 scp?
如何通过 SSH 在 azure devops 管道复制文件中使用公钥