Search code examples
node.jsexpressspotifysession-state

Node.js Express Spotify API save in session


Question appeared while integrating Spotify API into Nodejs Express web application using spotify-web-api-node. How multiple simultaneous user requests should be handled? After passing the authentication step, user receives access_token, which is different for each user. Each request can have a session, for example using express-session since access_token is unique for each authenticated user. The weird thing is that I can't find an example with proper session usage in the description and samples https://www.npmjs.com/package/spotify-web-api-node where spotify-web-api-node is used. How is that possible to use global variable without session? Would it make full mess among separate user requests or I'm missing something? I guess that the access_token would be always replaced with latest authenticated user. Another usage example is here https://github.com/thelinmichael/spotify-web-api-node, though it also suggests to use one global instance.


Solution

  • the solution is to store the access_token and refresh_token after successful authentication in the session storage, than before calling Spotify API endpoints set both tokens for the current user from the present session:

    saving tokens in the session after successful authentication:

    app.get('/login', (req,res) => {
      var scopes = [ ... ]
      var authUrl = spotifyApi.createAuthorizeURL(scopes)
      res.redirect(authUrl+"&show_dialog=true")
    })
    
    app.get('/callback', async (req, res) => {
      const { code } = req.query
      try {
        var data = await spotifyApi.authorizationCodeGrant(code)
        const { access_token, refresh_token } = data.body
        spotifyApi.setAccessToken(access_token)
        spotifyApi.setRefreshToken(refresh_token)
    
        req.session.spotifyAccount = { access_token, refresh_token }
    
        res.redirect('...')
      } catch(err) {
        res.send(`error ${err}`)
      }
    });
    
    app.get('/userinfo', async (req,res) => {
      try {
        spotifyApi.setAccessToken(req.session.spotifyAccount["access_token"])
        spotifyApi.setRefreshToken(req.session.spotifyAccount["refresh_token"])
        var result = await spotifyApi.getMe()
        console.log(result.body);
        res.status(200).send(result.body)
      } catch (err) {
        res.status(400).send(err)
      }
    });
    

    since access_token is only identification key which identifies any API request, that ensures that API endpoints are called for the current user. This technique prevents mess and confusion, so that each user can see and manipulate his data only.