Search code examples
node.jsyoutube-apigoogle-oauthyoutube-data-apigoogle-api-nodejs-client

How to refresh an access token for the youtube-data-api v3


I'm using v3 of the youtube data api for my server. So far I'm able to create a token by getting a code from the redirect.

                oauth2Client.getToken(req.query.code, function(err, token) {
                    if (err) {
                      console.log('Error while trying to retrieve access token', err);
                      return;
                    }
                    oauth2Client.credentials = token;
                    storeToken(token);
                    res.redirect("/channel");
                  });

I'm storing this token locally, but I have a couple questions on the following;

  1. How do I check if this token is valid when a request is about to be made?
  2. How do I get a new token by using the refresh token if the token I currently have is expired?

Solution

  • The best way to find out if a token is valid is to use it. In the case of an access token just use it to make a call. In the case of a refresh token the answer is the same use it to create a new access token.

    The node.js client library should be handling all your refreshing of the access token for you.

    The first time this code runs a file is created in TOKEN_PATH containing the consent from the user this is the refresh token. If the file exists it will be used to create a new access token as needed.

    const fs = require('fs');
    const readline = require('readline');
    const {google} = require('googleapis');
    
    // If modifying these scopes, delete token.json.
    const SCOPES = ['https://www.googleapis.com/auth/youtube'];
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    const TOKEN_PATH = 'token.json';
    
    // Load client secrets from a local file.
    fs.readFile('credentials.json', (err, content) => {
      if (err) return console.log('Error loading client secret file:', err);
      // Authorize a client with credentials, then call the Google Tasks API.
      authorize(JSON.parse(content), listConnectionNames);
    });
    
    /**
     * Create an OAuth2 client with the given credentials, and then execute the
     * given callback function.
     * @param {Object} credentials The authorization client credentials.
     * @param {function} callback The callback to call with the authorized client.
     */
    function authorize(credentials, callback) {
      const {client_secret, client_id, redirect_uris} = credentials.installed;
      const oAuth2Client = new google.auth.OAuth2(
          client_id, client_secret, redirect_uris[0]);
    
      // Check if we have previously stored a token.
      fs.readFile(TOKEN_PATH, (err, token) => {
        if (err) return getNewToken(oAuth2Client, callback);
        oAuth2Client.setCredentials(JSON.parse(token));
        callback(oAuth2Client);
      });
    }
    
    /**
     * Get and store new token after prompting for user authorization, and then
     * execute the given callback with the authorized OAuth2 client.
     * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
     * @param {getEventsCallback} callback The callback for the authorized client.
     */
    function getNewToken(oAuth2Client, callback) {
      const authUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES,
      });
      console.log('Authorize this app by visiting this url:', authUrl);
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
      });
      rl.question('Enter the code from that page here: ', (code) => {
        rl.close();
        oAuth2Client.getToken(code, (err, token) => {
          if (err) return console.error('Error retrieving access token', err);
          oAuth2Client.setCredentials(token);
          // Store the token to disk for later program executions
          fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
            if (err) return console.error(err);
            console.log('Token stored to', TOKEN_PATH);
          });
          callback(oAuth2Client);
        });
      });
    }