2013-11-23 12 views
32

Qui sto provando un po 'di tempo cercando di utilizzare google OAuth per autenticare gli utenti nella mia app express del nodo. Posso fare con successo l'OAuth, che restituisce una risposta in questo modo:Come posso decodificare un google OAuth 2.0 JWT (OpenID Connect) in un'app di nodo?

{ 
    access_token: 'token string', 
    id_token: 'id.string', 
    expires_in: 3599, 
    token_type: "Bearer" 
} 

Tutto questo ha un senso, ma non posso per la vita di me capire come decodificare il JWT. Sono un po 'inesperto in tutto questo, quindi questo è tutto un po' estraneo a me.

Seguire le istruzioni elencate qui: https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken Sto tentando di decodificare il JWT localmente nell'app del mio nodo.

Ho installato https://github.com/hokaccha/node-jwt-simple nell'ambiente del mio nodo.

E sono abbastanza certo di aver bisogno di usare questo certificato (https://www.googleapis.com/oauth2/v1/certs) in tutto questo in qualche modo per decodificarlo, ma sono un po 'in perdita qui. Non capisco veramente come ottengo il certificato nell'app del mio nodo e, successivamente, come usarlo con node-jwt-simple. Inoltre, non capisco come faccio a sapere quando devo ritirare un nuovo certificato, contro l'utilizzo di uno in cache.

Qualcuno là fuori con un po 'di esperienza in questo che può darmi una mano?

Grazie per qualsiasi aiuto. Sono totalmente in perdita a questo punto.

** Aggiornamento **

così ho fatto qualche progresso ... Una specie. Chiamando jwt.decode (id_token, certificate, true); Sono in grado di decodificare con successo il token. Anche se il certificato var è un oggetto vuoto {}. Questo mi lascia ancora con 3 domande. 1: Qual è il modo migliore per ottenere il certificato nella mia app Express utilizzando l'URL di Google? 2: Come faccio a sapere quando ho bisogno di tirarne una nuova versione? 3: Sembra che passare true per noVerify (3rd arg in jwt.decode) sia una pessima idea. Come posso farlo funzionare senza farlo passare? Sembra che forse jwt-simple si aspetta hs256 e il token sta usando rs256.

Ancora una volta, sono super-inesperto in questo, quindi potrei essere fuori base qui.

* AGGIORNAMENTO * Grazie all'aiuto di Nat, sono riuscito a farlo funzionare! Penso di aver provato ogni singolo modulo nodo JWT e JWS. Ciò a cui sono finalmente atterrato è il seguente: Ho scoperto che nessuno dei moduli che ho visto ha fatto esattamente quello che volevo fuori dalla scatola. Ho creato i seguenti metodi helper di decodifica jwt che sto usando per decodificare l'id_token, in modo da poter ottenere il bambino dall'intestazione.

module.exports = { 
    decodeJwt: function (token) { 
    var segments = token.split('.'); 

    if (segments.length !== 3) { 
     throw new Error('Not enough or too many segments'); 
    } 

    // All segment should be base64 
    var headerSeg = segments[0]; 
    var payloadSeg = segments[1]; 
    var signatureSeg = segments[2]; 

    // base64 decode and parse JSON 
    var header = JSON.parse(base64urlDecode(headerSeg)); 
    var payload = JSON.parse(base64urlDecode(payloadSeg)); 

    return { 
     header: header, 
     payload: payload, 
     signature: signatureSeg 
    } 

    } 
} 

function base64urlDecode(str) { 
    return new Buffer(base64urlUnescape(str), 'base64').toString(); 
}; 

function base64urlUnescape(str) { 
    str += Array(5 - str.length % 4).join('='); 
    return str.replace(/\-/g, '+').replace(/_/g, '/'); 
} 

Sto usando questo decodificazione per determinare se ho bisogno di tirare in una nuova cert pubblica da: https://www.googleapis.com/oauth2/v1/certs

Poi sto usando che cert pubblico e nodo-JWS (https://github.com/brianloveswords/node-jws) jws.verify (id_token , cert) per verificare la firma!

Urrà! Grazie ancora per la spiegazione extra che hai dato nella tua risposta. Mi ha aiutato molto a capire cosa stavo cercando di fare. Spero che questo possa aiutare anche gli altri.

risposta

48

Dal punto di vista disciplinare, quello che si è verificato è [OpenID Connect].

id_token è un [JWS] firmato [JWT]. In questo caso, è un "." stringa separata con tre componenti. La prima parte è l'intestazione. Il secondo è il carico utile. Il terzo è la firma. Ognuna di esse è una stringa codificata Base64url.

Quando si decodifica l'intestazione, si otterrà qualcosa di simile a:

{ "alg": "RS256", "bambino": "43ebb53b0397e7aaf3087d6844e37d55c5fb1b67"}

Il "alg" indica che l'algoritmo di firma è RS256, che è definito in [JWA]. Il "ragazzo" indica l'ID della chiave della chiave pubblica che corrisponde alla chiave utilizzata per firmare.

ora sono pronto a rispondere ad alcune delle vostre domande:

2: Come faccio a sapere quando ho bisogno di tirare in una nuova versione di esso?

Quando il figlio del file cert memorizzato nella cache (un file [JWK]) non corrisponde al capretto nell'intestazione, preleva un nuovo file cert. (A proposito, l'URL da cui si tira i certs sono chiamati x5u.)

3: Sembra che passando vero per noVerify (3 ° arg in jwt.decode) è una pessima idea. Come posso convincere quello per funzionare senza passare che in?

Infatti. Forse potresti voler guardare un'altra libreria come kjur.github.io/jsjws/.

Riferimenti

  • [OpenID Connect] openid.bitbucket.org/openid-connect-core-1_0.html
  • [JWS] tools.ietf.org/html/draft-ietf- jose-jSON-web-firma
  • [JWT] tools.ietf.org/html/draft-ietf-oauth-json-web-token
  • [JWK] tools.ietf.org/html/draft-ietf -oauth-jSON-web-keys
  • [JWA] tools.ietf.org/html/draft-ietf-j ose-json-web-algorithms
+0

Fantastico! Grazie mille per la spiegazione completa e dettagliata. Questo ha aiutato moltissimo a capire cosa stavo cercando di fare. E ora so cosa dovrei cercare se ho altre domande. Lo apprezzo molto. – ThePuzzleMaster