Create a React App with TS, Redux and OAuth 2.0 - Spotify login example

How to create a React app with Typescript, Redux and OAuth 2.0 user authorization. User login example with Spotify.

Oskar Asplin
Sep 3, 2020 · 8 min read

In this tutorial we will create a React app using the official Redux+Typescript template and add OAuth 2.0 user authorization. The OAuth 2.0 authorization in this tutorial is used to connect to Spotify’s Web API, but can be used for any service with the same authorization flow. The web app created in this tutorial is a stand-alone client-side web app with no server-side application needed.

tl;dr
Code result in this template. But I still recommend following the tutorial :)

Npm is required for this tutorial and can be installed here.

Tutorial

Step 1: Create a React app with Typescript and Redux

Run the command below:

npx create-react-app my-app --template redux-typescript

Your app is now installed with a premade example of a counter to show how you can use the Redux store. Change directory to my-app ( cd my-app ) and run the following command to run the app locally:

npm start

You should see the counter example in your browser at http://localhost:3000.

The basics: To understand the basics of the template code let us start by looking at index.tsx in the src folder. The line <Provider store={store}> makes the Redux store available to all nested components, which is currently the <App /> component. The App component is defined in App.tsx and is the main React component. By looking at the contents of App.tsx we see the Counter component being included with <Counter /> along with the rest of the text we can see at localhost:3000. All code for the counter is in the src/features/counter folder. The Counter component is written in Counter.tsx and the code for managing its Redux state is in counterSlice.ts. The Redux store itself is defined in store.ts in the src/app folder.

Don’t worry if you don’t understand everything at the moment. It will be more clear as you follow the next steps.

Optional step: Upload to a git repository

With your favorite Git-repository manager (GitHub/GitLab/Bitbucket/…): Create an empty repository without readme, gitignore or license. Copy the url of the repo. On your computer: change working directory to my-app and push your code:

cd my-app
git remote add origin remote_repository_url
git push -u origin master

Step 2: Acquire relevant OAuth 2.0 information

We need the following for our authorization setup:

  • Authorization URL
  • Client ID
  • Redirect URI
  • Scopes

Quick explanation: Authorization URL is the base URL to the authorization service (e.g.: https://accounts.spotify.com/authorize). Client ID is an identifier for your specific application. Redirect URI is where the authorization service should redirect the user after a successful login through their service (usually the URL of your application). The scopes define what type of user data you want to access with your application.

Authorization URL, client ID and scopes will depend on which service you are using for authorization. For this tutorial we will implement user authorization with Spotify, which is described here (implicit grant flow). The following paragraph is specific to Spotify’s web API.

To use the Spotify API you need to register your app by logging in to the developer dashboard and register a new app. When the app is registered, press edit settings and add http://localhost:3000 to Redirect URIs. Remember to add other URI’s if you deploy your web app or you want to work locally on another port than 3000. You will find your client ID on the page of your registered app. All scopes for the Spotify API are listed here.

Step 3: Configure your OAuth 2.0 setup

Create a file called oauthConfig.ts in the src folder and paste the following code:

authEndpoint (Authorization URL) is set to Spotify’s authorization service and scopes is set to user-read-private which gives read access to the user’s subscription details. authEndpoint and scopes can be changed to your desired scenario. As you can see above, the client ID and redirect URI are stored in something called process.env, which means they are environment variables. This is done to hide them from the code for safety reasons. To set environment variables from another file in the project we need to install a package called dotenv. Run:

npm i dotenv

Create a file called .env.local in your root folder (the my-app folder) and add the environment variables like this:

Paste the client ID acquired from the previous step of the tutorial. Change the redirect URI if you are running the app from another port than 3000 locally. Also, make sure .env.local is listed in the .gitignore file of your project. It should be there by default if you followed step 1 and created the React app with npx create-react-app.

Step 4: Implement the authorization

Finally we have gotten to the implementation. First we will create a new folder called utils to create some necessary utility functions:

mkdir utils

Create a new file in this folder called hashUtils.ts and paste the following code:

getHashParams helps us to extract the access token from the URL when we have logged in with our authorization service. removeHashParamsFromUrl is just there to clean up the URL afterwards so the user won’t be confused by a long and messy URL.

Now to the login button. We want a login button that saves the access token to the Redux state, so we will write the code in a similar way as the premade counter. We begin with creating a folder for our authorization functionality. Create a new folder called authorization in the src/features folder:

cd src/features/
mkdir authorization

Create two new files in the authorization folder called Authorization.tsx and authorizationSlice.ts and paste the two following code blocks in them:

We will go through how all of this works, but first let’s connect these to the rest of the code. To add the authorizationReducer in authorizationSlice.ts to the root reducer, we have to import and add it to store.ts in the src/app folder. Add this import statement to store.ts:

import authorizationReducer from '../features/authorization/authorizationSlice';

Then add authorization: authorizationReducer under the line where it says counter: counterReducer. Last thing we need to do is add the Authorization component to App.tsx. Add this import statement to App.tsx:

import { Authorization } from './features/authorization/Authorization';

Then add <Authorization /> over the line that says <Counter />.

How it works:

In Authorization.tsx we define a React component with a login button. When clicked it redirects the browser window to the authorization service which in this tutorial is Spotify. When the user has logged in and granted access to the scopes we set in oauthConfig.ts, the browser is redirected back to our app with an access token and an expiry time. The token and expiry time are sent as hash parameters in the URL. These hash parameters are retrieved in lines 15–17 in Authorization.tsx and then removed from the URL at line 18. The redux state is updated in the useEffect block in lines 25–33. useEffect is a React Hook which is similar to componentDidMount and componentDidUpdate. The useEffect block will only run once because of the empty square brackets on line 33. You can read more about useEffect here.

The Authorization component keeps track of two values in the Redux state, loggedIn and tokenExpiryDate, using selectors on lines 21–22. loggedIn determines whether the component will return a login button or show the token expiry date (lines 38 and 46).

The authorization state is defined in authorizationSlice.ts. The three values loggedIn, accessToken and tokenExpiryDate are defined in this state. The three actions setLoggedIn, setAccessToken and setTokenExpiryDate are used to change these values in the Redux state. Actions need to be dispatched, which we can see in the useEffect block in Authorization.tsx. To easily retrieve the values we have defined selectors in lines 36–38 which selects the specific value from the Redux state tree.

When the authorization reducer is added to the main reducer in state.ts, the authorization state is effectively a part of the Redux state.

Step 5: Test the token retrieval

At this point we have successfully made a working login button with OAuth 2.0 and saved the access token and expiry date to the Redux state. So let’s test what we have. Run npm start in the terminal and you should see the login button at http://localhost:3000. Should look something like this:

Press the button and login through the authorization service. When you are redirected back to your app you should not be able to see the login button, but instead see the token expiry date like this:

Remember that the expiry date is in UTC time.

A very helpful browser extension when working with Redux is Redux DevTools (for Chrome, Firefox and Edge). With Redux DevTools installed you can check the Redux state in your browser. This way you can easily verify that the access token is stored in the Redux state.

Step 6: Use the token

Now that we have the access token in the Redux state we can use it in a fetch call to retrieve information within our scopes. We will show you how to do this with a plain fetch call without any other dependencies. In our example we will use Spotify’s endpoint https://api.spotify.com/v1/me to retrieve the name and subscription type of the logged in user.

Create a new directory in src/features called spotifyExample and add the following three files:

Now add spotifyExample: spotifyExampleReducer to store.ts and add <SpotifyExample /> under the line that says <Authorization /> in App.tsx in the same way as you did with the authorization component and reducer.

You are all done! Start your application and login to see the result. You should see something like this after you logged in:

The Spotify example component and reducer are structured in the same way as the authorization component and reducer. The Redux state has been expanded with displayName and product. The fetch call is sent and handled in lines 36–54 in the function setUserProfileAsync in spotifyExampleSlice.ts. It is important that the fetch call is in an async action using AppThunk defined in store.ts, since the fetch call is run asynchronously. Read more about async logic in Redux here. As you can see in the code, making the fetch call is as easy as adding an authorization header with your token and adding it to the fetch call like this:

Conclusion

Congratulations! You have successfully made a fully functional React app with Typescript, Redux and Oauth 2.0 login. Feel free to check out the result code at: github.com/OskarAsplin/react-ts-redux-oauth2-template

If you want inspiration for what you could do with this setup, you can check out my music festival finder: Oskarito SpotiFest. The code for the app is open source and available at github.com/OskarAsplin/spotifest.

Further suggestions for your app

Host your website: netlify.com (Remember to add the environment variables)
Use a UI framework: 6-best-reactjs-based-ui-frameworks
Maintain the Redux state after a page refresh: redux-persist
Add more pages to your app: react-router-dom, guide

Complimentary reading

React: https://reactjs.org/
Typescript: https://www.typescriptlang.org/
Redux: https://redux.js.org/
OAuth 2.0: https://oauth.net/articles/authentication/
The authorization flow used in this tutorial: Spotify implicit-grant-flow

The Startup

Get smarter at building your thing. Join The Startup’s +788K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Oskar Asplin

Written by

Software developer in Berlin

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +788K followers.

Oskar Asplin

Written by

Software developer in Berlin

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +788K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store