我很肯定這是答案,但我可能是錯的。我們拭目以待。
Google面臨的主要挑戰是它似乎從其證書端點提供了兩個備用密鑰。這些具有相同的算法,但具有不同的密鑰標識符。它看起來有點像這樣:
{
"keys": [
{
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"kid": "5543f23f58e980646d8088d9393fcc3c1ac69ec5",
"n": "xxx...",
"e": "AQAB"
},
{
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"kid": "da6625b36bc09d300353b28a741ce17525a4c33b",
"n": "yyy...",
"e": "AQAB"
}
]
}
不幸的是,Connect2D JWT解碼器的默認實現選擇單獨的算法(即,只是RS256)的關鍵,因此它是歸因於運氣你哪一個先。它們似乎是按順序添加的,所以計時模式(我猜測)是Google選擇的密鑰的順序相當一致,並與密鑰輪換相結合。
即它的邏輯是(簡化):
JWSAlgorithm alg = signedJWT.getHeader().getAlgorithm();
JWSVerifier verifier = jwsVerifiers.get(alg);
boolean verified = signedJWT.verify(verifier);
這意味着密鑰ID(孩子)被忽略,即使它存在於JWT報頭。實際上,選擇的驗證者有50%可能是錯誤的,因此顯然不會驗證。所有查找都是順序的,因此可能是穩定的,導致觀察到的一致成功或失敗期間的行爲。
正確的實施JWT解碼器應該大概是:
- 使用孩子以及算法來選擇要使用的關鍵
- 如果沒有驗證的可用於給定的孩子,或許應該重新 - 從發現API端點中獲取密鑰。這是因爲無論如何Google都經常改變它的密鑰,所以如果你初始化一次,你永遠不會得到新的密鑰。
所以我的推論是,這是正確的但複雜的OIDC行爲從谷歌,這是不是默認在Connect2D OAuth SDK中實現。
我應該在Connect2D OAuth SDK bitbucket站點上報告這一點。
「解決方法」似乎是不直接使用DefaultJWTDecoder,而是對其進行子類化並添加缺少的邏輯,據我所知,這似乎大部分是可行的,儘管關鍵更新可能需要一點思考。
UPDATE
是是問題,在由註釋證實:https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions/issues/138/google-openid-connect-cant-locate-which。
的評論是:
對不起,是一個有點混淆的,它是雨雲JOSE +智威湯遜的lib,現在已經處理JWTs一個全新的框架(http://connect2id.com/blog/nimbus-jose-jwt-4.0-rc1),然而,它的整合到OIDC SDK仍然在我們的待辦事項列表中。我們目前正在忙於完成Connect2id服務器的新版本,並且在7月29日之前將無法在SDK上投入時間。
如果您使用的SDK OIDC的V3.4.1你有兩種選擇:
- 實現替代JWTDecoder。
- 擴展JWSVerifier實現以支持密鑰ID查找。
第一種方法可能會更容易兩個。
因爲我正在和Apache Shiro合作,所以我不得不與其整合,但是大部分的邏輯是here,儘管我沒有對它進行非常嚴格的測試。該功能分支的其餘部分似乎使用ConnectID強大地對Google OIDC進行身份驗證。
基本原理是添加按鍵旋轉邏輯。
如果您可以更新到4.0的ConnectID,您可能會更快,但由於各種依賴層,我必須堅持使用3.4.1。
是的,我也看到了。我對令牌過期的時區差異持懷疑態度,因爲它似乎在時間塊中起作用,隨後是時間塊失敗,但我還沒有時間來確認每日重複模式。 –
是的,我希望Google的某個人能對此做出迴應。 – jamie
我正在處理這一點,但我有第二個更好的假設。 Google旋轉其公鑰,用於驗證簽名令牌。我想知道是否有某個公共密鑰緩存正在進行。我可以將令牌傳遞給Google自己的調試API並且沒問題,但是如果我將它們放到http://jwt.io/中,它將無法驗證。 –