title: How can I decode a google OAuth 2.0 JWT (OpenID Connect) in a node app?
body: <p>I'm having a heck of a time here trying to use google OAuth to authenticate users in my node express app. I can successfully do the OAuth, which returns a response like so:</p>
  
  <pre><code>{
    access_token: 'token string',
    id_token: 'id.string',
    expires_in: 3599,
    token_type: "Bearer"
  }
  </code></pre>
  
  <p>This all makes sense, but I can't for the life of me figure out how to decode the JWT. I am a bit inexperienced in all this, so this is all a bit foreign to me.</p>
  
  <p>Following the instructions listed here: <a href="https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken">https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken</a> I am attempting to decode the JWT locally in my node app.</p>
  
  <p>I installed <a href="https://github.com/hokaccha/node-jwt-simple">https://github.com/hokaccha/node-jwt-simple</a> in my node environment.</p>
  
  <p>And I'm pretty certain I need to use this certificate (<a href="https://www.googleapis.com/oauth2/v1/certs">https://www.googleapis.com/oauth2/v1/certs</a>) in all this somehow to decode it, but I am at a bit of a loss here. I don't really understand how I get the certificate into my node app, and after that how to use it with node-jwt-simple. And I also don't really understand how I know when I need to pull a fresh certificate, vs using a cached one.</p>
  
  <p>Anyone out there with some experience in this that can help me out?</p>
  
  <p>Thanks for any help. I'm totally at a loss at this point.</p>
  
  <p>** Update **</p>
  
  <p>So I have made some progress... Kind of.
  By calling jwt.decode(id_token, certificate, true); I am able to successfully decode the token. Even if the certificate var is an empty object {}. This leaves me with 3 questions still.
  1: What is the best way to get the certificate into my express app using the url from google?
  2: How will I know when I need to pull in a fresh version of it?
  3: It seems like passing in true for noVerify (3rd arg in jwt.decode) is a terrible idea. How can I get that to work without passing that in?
  It looks like perhaps jwt-simple is expecting hs256 and the token is using rs256.</p>
  
  <p>Again, I'm super inexperienced in this, so I may be way off base here.</p>
  
  <p><strong>* UPDATE *</strong>
  Thanks to the help from Nat, I was able to get this working!
  I think I tried every single JWT and JWS node module out there. What I finally landed on is as follows:
  I found that none of the modules that I looked at did quite what I wanted out of the box. I created the following jwt decoding helper methods that I am using to decode the id_token, so I can get the kid from the header.</p>
  
  <pre><code>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, '/');
  }
  </code></pre>
  
  <p>I am using this decoding to determine if I need to pull in a new public cert from: <a href="https://www.googleapis.com/oauth2/v1/certs">https://www.googleapis.com/oauth2/v1/certs</a></p>
  
  <p>Then I am using that public cert and node-jws (<a href="https://github.com/brianloveswords/node-jws">https://github.com/brianloveswords/node-jws</a>) jws.verify(id_token, cert) to verify the signature!</p>
  
  <p>Hooray!
  Thanks again for the extra explanation you gave in your response. That went a long way in helping me understand what I was even trying to do. Hope this might help others too.</p>