title: getSignedURL() in Google Cloud Function produces link that works for several days, then returns "SignatureDoesNotMatch"
body: <p>My Firebase Storage <code>getSignedUrl()</code> download links work for a few days, then stop working. The error message is </p>
  
  <pre><code>SignatureDoesNotMatch
  The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
  </code></pre>
  
  <p>Last summer there was a long <a href="https://github.com/googleapis/nodejs-storage/issues/244" rel="noreferrer">discussion</a> of this on GitHub but I don't see that a solution was reached. </p>
  
  <p>I'm thinking of using <code>getDownloadURL()</code> from the front end instead of using <code>getSignedUrl()</code> from the back end. Is <code>getDownloadURL()</code> less secure then <code>getSignedUrl()</code>?</p>
  
  <p>Here's my code, which is mostly copied from the <a href="https://cloud.google.com/nodejs/docs/reference/storage/2.3.x/File#getSignedUrl" rel="noreferrer">documentation</a>:</p>
  
  <pre class="lang-js prettyprint-override"><code>let audioType = 'mp3';
  const {Storage} = require('@google-cloud/storage');
  const storage = new Storage();
  const bucket = storage.bucket('my-app.appspot.com');
  var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + wordFileType);
  
    // Firebase Storage file options
    var options = {
      metadata: {
        contentType: 'audio/' + audioType,
        metadata: {
          audioType: audioType,
          longAccent: 'United_States',
          shortAccent: 'US',
          longLanguage: 'English',
          shortLanguage: 'en',
          source: 'Oxford Dictionaries',
          word: word
        }
      }
    };
  
    const config = {
      action: 'read',
      expires: '03-17-2025',
      content_type: 'audio/mp3'
    };
  
    function oedPromise() {
      return new Promise(function(resolve, reject) {
        http.get(oedAudioURL, function(response) {
          response.pipe(file.createWriteStream(options))
          .on('error', function(error) {
            console.error(error);
            reject(error);
          })
          .on('finish', function() {
            file.getSignedUrl(config, function(err, url) {
              if (err) {
                console.error(err);
                return;
              } else {
                resolve(url)
              }
            });
          });
        });
      });
    }
  </code></pre>