If you’ve seen phrases like ‘access token’, ‘refresh token’, ‘credentials’, ‘scope’, or ‘redirect uri’ thrown around and aren’t sure how they all fit together, you’ve come to the right article. I’m not going to speak too much about the principles of OAuth; instead we’ll just work through everything we need to do to set ourselves up with robust API authentication. Let’s get into it!
Choosing The Right Authorization Flow
Spotify provides three authorization flows that allow different forms of access to their API. We have to choose one, so let’s figure out which.
From their developer documentation:
- Refreshable user authorization: Authorization Code Flow
- Temporary user authorization: Implicit Grant Flow
- Refreshable app authorization: Client Credentials Flow
We’re building an app, so at first glance it seems like we want to go with the Client Credentials Flow. Unfortunately though, “only endpoints that do not access user information can be accessed.”
The Implicit Grant Flow might seem like a good idea because it doesn’t require as much information and still gets us access to users’ personal Spotify data, but it doesn’t provide a refresh token, so if they’re in the app for more than a few minutes, we’d have to keep redirecting them to the browser to grab a new access token.
That leaves us with the Authorization Code Flow. It’s the most complex, but it’s going to give us access to all the data we want and will allow us to automatically refresh our access token so the user only has to be bothered when they use our app for the first time. So let’s dive in!
Here’s the infamous image that we’ll be working through:
Don’t stress, it’ll be fine.
TLDR: We’re going with the Authorization Code Flow
Registering Our App To Get Our Spotify Credentials
The first thing we’ll need to do is register our app in Spotify’s developer dashboard. You’ll need a Spotify account to access the dashboard (if you are making an account after reading this, let me be the first to welcome you to your new, better life).
Steps to follow:
- Login to the developer dashboard here: https://developer.spotify.com/dashboard/login
- Click the green ‘CREATE A CLIENT ID’ button
- Follow the prompts and fill out the required info (Click ‘No’ if they ask if you’re developing a commercial integration. You can change this later if needed)
- Copy the Client ID and save it somewhere
- Click ‘SHOW CLIENT SECRET’, then copy and save it in that same place
- Click the green ‘EDIT SETTINGS’ button
- Look at the *** message below
- Enter your Redirect URI where it asks and press the ‘ADD’ button! Don’t forget to press the ‘ADD’ button. It’s happened to people I know …
- Copy and save your Redirect URI with your other credentials
- Rejoice! Also, look back at your Dashboard once you start using your app — Spotify shows you cool graphs with all the usage statistics and API endpoints you’ve been pinging
*** If you’re building a React Native app with Expo like me, somewhere in your app, write the following (we’ll talk more about AuthSession later):
The logged string will be the Redirect URI that we want to use. It should be something along the lines of https://auth.expo.io/@your-username/your-app-name.
If you’re not using Expo, just choose a Redirect URI that you’d like the user to be redirected to after they go through the Spotify authorization process.
TLDR: Umm, don’t skip this part or any of the parts below 😅
Safely Accessing Our Spotify Credentials
Now it’s time to store those app credentials that we just created!
In development, I put my credentials in a file called
secrets.js, which I make sure to add to my
.gitignore file so that it doesn’t end up on Github. It looks like this, except with the actual credentials filled in:
When your app is ready to be deployed, you should store the credentials on your server and expose an endpoint that makes API calls for your client and passes the data back to your front-end. If you’re deploying to Heroku, this can be done by setting the credentials as config vars (either with the Heroku CLI or in the Heroku Dashboard) and then accessing them with
process.env. Here’s Heroku’s guide to setting up config vars: https://devcenter.heroku.com/articles/config-vars.
Here’s what the server-side route could be:
And here’s what your front-end API call might look like with axios:
Getting An Authorization Code
Assuming you now have safe access to your Spotify app credentials, it’s time to put them to good use and actually do the authorization! Before we can get our API access token, we need to get an authorization code. Since I’m using Expo to build and test my React Native app, I can make use of Expo’s built-in AuthSession functionality to safely and easily redirect users to Spotify’s authorization URL in order to get the code.
According to the Expo docs, this is what AuthSession does for us:
- It opens the sign in URL for your authentication provider (
authUrl, you must provide it) in a web browser that shares cookies with your system browser
- It handles success redirects and extracts all of the data encoded in the URL
- It handles failures and provides information to you about what went wrong
Sounds dope. And if you’re not using Expo, you’ll just have to manually redirect the user to the same location, so don’t worry — this guide is still for you!
When working through this, I pretty much just copied the code from Expo’s AuthSession example and replaced the Facebook authURL with what I found in the Spotify Authorization Guide. The scopes are the user data that you will be requesting access to. The full list of them is here. Add or remove whatever you’d like. I know I want to be able to view, modify, and create playlists for the user — the other stuff could maybe come in handy too.
Here’s what it should look like:
Don’t think for a second that you’re supposed to know how to actually grab the authorization code from the result. I logged out
result to my console to figure out that it was stored in
Ok great, we just finished Step 1 of the Authorization Code Flow. Only 2 more to go!
Getting An Access Token And Refresh Token
Now that we’ve got our authorization code, we can use it to get what we really want: an API access token. This part was tough to figure out, but I got through it with the help of Bene Studio’s Github repo and this segment of the Spotify Authorization Guide:
Here’s what it should look like:
Things of Note:
- I used the fetch API that’s built into React Native, but you can make the
POSTrequest however you’d like as long as it contains the right info.
btoafunction on line 7 creates a base-64 encoding of the clientId and clientSecret, which is required for the Authorization section of the Header.
- It took a while to figure out that the body parameters had to be sent as a string and separated by the ‘&’ character.
- On line 26, I calculate the actual expiration time in Unix time. I have to multiply the
expiresInproperty by 1000 because Spotify sends it in seconds, and Unix time is in milliseconds.
- On lines 27–29, I am saving the three properties to the device’s
asyncStoragewith a custom
setUserDatafunction I wrote. You can save them wherever you’d like as long as you’re able to access them when you want to make Spotify API calls.
Hey! We have an access token now, which means that we can actually make calls to Spotify’s API. That’s awesome, and we’ll get to that in a second. We just need to touch on the last part of the Authorization Code Flow, which is how to get a new access token when ours expires (which happens every 6 minutes 😿). I was super nonchalant about the third property that came along in that fetch request. The access token gets all the glory, but it would quickly fade to dust without our handy-dandy refresh token. Let’s put it to work.
Using The Refresh Token To Get A New Access Token
The process for refreshing an expired access token is really similar to getting the access token for the first time. Take a look at the code:
Things of Note:
grant_typeproperty in the request body simply changes to
- The function could error out if the refresh token expires (not sure if or when that happens) or if we call it without actually having a refresh token available to us. In that case, the
responseJsonwill have an error property on it, and we know that we should run our
getTokensfunction to generate an authorization code and get tokens from that method instead. This logic might not be the most efficient, but it enables us to just call this function whenever we want to get a valid access token. If it works, great. If not, it will call our other function instead.
That’s all we need to do! In the first place that our app needs to use the Spotify API, we can just add some logic like this:
We check to see if we have a token expiration time. If we don’t, we know we need to get an authorization code and then get tokens. If we do, we check to see if the current time is greater than the token’s expiration time. If so, we need to refresh our tokens. Our
refreshTokens function will take care of both situations for us. If the token expiration time hasn’t occurred yet, we’re all set and don’t need to do anything.
The first time a user logs into our app and goes to a screen that needs Spotify authorization, Expo’s AuthSession will handle the redirection to the web browser for us and then bring them back to the same screen once they have logged into Spotify and given us access to the scopes we’ve requested. Assuming a refresh token is good until you use it, the user shouldn’t ever have to be redirected to the browser to give us access again.
A user should see the following two screens when they use your Expo app for the first time.
The Fun Part: Actually Using The Spotify API
After all that hard work, we can finally do what we set out to do: use the freakin API! We can show user’s their top tracks and artists, we can search for any media object and get all of its metadata, and we can even generate music recommendations and create real Spotify playlists for a user. The full API reference is located here: https://developer.spotify.com/documentation/web-api/reference/
At the time of writing this, Spotify’s new API reference is in beta and is located here: https://developer.spotify.com/documentation/web-api/reference-beta/
Most of the endpoints are unchanged in the beta, but some — notably the Playlists API — are different, so be careful!
With your access token, you can call the API however you’d like. I personally like to use the client-side spotify-web-api-js wrapper created by JMPerez (a former Spotify employee). The wrapper simply gives you an object with methods that access most if not all of the API methods so that you don’t have to write the request yourself. There’s also a spotify-web-api-node wrapper for
node.js if you’d like to do things on the backend, and wrappers for many other languages as well. Huge props to everyone who helped make them all. But be warned: since Spotify is updating their API endpoints, some of the methods probably won’t work anymore until they’re updated. I’ve created some issues on the Github repos for the ones I’ve found — I’m sure it wouldn’t hurt to do the same if you find any! Until they’re fixed, you’ll have to build those requests yourself.
I’m just going to quickly walk you through how I use the wrapper.
I installed and imported the spotify-web-api-js package, and created a helper function that uses the functions we wrote above to make sure that I have a functional access token. Here it is:
I run this function before I make any group of API calls, just to make sure that I have a valid access token. If I’m running a call in a loop, I’ll call it inside the loop just to be safe. It might not be the best method, but it’s worked for me so far (any feedback/disagreement would be welcomed).
sp object that’s returned has all of the aforementioned methods on it. So for example, to get a list of a user’s 50 most recent playlists, I would do this:
You constantly have to be looking at the documentation for the wrapper and Spotify’s API documentation to make sure you’re calling the right methods with the right arguments, using the right options, and destructuring your results in the right way. Spotify actually lets you demo every API endpoint at their reference site, which is invaluable for seeing what the output is going to look like.
That’s essentially all you need to know to get up and running. I hope this was helpful. Please feel free to provide any feedback and ask any questions in the comments below, or reach out to me at firstname.lastname@example.org.
Thanks for reading!!