OpenReplay
Navigate back to the homepage
BLOG
Browse Repo
Back

Implementing user authentication in React with SuperTokens

Mercy Ben
May 11th, 2022 · 4 min read

Have you ever considered implementing easy and safe authentication on your web application at no cost? Have you considered integrating authentication with minimal or no initial environment setup? Then hang on for the next 10 minutes. In this tutorial, you’ll learn to Implement user authentication in React with Supertoken. This tutorial is a hands-on demonstration to get you started. Ensure you’ve met the following requirements:

  • You have Node (>= 10.13.0, except for v13) installed
  • You have a foundational knowledge of Javascript

To follow along, clone the code repository for this tutorial.

What is Supertokens, and why use it?

Supertokens is a developer-first developer’s first, open-source, flexible alternative to Firebase, AWS Cognito, and Auth0. Supertokens allows you to add secure authentication to your web application in minutes with a prebuilt UI that you can easily customize. It has many unique features that make it the best authentication service for your web application.

  • Prebuilt UI: Supertokens has prebuilt Sign up / sign-in forms (via our front-end SDK) that can be embedded on your website natively.
  • Feature segmentation: with Supertokens, you can pick only the features you need and see docs relevant to your use case (we call it ‘recipes’)
  • Simple data model: Supertokens has a modular structure that allows you to add database tables with fewer configurations.
  • Priced for startups: Supertokend has a generous limit and pricing for our managed service, and it’s free forever for self-hosted.
  • Integrate with any service: You can set up your content delivery service (e.g., SMS or email) for free.

Scaffold React Project

To get started, we’ll create a React application with the command below:

1npm create-react-app auth-with-supertokens

The command will scaffold a new project for us with the following folder structure below:

1auth-with-supertokens
2 ┣ node_modules
3 ┣ public
4 ┣ src
5 ┃ ┣ App.css
6 ┃ ┣ App.js
7 ┃ ┣ App.test.js
8 ┃ ┣ index.css
9 ┃ ┣ index.js
10 ┃ ┣ logo.svg
11 ┃ ┣ reportWebVitals.js
12 ┃ ┗ setupTests.js
13 ┣ .gitignore
14 ┣ README.md
15 ┣ package-lock.json
16 ┗ package.json

Configure the front-end SDK

With our React project created, let’s set up the SuperTokens front-end SDK. First, we need to install the SuperTokens React SDK:

1npm i -s supertokens-auth-react

Next, call the init function in your App.js file:

1import React from "react";
2
3import SuperTokens from "supertokens-auth-react";
4import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
5import Session from "supertokens-auth-react/recipe/session";
6
7SuperTokens.init({
8 appInfo: {
9 // learn more about this on https://supertokens.com/docs/emailpassword/appinfo
10 appName: "auth-application",
11 apiDomain: "http://localhost:3001",
12 websiteDomain: "http://localhost:3000",
13 apiBasePath: "/api/auth",
14 websiteBasePath: "/auth",
15 },
16 recipeList: [EmailPassword.init(), Session.init()],
17});
18
19/* Your App */
20class App extends React.Component {
21 render() {
22 return <div>{/*Your app components*/}</div>;
23 }
24}

In the code above, we initialized the SuperTokens SDK using the init method, which takes the following objects as required parameters in the appInfo object:

  • appName: This is the name of your application. It is used when sending password reset or email verification emails
  • apiDomain: This is the domain part of your website, where the login UI will be shown.
  • websiteDomain: This is the domain part of your API endpoint that the front end talks to.
  • apiBasePath: The default path where the front end SDK will query.
  • websiteBasePath: This is the default path where the website UI will be displayed.

Note: Ensure that apiDomain and websiteDomain match the host for your back end and front end.

SuperTokens has a lot of recipe, but for this tutorial, we’ll use the EmailPassword as specified in the recipeList array.

Create App Components

With the Supertokens SDK setup, let’s create our component. First, create a component folder inside the src directory and a BookStore component within. Now add the code below to the BookStore component.

1export default function BookStore() {
2 const BookList = [
3 {
4 SID: 1,
5 name: "Python for Beginners",
6 author: "Mercy Ben",
7 coppies: 10,
8 publishedAt: "2022-04-03",
9 },
10 {
11 SID: 2,
12 name: "Python for Dummies",
13 author: "Nelson Fos",
14 coppies: 20,
15 publishedAt: "2022-01-03",
16 },
17 {
18 SID: 3,
19 name: "Blockchain master course",
20 author: "Gilt John",
21 coppies: 12,
22 publishedAt: "2022-03-03",
23 },
24 ];
25
26 return (
27 <div className="book">
28 <ul>
29 {BookList.map((book) => (
30 <li>{book.name}</li>
31 ))}
32 </ul>
33 </div>
34 );
35}

In the code above, we created a BookList array with some dummy data, then used the map function to loop through them and render them to the browser. (In real apps, we’d get the list from the server, but that doesn’t matter here; we want to deal with authentication only.) Next, create a Header component and add the code below.

1export default function Header() {
2 return (
3 <div className="header">
4 <ul>
5 <li>Home</li>
6 <li className="logout">Logout</li>
7 </ul>
8 </div>
9 );
10}

Here we created a central header where we can navigate between the BookStore, Login UI, and the Logout component. Delete the styles in the App.css file and add the following styles below:

1* {
2 padding: 0px;
3 margin: 0px;
4}
5
6.header {
7 background-color: rgb(218, 218, 218);
8 padding: 10px;
9 color: #212529;
10}
11
12.header ul {
13 display: flex;
14 justify-content: space-between;
15 list-style: none;
16 align-items: center;
17}
18
19.header ul .logout {
20 background-color: #dc3545;
21 border-color: #dc3545;
22 display: inline-block;
23 font-weight: 400;
24 line-height: 1.5;
25 color: white;
26 text-align: center;
27 text-decoration: none;
28 vertical-align: middle;
29 cursor: pointer;
30 border: 1px solid transparent;
31 padding: 0.375rem 0.75rem;
32 font-size: 1rem;
33 border-radius: 0.25rem;
34}
35
36.book ul li {
37 padding: 10px;
38 background-color: #212529;
39 color: white;
40 margin-bottom: 10px;
41 margin: 10px;
42}

Finally, import BookStore, Header, and the App.css file in the App component.

1// ...
2
3import BookStore from "./component/BookStore";
4import Header from "./component/Header";
5import "./App.css";
6
7//...
8
9/* Your App */
10export default function App() {
11 return (
12 <div>
13 <Header />
14 <BookStore />
15 </div>
16 );
17}

If you navigate to localhost:3000 0n your browser, you will see the output shown on the screenshot below:

Book store page

Open Source Session Replay

OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.

replayer.png

Start enjoying your debugging experience - start using OpenReplay for free.

Setup the login UI

Now let’s set up the SuperTokens login UI. But before that, you need to install react-router-dom to enable you to create the routes for the application. So, run the command below on your terminal.

1npm i react-router-dom

Note: Ensure the version you are installing is at least version 16.* Next, Call the getSuperTokensRoutesForReactRouterDom method from within any react-router-dom Routes component in App.js.

1// ...
2
3import SuperTokens, {
4 getSuperTokensRoutesForReactRouterDom,
5} from "supertokens-auth-react";
6import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
7import * as reactRouterDom from "react-router-dom";
8
9// ...
10
11/* Your App */
12export default function App() {
13 return (
14 <div>
15 <Header />
16 <BrowserRouter>
17 <Routes>
18 {/*This renders the login UI on the /auth route*/}
19 {getSuperTokensRoutesForReactRouterDom(reactRouterDom)}
20 {/*Your app routes*/}
21 <Route path="/" element={<BookStore />} />
22 </Routes>
23 </BrowserRouter>
24 </div>
25 );
26}

We have set up the routes for the application. The Header component will be accessible from the login and BookStore components. So if you go back to your browser and navigate to /auth, you will see the login UI recipe setup for you by SuperTokens as shown below:

login UI

You can also navigate the signup route by clicking the sign up link.

signup UI

Protect Routes

Now we have set up the login UI for our application. But the users can view the bookstore without being authenticated. To prevent that, let’s protect the BookStore route. First, update the BookStore route:

1<Route
2 path="/"
3 element={
4 <EmailPassword.EmailPasswordAuth
5 onSessionExpired={() => {
6 alert("Session expired!");
7 }}
8 >
9 <BookStore />
10 </EmailPassword.EmailPasswordAuth>
11 }
12/>

If a user tries to access the / route, they will be automatically redirected to the /auth route by SuperTokens.

Setup the backend SDK

For the SuperTokens front-end SDK to work, it needs to talk to the back-end SDK. You can choose to use any framework for your back end. But for the demonstration in this tutorial, we’ll use Node.js Express SDK. So let’s set that up pretty quick.

Create a new folder outside the auth-with-supertokens directory called backend-sdk. Then, initialize a Node.js project and install the SuperTokens Node.js SDK, Express, and Cors by running the command below on your terminal.

1npm init -y && npm i -s supertokens-node express cors

Create an index.js file and add the code below:

1const express = require("express");
2const supertokens = require("supertokens-node");
3const Session = require("supertokens-node/recipe/session");
4const EmailPassword = require("supertokens-node/recipe/emailpassword");
5
6const app = express();
7
8supertokens.init({
9 framework: "express",
10 supertokens: {
11 // try.supertokens.com is for demo purposes. Replace this with the
12 // address of your core instance (sign up on supertokens.com), or self host a core.
13 connectionURI: "https://try.supertokens.com",
14 // apiKey: "IF YOU HAVE AN API KEY FOR THE CORE, ADD IT HERE",
15 },
16 appInfo: {
17 // learn more about this on https://supertokens.com/docs/session/appinfo
18 appName: "auth-application",
19 apiDomain: "http://localhost:3001",
20 websiteDomain: "http://localhost:3000",
21 apiBasePath: "/api/auth",
22 websiteBasePath: "/auth",
23 },
24 recipeList: [
25 EmailPassword.init(), // initializes signin / sign up features
26 Session.init(), // initializes session features
27 ],
28});
29
30const PORT = 3001;
31app.listen(PORT, () => console.log(`Server runing on port ${PORT}`));

In the above code, we initialized SuperTokens. Then, we provided the details of our application as we did in the front end in the appInfo object and created an express server.

Note: SuperTokens have a hosted database to store records for your demo project. You can also set up and connect to your own Core self-hosted database.

Now run the Express server with the command below:

1npm index.js

If you inspect the application, you should see some CORS warnings. Let’s fix those.

Enable CORS

To allow our front end to communicate with the back end, we need to enable CORS.

1// ...
2
3const cors = require("cors");
4const { middleware } = require("supertokens-node/framework/express");
5
6// ...
7
8// ...other middlewares
9app.use(
10 cors({
11 origin: "http://localhost:3001",
12 allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
13 credentials: true,
14 })
15);
16
17app.use(middleware());
18
19// ...your API routes

The CORS errors should disappear now. So go ahead and sign up to test things out.

Once you signup or sign in, SuperTokens will create and store your session data on your browser, which can expire and become invalid.

null

Also, as far as your session remains valid, you can’t navigate to the /auth route unless you clear your session by logging out.

Logout Users

Now let’s implement the logout route. First, create a logout method in the App component and pass it as props to the Header component.

1// ...
2
3import EmailPassword, {
4 signOut,
5} from "supertokens-auth-react/recipe/emailpassword";
6
7// ...
8
9async function onLogout() {
10 await signOut();
11 window.location.href = "/";
12}
13
14// ...

In the above code, we imported and used the signOut function provided by SuperTokens to log out a user.

Finally, update the Header component.

1export default function Header(props) {
2 const { onLogout } = props;
3 return (
4 <div className="header">
5 <ul>
6 <li>Home</li>
7 <li className="logout" onClick={onLogout}>
8 Logout
9 </li>
10 </ul>
11 </div>
12 );
13}

Here we destructure our props object to get the onLogout function and bind it to an onClick event on the logout button.

Conclusion

Congrats! You made it at this point. You’ve learned how to easy and fast it is to implement user authentication in React with SuperTokens. We started with an introduction to SuperTokens and why a developer should use it. Then we moved to create a BookStore application for demonstration. Now which auth service will you prefer to use in your next project? Feel free to learn more about SuperTokens from the official documentation.

newsletter

More articles from OpenReplay Blog

Comparing Astro and Next for React apps

Help decide how to choose between two React-based frameworks

May 10th, 2022 · 5 min read

How to Implement Redux Reducers for React

Simple explanations for Reducers, Actions, and State

May 9th, 2022 · 3 min read
© 2022 OpenReplay Blog
Link to $https://twitter.com/OpenReplayHQLink to $https://github.com/openreplay/openreplayLink to $https://www.linkedin.com/company/18257552