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.
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);
}
}
}
);
}