2017-02-23 48 views
7

我的前端應用程序是使用gmail帳戶進行身份驗證如何在服務器端驗證節點js中的Google身份驗證令牌?

我找回id_token後驗證成功並把它作爲認證頭承載令牌

E.g. http://localhost:4000/api

授權承載token_id

的NodeJS服務器端,我調用下面的方法來驗證令牌。

exports.verifyUser = function(req, res, next) { 
    var GoogleAuth = require('google-auth-library'); 
    var auth = new GoogleAuth(); 
    var client = new auth.OAuth2(config.passport.google.clientID, config.passport.google.clientSecret, config.passport.google.callbackURL); 
    // check header or url parameters or post parameters for token 
    var token = ""; 
    var tokenHeader = req.headers["authorization"]; 
    var items = tokenHeader.split(/[ ]+/); 
    if (items.length > 1 && items[0].trim().toLowerCase() == "bearer") { 
     token = items[1]; 
    } 
    if (token) { 
     var verifyToken = new Promise(function(resolve, reject) { 
      client.verifyIdToken(
       token, 
       config.passport.google.clientID, 
       function(e, login) { 
        console.log(e); 
        if (login) { 
         var payload = login.getPayload(); 
         var googleId = payload['sub']; 
         resolve(googleId); 
         next(); 
        } else { 
         reject("invalid token"); 
        } 
       } 
      ) 
     }).then(function(googleId) { 
      res.send(googleId); 
     }).catch(function(err) { 
      res.send(err); 
     }) 
    } else { 
     res.send("Please pass token"); 
    } 
} 

當我調用上面的方法,我總是得到憑證無效具有以下錯誤響應。

Error: No pem found for envelope:  {"alg":"RS256","kid":"c1ab5857066442ea01a01601 
850770676460a712"} 
    at OAuth2Client.verifySignedJwtWithCerts (\node_modules\google-auth-libr 
ary\lib\auth\oauth2client.js:518:13) 
  • 這是爲了驗證令牌正確的方法?
  • 我是否將id_token作爲授權承載發送?或者僅用於授權?
  • 如何將id_token發送到服務器端?通過URL,標題?
  • 我在做什麼錯?

任何幫助,高度讚賞。

回答

2

OAuth2Client.verifyIdToken採取idToken的參數,從library source

/** 
* Verify id token is token by checking the certs and audience 
* @param {string} idToken ID Token. 
* @param {(string|Array.<string>)} audience The audience to verify against the ID Token 
* @param {function=} callback Callback supplying GoogleLogin if successful 
*/ 
OAuth2Client.prototype.verifyIdToken = function(idToken, audience, callback) 

你已經通過了整頭值bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxYWI1OD U3MDY2NDQyZWEwMWEwMTYwMTg1MDc3MDY3NjQ2MGE3MTIifQ所以你必須將頭值分解爲:

var authorization = req.headers["authorization"]; 
var items = authorization.split(/[ ]+/); 

if (items.length > 1 && items[0].trim() == "Bearer") { 
    var token = items[1]; 
    console.log(token); 
    // verify token 
} 

Is this the right approach to verify token ?

是的,這是驗證令牌的正確方法。爲了調試,您還可以驗證與tokeninfo端點令牌,如果您有任何疑問或快速測試:

https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123 
  • Do I send the id_token as Authorization bearer? Or is it for authorization only?
  • How do I send the id_token to the sever side? Thru url, header?

您可以發送JWT令牌授權頭,但是,你必須multiple Authorization headers就可能導致用例。最好將URL編碼或將令牌嵌入到主體中。您可以查看谷歌例如here

此外,以下是由谷歌要求:

  • 令牌必須通過HTTPS POST發送
  • 令牌完整必須得到驗證

爲了優化您的代碼,也可以將您的Google auth對象移動到您的應用程序根目錄中的app.js,而不是在每次驗證令牌時重新定義它。在app.js

var app = express(); 

var GoogleAuth = require('google-auth-library'); 
var auth = new GoogleAuth(); 
app.authClient = new auth.OAuth2(config.passport.google.clientID, config.passport.google.clientSecret, config.passport.google.callbackURL); 

verifyUser調用它從req.app.authClient

req.app.authClient.verifyIdToken(...) 
+0

請你能回答我的其他問題在後? –

+0

我已更新我的帖子,希望它有幫助 –

+0

「您可以在授權標頭中發送JWT令牌,沒有問題」 - >但這不是授權標頭,它用於驗證,我認爲方法不同。如果有人必須同時發送(身份驗證和授權),該怎麼辦? –