Benjamin Friedman
Benjamin Friedman

Reputation: 31

How do I store and send authorization tokens with API requests using OAuth?

I'm trying to set my application up so I can use the Spotify API. Their API requires an Authorization token along with every request, and this token is different every user session. I have successfully implemented OAuth2 login using the 'passport-spotify' module (detail below) and have the token, which I am currently storing in my database. Once it is in the database, it is also available in my Redux store.

Functioning Passport strategy:

  const spotifyConfig = {
    clientID: process.env.SPOTIFY_CLIENT_ID,
    clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
    callbackURL: process.env.SPOTIFY_CALLBACK
  }

  const strategy = new SpotifyStrategy(spotifyConfig, (accessToken, refreshToken, profile, done) => {
    const spotifyId = profile.id
    const name = profile.displayName
    const email = profile.emails[0].value

    User.find({where: {spotifyId}})
      .then(foundUser => (foundUser
        ? foundUser.update({accessToken, refreshToken}).then(() => done(null, foundUser))
        : User.create({name, email, spotifyId, accessToken, refreshToken})
          .then(createdUser => done(null, createdUser))
      ))
      .catch(done)
  })

  passport.use(strategy)


router.get('/', passport.authenticate('spotify', {scope: ['user-read-email'], showDialog: true}))

router.get('/callback', passport.authenticate('spotify', {
  successRedirect: '/home',
  failureRedirect: '/login'
}))

What I am currently stuck on is how to set up my API requests so it accesses that token on every call. The 'spotify-web-api-node' node module has a setCredentials method, but I can't figure out how to access the token.

Semi-functioning API call (it makes the API request but gives me a 403 unauthorized):

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

const spotifyApi = new SpotifyWebApi();

spotifyApi.setCredentials({
  clientId: 'my client id',
  clientSecret: 'my client secret',
  redirectUri: 'http://localhost:8888/auth/spotify/callback',
  refreshToken: 'cant figure out how to properly include this',
  accessToken: 'and this.',
});


export function searchMetallica(){
  return spotifyApi.searchArtists('Metallica')
  .then(function(data) {
    console.log(data.body);
  }, function(err) {
    console.error(err);
  });
}

I hope this isn't too much a of a newbie question. Thanks in advance.

Upvotes: 0

Views: 1108

Answers (1)

arirawr
arirawr

Reputation: 1275

You're very close!

You need to pass the token to the setAccessToken() method on the Spotify wrapper, in your case:

spotifyApi.setAccessToken(<youraccesstoken>);

You can set the refresh token in a predictably similar way:

spotifyApi.setRefreshToken(<yourrefreshtoken>);

Easy peasy!

But, there's a catch. If you use this spotifyApi for all your calls, this will set the same access token for all those calls! You need to make sure to use the appropriate access token for each user, so user A can't do actions for user B and vice versa.

You can get around this by simply instantiating the API wrapper and setting the access token at the point when the user logs in, or at the point when the call is made. For example, a call to get top tracks may look like (using Express for convenience):

app.get('/myendpoint', function (request, response) {

  const loggedInSpotifyApi = new SpotifyWebApi();
  loggedInSpotifyApi.setAccessToken(request.access_token);

  // Get top tracks!
  loggedInSpotifyApi.getMyTopTracks()
    .then(function(data) {
      response.send(data.body);
    }, function(err) {
      console.error(err);
    });   
});

Here's a full working Glitch that shows the Authorization Code flow and spotify-web-api-node: https://glitch.com/edit/#!/spotify-authorization-code

Let me know if you have any questions!

Upvotes: 1

Related Questions