DEV Community

Cover image for Implementing user authentication in React with SuperTokens
OpenReplay Tech Blog
OpenReplay Tech Blog

Posted on • Originally published at blog.openreplay.com

Implementing user authentication in React with SuperTokens

by Mercy Ben

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:

npm create-react-app auth-with-supertokens
Enter fullscreen mode Exit fullscreen mode

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

auth-with-supertokens
 ┣ node_modules
 ┣ public
 ┣ src
 ┃ ┣ App.css
 ┃ ┣ App.js
 ┃ ┣ App.test.js
 ┃ ┣ index.css
 ┃ ┣ index.js
 ┃ ┣ logo.svg
 ┃ ┣ reportWebVitals.js
 ┃ ┗ setupTests.js
 ┣ .gitignore
 ┣ README.md
 ┣ package-lock.json
 ┗ package.json
Enter fullscreen mode Exit fullscreen mode

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:

npm i -s supertokens-auth-react
Enter fullscreen mode Exit fullscreen mode

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

import React from "react";

import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";

SuperTokens.init({
  appInfo: {
    // learn more about this on https://supertokens.com/docs/emailpassword/appinfo
    appName: "auth-application",
    apiDomain: "http://localhost:3001",
    websiteDomain: "http://localhost:3000",
    apiBasePath: "/api/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [EmailPassword.init(), Session.init()],
});

/* Your App */
class App extends React.Component {
  render() {
    return <div>{/*Your app components*/}</div>;
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

export default function BookStore() {
  const BookList = [
    {
      SID: 1,
      name: "Python for Beginners",
      author: "Mercy Ben",
      coppies: 10,
      publishedAt: "2022-04-03",
    },
    {
      SID: 2,
      name: "Python for Dummies",
      author: "Nelson Fos",
      coppies: 20,
      publishedAt: "2022-01-03",
    },
    {
      SID: 3,
      name: "Blockchain master course",
      author: "Gilt John",
      coppies: 12,
      publishedAt: "2022-03-03",
    },
  ];

  return (
    <div className="book">
      <ul>
        {BookList.map((book) => (
          <li>{book.name}</li>
        ))}
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

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.

export default function Header() {
  return (
    <div className="header">
      <ul>
        <li>Home</li>
        <li className="logout">Logout</li>
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

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:

* {
  padding: 0px;
  margin: 0px;
}

.header {
  background-color: rgb(218, 218, 218);
  padding: 10px;
  color: #212529;
}

.header ul {
  display: flex;
  justify-content: space-between;
  list-style: none;
  align-items: center;
}

.header ul .logout {
  background-color: #dc3545;
  border-color: #dc3545;
  display: inline-block;
  font-weight: 400;
  line-height: 1.5;
  color: white;
  text-align: center;
  text-decoration: none;
  vertical-align: middle;
  cursor: pointer;
  border: 1px solid transparent;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  border-radius: 0.25rem;
}

.book ul li {
  padding: 10px;
  background-color: #212529;
  color: white;
  margin-bottom: 10px;
  margin: 10px;
}
Enter fullscreen mode Exit fullscreen mode

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

// ...

import BookStore from "./component/BookStore";
import Header from "./component/Header";
import "./App.css";

//...

/* Your App */
export default function App() {
  return (
    <div>
      <Header />
      <BookStore />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

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 alternative to FullStory and LogRocket. It gives you full observability by replaying everything your users do on your app and showing how your stack behaves for every issue. OpenReplay is self-hosted for full control over your data.

replayer.png

Happy debugging for modern frontend teams - start monitoring your web app 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.

npm i react-router-dom
Enter fullscreen mode Exit fullscreen mode

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.

// ...

import SuperTokens, {
  getSuperTokensRoutesForReactRouterDom,
} from "supertokens-auth-react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import * as reactRouterDom from "react-router-dom";

// ...

/* Your App */
export default function App() {
  return (
    <div>
      <Header />
      <BrowserRouter>
        <Routes>
          {/*This renders the login UI on the /auth route*/}
          {getSuperTokensRoutesForReactRouterDom(reactRouterDom)}
          {/*Your app routes*/}
          <Route path="/" element={<BookStore />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

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:

<Route
  path="/"
  element={
    <EmailPassword.EmailPasswordAuth
      onSessionExpired={() => {
        alert("Session expired!");
      }}
    >
      <BookStore />
    </EmailPassword.EmailPasswordAuth>
  }
/>
Enter fullscreen mode Exit fullscreen mode

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.

npm init -y && npm i -s supertokens-node express cors
Enter fullscreen mode Exit fullscreen mode

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

const express = require("express");
const supertokens = require("supertokens-node");
const Session = require("supertokens-node/recipe/session");
const EmailPassword = require("supertokens-node/recipe/emailpassword");

const app = express();

supertokens.init({
  framework: "express",
  supertokens: {
    // try.supertokens.com is for demo purposes. Replace this with the 
    // address of your core instance (sign up on supertokens.com), or self host a core.
    connectionURI: "https://try.supertokens.com",
    // apiKey: "IF YOU HAVE AN API KEY FOR THE CORE, ADD IT HERE",
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/session/appinfo
    appName: "auth-application",
    apiDomain: "http://localhost:3001",
    websiteDomain: "http://localhost:3000",
    apiBasePath: "/api/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});

const PORT = 3001;
app.listen(PORT, () => console.log(`Server runing on port ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

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:

npm index.js
Enter fullscreen mode Exit fullscreen mode

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.

// ...

const cors = require("cors");
const { middleware } = require("supertokens-node/framework/express");

// ...

// ...other middlewares
app.use(
  cors({
    origin: "http://localhost:3001",
    allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
    credentials: true,
  })
);

app.use(middleware());

// ...your API routes
Enter fullscreen mode Exit fullscreen mode

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.

Session data

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.

// ...

import EmailPassword, {
  signOut,
} from "supertokens-auth-react/recipe/emailpassword";

// ...

async function onLogout() {
  await signOut();
  window.location.href = "/";
}

//  ...
Enter fullscreen mode Exit fullscreen mode

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

Finally, update the Header component.

export default function Header(props) {
  const { onLogout } = props;
  return (
    <div className="header">
      <ul>
        <li>Home</li>
        <li className="logout" onClick={onLogout}>
          Logout
        </li>
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (1)

Collapse
 
slidenerd profile image
slidenerd

please add a post on how to test supertokens with jest