Search code examples
node.jsyoutubegoogle-apiyoutube-apiyoutube-data-api

Node googleapis: getting Error: invalid_request after short period of time


I'm using the node googleapis library to make requests to the youtube data api. I'm starting of with authenticating a user using passport the passport-youtube-v3 library. Everything works fine. I'm able to authenticate and I can make authorized requests to the youtube data api. But after a certain amount of time (around 1-2h) the credentials seem to have expired or just become invalid and I get the following error:

{ Error: Invalid Credentials
    at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:85:15)
    at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
    at emitTwo (events.js:106:13)
    at Request.emit (events.js:191:7)
    at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
    at IncomingMessage.g (events.js:286:16)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:926:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
  code: 401,
  errors: 
   [ { domain: 'global',
       reason: 'authError',
       message: 'Invalid Credentials',
       locationType: 'header',
       location: 'Authorization' } ] }

I understand that auth tokens expire after some time. But according to the documentation this shouldn't happen before 6 months of inactivity. Also I'm not making an excessive amount of requests that could render the tokens invalid. Nevertheless I tried to implement a manual toke refresh of the access token like this:

const fetch = (user, ressource, operation, opts) => {
  let oauth2Client = new OAuth2();
  let client = google.youtube({ version: 'v3',auth: oauth2Client })[ressource][operation];

  oauth2Client.credentials = {
      access_token: user.youtube.token,
      refresh_token: user.youtube.refreshToken
  };

  return new Promise((success, failure) => {
    client(opts, function(err, data, response) {
        if (err)
          if(err.code === 401)
            oauth2Client.refreshAccessToken(function(err, tokens) {
              console.log(err);
            });
          else
            failure(err);
        if (data)
          success(data);
    });
  });
}

I'm not sure if I implemented this correctly of if it even makes sense to do this. I get the following error:

{ Error: invalid_request
    at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:81:15)
    at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
    at emitTwo (events.js:106:13)
    at Request.emit (events.js:191:7)
    at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
    at IncomingMessage.g (events.js:286:16)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:926:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9) code: 400 }

What else could be the issue when getting the first error? Is it possible that the access token expires so quickly? If so, how do I refresh it correctly?

Any help is greatly appreciated!


Solution

  • It seems like the problem was that I didn't instantiate OAuth2 correctly. I didn't pass the credentials of my app to the constructor upon creation. Everything seems to work now.

    let oauth2Client = new OAuth2(
      clientID,
      clientSecret,
      callbackURL
    );
    

    The only confusion I still have is as to why it worked for a couple of requests before it started to throw the error described above.