2015-05-20 28 views
2

我們正在使用Connect2D OAuth SDK(請參閱:http://connect2id.com/products/nimbus-oauth-openid-connect-sdk)通過Open ID協議驗證Google Apps用戶。用戶報告間歇性問題驗證。偶爾,我們的應用無法驗證從Google Apps收到的令牌。Intermittant Bad Jws簽名不帶Google Apps Open ID身份驗證

OIDToken token = new OIDToken(getApplication(), tokenResponse.getIDToken(), id); 
ReadOnlyJWTClaimsSet claimsSet = null; 
try { 
    claimsSet = token.verify(); 
} catch (Exception e) { 
    throw new SecurityProviderException(994,"failed to verify token:"+e.getMessage()); 
} 

報告的錯誤是:「錯誤的JWS簽名」。

問題是間歇性的。有時它起作用,有時它不起作用。

非常感謝任何建議。

+0

是的,我也看到了。我對令牌過期的時區差異持懷疑態度,因爲它似乎在時間塊中起作用,隨後是時間塊失敗,但我還沒有時間來確認每日重複模式。 –

+0

是的,我希望Google的某個人能對此做出迴應。 – jamie

+0

我正在處理這一點,但我有第二個更好的假設。 Google旋轉其公鑰,用於驗證簽名令牌。我想知道是否有某個公共密鑰緩存正在進行。我可以將令牌傳遞給Google自己的調試API並且沒問題,但是如果我將它們放到http://jwt.io/中,它將無法驗證。 –

回答

2

我很肯定這是答案,但我可能是錯的。我們拭目以待。

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你有兩種選擇:

  1. 實現替代JWTDecoder。
  2. 擴展JWSVerifier實現以支持密鑰ID查找。

第一種方法可能會更容易兩個。

因爲我正在和Apache Shiro合作,所以我不得不與其整合,但是大部分的邏輯是here,儘管我沒有對它進行非常嚴格的測試。該功能分支的其餘部分似乎使用ConnectID強大地對Google OIDC進行身份驗證。

基本原理是添加按鍵旋轉邏輯。

如果您可以更新到4.0的ConnectID,您可能會更快,但由於各種依賴層,我必須堅持使用3.4.1。

+0

斯圖爾特。感謝您的分析。如果您設法獲得工作實施/解決方案,可以讓我們知道。 – jamie

+0

斯圖爾特。在RotatingJWTDecoder.java中,第48行的變量kid1有可能出現null ptr異常。我的解決方法是調用Apache commons return ObjectUtils.compare(kid1,kid2); – jamie

+0

@jamie非常感謝。我已將它記錄爲一個問題,我將在該更改中工作。 –