Implementing user authentication in React with SuperTokens
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
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
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
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>;
}
}
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 emailsapiDomain
: 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>
);
}
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>
);
}
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;
}
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>
);
}
If you navigate to localhost:3000 0n your browser, you will see the output shown on the screenshot below:
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.
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.
npm 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
.
// ...
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>
);
}
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:
You can also navigate the signup route by clicking the sign up
link.
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>
}
/>
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
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}`));
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
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
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.
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 = "/";
}
// ...
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>
);
}
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.