Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs - Spotify API Refresh Token

First off. I have not worked with APIs before.

The problem I have is to refresh the token. The code that's returned as a query parameter to the redirect URI seems to be needed to be put in manually each time. When I get that authentication code, the code below gets me the new access token, as well as the refresh token.

The package I use is spotify-web-api-node and the code below is a result of following their readme. I have also tried spotify-oauth-refresher but I'm too new to coding to figure it out how to use it.

I've tried following the guide on Spotify's own website as well. But I don't seem to be able to get this right by myself.

Would love some guidance. Thanks. Hope things are clear.

 var scopes = ['user-read-private', 'user-read-email', 'playlist-read-private', 'playlist-modify-private'],
      redirectUri = '<redirect uri>',
      clientId = '<client id>',
      clientSecret = '<client secret>',
      state = '<random string>';
    
    var spotifyApi = new SpotifyWebApi({
      redirectUri: redirectUri,
      clientId: clientId,
      clientSecret: clientSecret
    });
    
    // Create the authorization URL
    var authorizeURL = spotifyApi.createAuthorizeURL(scopes, state);
    
    console.log(authorizeURL);
    
    var credentials = {
      clientId: '<client id>',
      clientSecret: '<client secret>',
      redirectUri: '<redirect uri>'
    };
    
    var spotifyApi = new SpotifyWebApi(credentials);
    
    // The code that's returned as a query parameter to the redirect URI
    var code = 'I HAVE TO MANUALLY PUT THIS IN WHEN THE DURATION RUNS OUT';
    
    // Retrieve an access token and a refresh token
    spotifyApi.authorizationCodeGrant(code).then(
      function(data) {
        console.log('The token expires in ' + data.body['expires_in']);
        console.log('The access token is ' + data.body['access_token']);
        console.log('The refresh token is ' + data.body['refresh_token']);
    
        // Set the access token on the API object to use it in later calls
        spotifyApi.setAccessToken(data.body['access_token']);
        spotifyApi.setRefreshToken(data.body['refresh_token']);
      },
      function(err) {
        console.log('Something went wrong!', err);
      }
    );
    
    // clientId, clientSecret and refreshToken has been set on the api object previous to this call.
    spotifyApi.refreshAccessToken().then(
      function(data) {
        console.log('The access token has been refreshed!');
    
        // Save the access token so that it's used in future calls
        spotifyApi.setAccessToken(data.body['access_token']);
      },
      function(err) {
        console.log('Could not refresh access token', err);
      }
    );

EDIT: I’ve created a working solution and will submit my code when I get time. Hopefully today.

like image 827
flx Avatar asked Oct 29 '25 06:10

flx


2 Answers

Information on best practice Auth Flow directly from Spotify can be found at the link below. It includes code snippets detailing how and when they want you to POST back the refresh token for a new Access Token.

https://developer.spotify.com/documentation/general/guides/authorization/code-flow/

This is the endpoint they recommend for refreshing your token when you detect an Access Token has expired or your Request for data failed due to expired Access Token.

app.get('/refresh_token', function(req, res) {

  var refresh_token = req.query.refresh_token;
  var authOptions = {
    url: 'https://accounts.spotify.com/api/token',
    headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) },
    form: {
      grant_type: 'refresh_token',
      refresh_token: refresh_token
    },
    json: true
  };

  request.post(authOptions, function(error, response, body) {
    if (!error && response.statusCode === 200) {
      var access_token = body.access_token;
      res.send({
        'access_token': access_token
      });
    }
  });
});

The response will look something like this:

{
   "access_token": "NgCXRK...MzYjw",
   "token_type": "Bearer",
   "scope": "user-read-private user-read-email",
   "expires_in": 3600,
   "refresh_token": "NgAagA...Um_SHo"
}

TLDR: You check to see if your Access Token has expired, if so POST the refresh-token to receive a new Access Token that can then again be used to GET data. You also receive a new refresh token along with the response from this and the process starts all over again.

like image 170
ankziety Avatar answered Oct 30 '25 23:10

ankziety


The way I managed to get this to work was by the code below:

const express = require('express');
const SpotifyWebApi = require('spotify-web-api-node');

var generateRandomString = function(length) {
    var text = '';
    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    for (var i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    return text;
};

var scopes = ['user-read-private', 'user-read-email', 'playlist-read-private', 'playlist-modify-private'],
    redirectUri = '<redirect uri>',
    clientId = '<client id>',
    clientSecret = '<client secret>',
    state = generateRandomString(16);

// Setting credentials can be done in the wrapper's constructor, or using the API object's setters.
var spotifyApi = new SpotifyWebApi({
    redirectUri: redirectUri,
    clientId: clientId,
    clientSecret: clientSecret
});

// Create the authorization URL
var authorizeURL = spotifyApi.createAuthorizeURL(scopes, state);

// https://accounts.spotify.com:443/authorize?client_id=5fe01282e44241328a84e7c5cc169165&response_type=code&redirect_uri=https://example.com/callback&scope=user-read-private%20user-read-email&state=some-state-of-my-choice
console.log(authorizeURL);

// --------------------------------

var credentials = {
    clientId: '<client id>',
    clientSecret: '<client secret>',
    redirectUri: '<redirect uri>'
};

var spotifyApi = new SpotifyWebApi(credentials);

var app = express();

app.get('/login', function(req, res) {
    res.redirect(authorizeURL);
});

// The code that's returned as a query parameter to the redirect URI
var code = '<authorization code>'; // this does not need to be updated

// Retrieve an access token and a refresh token
spotifyApi.authorizationCodeGrant(code).then(
    function(data) {
        console.log('The token expires in ' + data.body['expires_in']);
        console.log('The access token is ' + data.body['access_token']);
        console.log('The refresh token is ' + data.body['refresh_token']);

        // Set the access token on the API object to use it in later calls
        spotifyApi.setAccessToken(data.body['access_token']);
        spotifyApi.setRefreshToken(data.body['refresh_token']);
    },
    function(err) {
        console.log('Something went wrong!', err);
    }
);
// --------------------------------------------------
// clientId, clientSecret and refreshToken has been set on the api object previous to this call.
function refreshSpotifyToken() {
    spotifyApi.refreshAccessToken().then(
        function(data) {
            console.log('The access token has been refreshed!');

            // Save the access token so that it's used in future calls
            spotifyApi.setAccessToken(data.body['access_token']);
            console.log('The access token is ' + data.body['access_token']);
            console.log('The token expires in ' + data.body['expires_in']);
        },
        function(err) {
            console.log('Could not refresh access token', err);
        });
};
client.on('ready', () => {
    refreshSpotifyToken();
    setInterval(refreshSpotifyToken, 1000 * 59 * 59);
})
like image 41
flx Avatar answered Oct 31 '25 00:10

flx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!