1

我使用Google's OpenIDConnect authentication,我想驗證從Google返回的JWT id_token。但是,文檔似乎並不一致,Google在ID標記中爲iss(發行者)聲明返回的值爲多少。我可以爲Google OpenIDConnect id_token獲得一致的'iss'值嗎?

One page說,「ISS:總是accounts.google.com」,但another page說「在ID令牌ISS的值等於或accounts.google.comhttps://accounts.google.com」,並在示例代碼中的註釋進一步解釋:

// If you retrieved the token on Android using the Play Services 8.3 API or newer, set 
// the issuer to "https://accounts.google.com". Otherwise, set the issuer to 
// "accounts.google.com". If you need to verify tokens from multiple sources, build 
// a GoogleIdTokenVerifier for each issuer and try them both. 

我有一個服務器端應用程序,而不是一個Android應用程序,所以我沒有使用Play服務。

爲了進一步渾水摸魚,the OpenIDConnect specification itself包含一個需要注意的是:

實施者可能想知道,截至發稿時,谷歌的部署ID連接實施問題ID令牌省略所需https://來自iss(發行者)聲明值的計劃前綴。希望與Google合作的依賴方實施因此需要有代碼來解決這個問題,直到他們的實施更新。任何這樣的解決方法代碼應該以不會中斷的方式編寫,Google會將缺少的前綴添加到其發佈者值中。

該文件的日期爲2014年11月8日。從那時起,谷歌是否已經對iss價值進行了標準化,還是我真的需要檢查兩者?上面的評論似乎表明,只有播放服務> = 8.3獲得isshttps://,而其他地方的值將只是accounts.google.com。真的嗎?

回答

0

首先,我絕對同意Google的文檔是一個模糊的業務。

有幾個不同的方式,你可以驗證在服務器端的ID令牌的完整性(順便說一句this就是你要找的頁面):

  1. 「手動」 - 不斷下載Google的公鑰,驗證簽名,然後檢查每個字段,包括iss;我認爲主要優點(儘管我認爲很小)可以最大限度地減少發送給Google的請求數量)。
  2. 「自動」 - 做谷歌的端點的GET來驗證此令牌 - 目前爲止最簡單: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
  3. 使用谷歌API客戶端庫 - 開銷可能不值得,C#沒有一個正式的一個等

我建議你去第二個選項,讓谷歌擔心驗證算法。

+0

並且在該頁面上此刻還表示:「ID令牌中的iss值等於」accounts.google.com「或」https:// accounts.google.com「。 –

+0

同意;如果你沿着這條路走下去,你可能必須檢查兩種可能性 –

+1

謝謝,這並不能完全回答我的問題,因爲你一般在談論如何驗證Google'id_token'。我具體詢問'iss'字段。聽起來好像你在說「不,沒有辦法獲得一致的價值,你必須檢查兩種可能性。」 – bjmc

0

你必須檢查兩種可能性。這對我來說是...

解碼令牌以獲得發行者。如果發行人不等於https://accounts.google.comaccounts.google.com中的任何一個,您可以在此停止。這是一個無效的標記。

如果發行人與上述任何一個Google字符串相同,則將相同的解碼髮卡方值傳遞給驗證步驟。

以下是我在JavaScript寫了一些Node.js的快遞中間件的實現:

function authorize(req, res, next) { 
    try { 
     var token  = req.headers.authorization; 
     var decoded  = jwt.decode(token, { complete: true }); 
     var keyID  = decoded.header.kid; 
     var algorithm = decoded.header.alg; 
     var pem   = getPem(keyID); 
     var iss   = decoded.payload.iss; 

     if (iss === 'accounts.google.com' || iss === 'https://accounts.google.com') { 
      var options = { 
       audience: CLIENT_ID, 
       issuer: iss, 
       algorithms: [algorithm] 
      } 

      jwt.verify(token, pem, options, function(err) { 
       if (err) { 
        res.writeHead(401); 
        res.end(); 
       } else { 
        next(); 
       } 
      });    

     } else { 
      res.writeHead(401); 
      res.end(); 
     } 
    } catch (err) { 
     res.writeHead(401); 
     res.end(); 
    } 
} 

注意:此功能使用jsonwebtokenjwk-to-pem節點模塊。我省略了最終將json網絡密鑰轉換爲pem格式的getPem函數的細節。

相關問題