title: How to maintain a cache of the public keys from Google's OpenID Connect discovery document
body: <p>I am working on a Node.js server side validation of json web tokens received from cross origin ajax clients. Presumably the tokens are generated by <a href="https://developers.google.com/identity/protocols/OpenIDConnect" rel="nofollow noreferrer">Google OpenID Connect</a> which states the following:</p>
  <blockquote>
  <p>To use Google's OpenID Connect services, you should hard-code the <a href="https://accounts.google.com/.well-known/openid-configuration" rel="nofollow noreferrer">Discovery-document URI</a> into your application. Your application fetches the document, then retrieves endpoint URIs from it as needed.</p>
  <p>You may be able to avoid an HTTP round-trip by caching the values from the Discovery document. Standard HTTP caching headers are used and should be respected.</p>
  <p><em>source:</em> <a href="https://developers.google.com/identity/protocols/OpenIDConnect#discovery" rel="nofollow noreferrer">https://developers.google.com/identity/protocols/OpenIDConnect#discovery</a></p>
  </blockquote>
  <p>I wrote the following function that uses request.js to get the keys and moment.js to add some timestamp properties to a <code>keyCache</code> dictionary where I store the cached keys. This function is called when the server starts.</p>
  <pre><code>function cacheWellKnownKeys(uri) {
    var openid = 'https://accounts.google.com/.well-known/openid-configuration';
  
    // get the well known config from google
    request(openid, function(err, res, body) {
      var config               = JSON.parse(body);
      var jwks_uri             = config.jwks_uri;
      var timestamp            = moment();
  
      // get the public json web keys
      request(jwks_uri, function(err, res, body) {
        keyCache.keys          = JSON.parse(body).keys;
        keyCache.lastUpdate    = timestamp;
        keyCache.timeToLive    = timestamp.add(12, 'hours');
      });
    });
  }
  </code></pre>
  <p>Having successfully cached the keys, my concern now is regarding how to effectively maintain the cache over time.</p>
  <blockquote>
  <p>Since Google changes its public keys only infrequently (on the order of once per day), you can cache them and, in the vast majority of cases, perform local validation.</p>
  <p><em>source:</em> <a href="https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken" rel="nofollow noreferrer">https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken</a></p>
  </blockquote>
  <p>Since Google is changing their public keys every day, my idea with the <code>timestamp</code> and <code>timeToLive</code> properties of <code>keyCache</code> is to do one of two things:</p>
  <ol>
  <li>Set a timeout every 12 hours to update the cache</li>
  <li>Deal with the case where Google changes their public keys in between my 12 hour update cycle. The first failed token validation on my end triggers a refresh of the key cache followed by one last attempt to validate the token.</li>
  </ol>
  <p>This seems like a viable working algorithm until I consider an onslaught of invalid token requests that result in repeated round trips to the well known config and public keys while trying to update the cache.</p>
  <p>Maybe there's a better way that will result in less network overhead. This one line from the first quote above may have something to do with developing a more efficient solution but I'm not sure what to do about it: <code>Standard HTTP caching headers are used and should be respected.</code></p>
  <p>I guess my question is really just this...</p>
  <p><strong>Should I be leveraging the HTTP caching headers from Google's discovery document to develop a more efficient caching solution? How would that work?</strong></p>