问题描述
集成Azure AD(新名称Microsoft Entra ID),拿到对应的accessToken作为登录用的凭证。这个 AccessToken 能够正常返回,并作为Microsoft Graph userinfo API的Authorization,因为应用中会对前端传递过来的 AccessToken进行校验合法性。但目前遇见的问题时这个 Token 签名校验失败。
“'IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey , KeyId: xxxxxxxxxxxxxxxxxxx”
如下是Token通过JWT.IO解码后的Header部分截图:
问题解答
在查看对Access Token进行JWT解码截图,Header中包含了nonce 参数,这意味着这个Token需要特殊处理,使用常规的JWT验证方法(正常处理)会失败。
## 常规验证AAD Token的 方法:
String stoken = "eyJ0eXAiOiJKV1QiLCJhbGciO......................_-dIQ"; DecodedJWT jwt = JWT.decode(stoken); JwkProvider provider = null; Jwk jwk = null; Algorithm algorithm = null; try { URL keysURL = new URL("https://login.partner.microsoftonline.cn/common/discovery/keys"); provider = new UrlJwkProvider(keysURL); jwk = provider.get(jwt.getKeyId()); algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null); algorithm.verify(jwt); //if the token signature is invalid, the method will throw SignatureVerificationException System.out.println("JWT Validation completed."); } catch (JwkException e) { e.printStackTrace(); } catch (SignatureVerificationException e) { System.out.println(e.getMessage()); }
在GitHub 平台中,关于nonce的说明有:
The 'nonce' is a mechanism, that allows the receiver to determine the token was forwarded. The signature is over the transformed nonce, so if you try and validate it directly, the signature will fail. Graph can determine that this token was replayed.
“随机数”是一种机制,允许接收者确定令牌已转发。签名是在转换后的随机数上进行的,因此如果您尝试直接验证它,签名将会失败。 Graph可以确定该令牌被重放。
同时,也有声明 Microsoft Graph 认识到了提高用户安全性的机会。通过将“nonce”放入 jwt 标头中来实现这一目标。JWS 使用随机数的 SHA2 进行签名,“随机数”在 JWS 序列化之前被替换。
所以自己在应用中验证Token并不是一个有效的办法,可以直接把Token转递给Microsoft Graph userinfo API, 让API自行验证Token。
参考资料
Cannot validate signature : https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!