Search code examples
node.jsspotifyrefresh-token

When and how should I refresh my Spotify API access token in Node.Js


I am building a small program currently consisting of one .js file that outputs all tracks of a specific Spotify list. Currently I have not managed to build a system that automatically refreshes the access token, this breaking the program after an hour. I am unsure how to implement this feature so I am asking here for help.

I have the access token and refresh token. This is my code, which currently works for an hour.

var request = require("request");
var user = USERNAME;
var token = "Bearer BQBpRXd...Yfofi8A";

var playlists_url = "https://api.spotify.com/v1/users/"+user+"/playlists";

request({url:playlists_url, headers:{"Authorization":token}}, function(err, res){
  if (res){
    var playlists = JSON.parse(res.body);
    playlists.items.forEach(function(playlist, i){
      if (playlists.items[i].id === "4N2...2PDX") {
        var playlist_url = playlists.items[i].href
        request({url:playlist_url, headers:{"Authorization":token}}, function(err, res){
          if (res){
            var playlist = JSON.parse(res.body);
            playlist.tracks.items.slice().reverse().forEach(function(track){
               console.log(track.track.name);
            });
          }
        });
      }
    });
  }
});

I hope someone can help me with this, and maybe provide some better code for me that can help me on my journey.


Solution

  • One way to do this would be to perform a token refresh once you get an unauthorized/expired token response in your request. See the Spotify API docs.

    For example you could do the following:

    NOTE: This code is untested and may need tweaks on your end.

     
    var request = require("request");
    var user = USERNAME;
    const refresh_token = "REFRESH_TOKEN_FROM_INITIAL_AUTH";
    let access_token = "AUTH_TOKEN_FROM_INITIAL_AUTH";
    let token = "BASE64_ENCODED_USER:ACCESS_TOKEN?";
    
    getPlaylists();
    
    function refreshAuthToken(callback) {
      const refreshBody = querystring.stringify({
        grant_type: 'refresh_token',
        refresh_token: refresh_token,
      });
      const req = request(
        {
          // Assuming you have this setup as: https://accounts.spotify.com/api/token
          url: refresh_token_url, 
          method: 'POST',
          headers:{
            // Authorization: Basic <base64 encoded client_id:client_secret>
            'Authorization': token
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': Buffer.byteLength(refreshBody)
          }
        },
        (err, res) => {
          if (res) {
            const resData = JSON.parse(res.body);
            // Set new access tokens
            access_token = resData.access_token;
            // setup your Authorization token, e.g.
            token = btoa(access_token);
            callback();
          } else if (err) {
            // Handle error...
          }
        }
      );
      req.write(refreshBody);
    }
    
    function getPlaylists() {
      request(
        {
          url: playlists_url, 
          headers:{
            "Authorization": token
          }
        }, 
        function(err, res) {
          if (res) {
            var playlists = JSON.parse(res.body);
            playlists.items.forEach(function(playlist, i) {
              if (playlists.items[i].id === "4N2...2PDX") {
                var playlist_url = playlists.items[i].href;
                request(
                  {
                    url:playlist_url, 
                    headers:{"Authorization":token}
                  },
                  function(err, res) {
                    if (res) {
                      var playlist = JSON.parse(res.body);
                      playlist.tracks.items.slice().reverse().forEach(function(track){
                        console.log(track.track.name);
                      });
                    }
                  }
                );
              }
            });
          } else if (err) {
            // Check what type of error
            if (res.statusCode === 401) {
              // Refresh the token, if possible
              refreshAuthentication(getPlaylists);
            }
          }
        }
      );
    }