The Ultimate Guide to How to Use SuperTokens for Authentication: From Setup to Production

Authentication remains one of the most critical and often frustrating components of modern web and mobile applications. Developers constantly battle the trade-off between building a secure, scalable authentication system themselves and relying on monolithic third-party providers that lock you into their ecosystem and often incur skyrocketing costs as your user base grows. Enter SuperTokens, an open‑source authentication solution that gives you complete control over your user data and authentication flow while drastically reducing development time. Unlike traditional providers, SuperTokens is built to be self‑hosted or used as a managed service, offering a suite of “recipes” for email‑password, passwordless, social login, and session management out of the box. This guide will take you through the entire journey of integrating SuperTokens into your application, from initial setup to production deployment, covering best practices, common pitfalls, and real‑world configuration examples. By the end, you will have a fully functional authentication system that is both secure and customizable, with the ability to extend it as your application evolves.

Before diving into the step‑by‑step implementation, it’s important to understand the architecture that makes SuperTokens so powerful. At its core, SuperTokens consists of three main components: the SuperTokens core service (a microservice that handles authentication logic, token generation, and persistent storage), the frontend SDK (available for React, Vanilla JS, and soon other frameworks), and the backend SDK (for Node.js, Python, Go, and others). The core service stores user data and sessions in your own database (PostgreSQL, MySQL, or SQLite), while the backend SDK integrates with your API to verify sessions and manage user roles. The frontend SDK provides pre‑built UI components like login/sign‑up forms, but also allows fully custom UIs. This decoupled architecture means you can scale each component independently and never have to pass user data through a third‑party server. Now, let���s walk through the exact steps to get SuperTokens up and running in your application.

Article illustration

Step 1: Setting Up the SuperTokens Core Service

The first step in your integration journey is to run the SuperTokens core service. This service is the brain of your authentication system – it handles the creation, verification, and revocation of sessions, as well as the storage of user credentials and password hashes. You have two options: you can either self‑host the core using Docker or deploy it on a cloud VM, or you can use the SuperTokens managed service (called SuperTokens Cloud). For most production applications, self‑hosting gives you full control over your data and avoids any third‑party dependency, but the managed service is excellent for prototyping or if you don’t want to manage infrastructure. To self‑host with Docker, you need a Docker environment (Docker Desktop or a Linux server with Docker Engine). The official SuperTokens Docker image is `registry.supertokens.io/supertokens/supertokens-postgresql:latest` (if you are using PostgreSQL). Alternatively, you can use the SQLite‑based image for simpler setups that don’t need a separate database. Create a `docker-compose.yml` file that includes both the SuperTokens core and a PostgreSQL database container. Here is a minimal example:

version: '3.8'
services:
  db:
    image: postgres:14-alpine
    environment:
      POSTGRES_USER: supertokens_user
      POSTGRES_PASSWORD: somePassword
      POSTGRES_DB: supertokens
    ports:
      - "5432:5432"
  supertokens:
    image: registry.supertokens.io/supertokens/supertokens-postgresql:latest
    depends_on:
      - db
    ports:
      - "3567:3567"
    environment:
      POSTGRES_CONNECTION_URI: "postgresql://supertokens_user:somePassword@db:5432/supertokens"
      API_KEY: "your-api-key"
    restart: unless-stopped

Once you run `docker-compose up -d`, the core service will be available on `http://localhost:3567`. You can verify it’s working by hitting `http://localhost:3567/hello`. The core service is now ready to accept connections from your backend SDK. If you prefer the managed service, simply sign up at https://supertokens.com, create a new project, and you’ll receive a connection URI and an API key. For the purpose of this tutorial, we’ll assume you are self‑hosting, but the backend SDK configuration is nearly identical regardless of deployment method. Note that the core service does not store user data itself – it uses your own database. This is a huge privacy and security win because your users’ passwords and personal details never leave your infrastructure. The core service also handles rate limiting, brute‑force protection, and automatically rotates refresh tokens to keep sessions secure.

Step 2: Integrating the Backend SDK (Node.js Example)

With the core service running, your next task is to install and configure the SuperTokens backend SDK for your server. In this tutorial, we’ll use Node.js with Express, but the concepts apply directly to Python (Flask/Django), Go, and other supported languages. Start by installing the SuperTokens Node.js SDK and the appropriate recipe SDK for the authentication method you want. For email‑password login, you’ll need the `supertokens-node` package and the `supertokens-node/recipe/emailpassword`:

npm install supertokens-node express cors

Now, create a file, say `app.js`, and initialise SuperTokens with the configuration pointing to your core service. You’ll need to provide the connection URI (e.g., `http://localhost:3567`), your API key (if you set one), and the appName (any string that identifies your app). Here’s a minimal initialisation snippet for email‑password authentication with session management:

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

supertokens.init({
  framework: "express",
  supertokens: {
    connectionURI: "http://localhost:3567",
    apiKey: "your-api-key",
  },
  appInfo: {
    appName: "MyApp",
    apiDomain: "http://localhost:3001",
    websiteDomain: "http://localhost:3000",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(),
    Session.init(),
  ],
});

The `appInfo` object is crucial because SuperTokens uses these domains to verify the origin of requests and to set secure cookie domains. The `apiBasePath` and `websiteBasePath` define where your backend authentication endpoints will be mounted (e.g., `/auth/signup`, `/auth/signin`). After initialisation, you need to add SuperTokens middleware to your Express app. This middleware handles the POST requests to the authentication endpoints automatically, so you don’t have to write your own signup/login logic. Simply add:

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

const app = express();
app.use(express.json());
app.use(middleware());

// Your other routes here...
app.listen(3001);

Your backend is now ready to accept authentication requests. The `middleware` function will respond to any request whose path starts with `/auth` and handle signup, signin, signout, session refresh, and email verification endpoints automatically. To verify that a session is valid on a protected API route, you can use the `verifySession` middleware provided by the Session recipe. For example:

const { verifySession } = require("supertokens-node/recipe/session/framework/express");

app.get("/dashboard", verifySession(), (req, res) => {
  let userId = req.session.getUserId();
  res.json({ message: "Welcome!", userId });
});

This will automatically check the session tokens in the cookies or headers and return a 401 if the session is invalid or expired. The session refresh is also handled transparently by the frontend SDK, so you don’t need to worry about token rotation on your own.

Step 3: Configuring the Frontend SDK (React Example)

With your backend ready, it’s time to connect your frontend application. SuperTokens provides frontend SDKs for Vanilla JS and React that offer both pre‑built UI components and hooks for custom UIs. We’ll use React for this example. First, install the necessary packages:

npm install supertokens-auth-react react-dom react-router-dom

Then, initialise the frontend SDK in your main `App.js` or a dedicated `Supertokens.js` file. The configuration must match your backend’s `appInfo` – same `apiDomain`, `websiteDomain`, and `apiBasePath`. Here’s an initialisation with the email‑password recipe and the pre‑built UI:

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: {
    appName: "MyApp",
    websiteDomain: "http://localhost:3000",
    apiDomain: "http://localhost:3001",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(),
    Session.init(),
  ],
});

Now, wrap your application with the SuperTokens component and use the pre‑built routes. For example, in your routing setup:

import { SuperTokensWrapper } from "supertokens-auth-react";
import { Routes, Route } from "react-router-dom";

function App() {
  return (
    
      
        } />
        } />
      
    
  );
}

The `` component (imported from the recipe) renders the sign‑up, sign‑in, and reset password forms automatically. You can also customise the UI by passing props like `signInForm` and `signUpForm` with your own components. If you prefer a headless approach, you can use the `useSessionContext` hook to get the session status and manually render forms. The frontend SDK also handles session refresh in the background – it intercepts API responses and automatically refreshes the session before retrying the request, so your users never see a login prompt until they explicitly sign out or their session expires.

Step 4: Implementing Social Login (Google, GitHub, etc.)

SuperTokens supports social login via its ThirdParty recipe. This recipe works in conjunction with the ThirdPartyEmailPassword recipe if you want to offer both email‑password and social login in the same flow. To add Google login, for example, you first need to create OAuth 2.0 credentials in the Google Cloud Console. Enable the “Google+ API” (or the newer OAuth consent screen), create an OAuth 2.0 Client ID for a web application, and add the redirect URI to match `http://localhost:3000/auth/callback/google` (adjust based on your websiteDomain and basePath). Then, install the ThirdPartyEmailPassword recipe on both backend and frontend. On the backend, modify your recipe list:

const ThirdPartyEmailPassword = require("supertokens-node/recipe/thirdpartyemailpassword");

recipeList: [
  ThirdPartyEmailPassword.init({
    providers: [
      {
        config: {
          thirdPartyId: "google",
          clients: [{
            clientId: "YOUR_GOOGLE_CLIENT_ID",
            clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
          }],
        },
      },
    ],
  }),
  Session.init(),
],

On the frontend, update the recipe list to use ThirdPartyEmailPassword instead of EmailPassword:

import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";

recipeList: [
  ThirdPartyEmailPassword.init(),
  Session.init(),
],

The pre‑built UI will automatically add “Sign in with Google” buttons. You can also add GitHub, Facebook, or any custom OAuth provider by following the same pattern. The SuperTokens core handles the OAuth callback and links the social account to a local user record if it’s the first sign‑in. If a user signs up with email first and later wants to link a social account, you can implement account linking manually using the UserMetadata recipe. For most applications, the simple social login setup is sufficient and greatly reduces friction for new users.

Step 5: Managing Sessions and User Roles

Once your users are authenticated, you’ll likely need to manage session lifetimes, role‑based access control (RBAC), and user metadata. SuperTokens provides built‑in session management that handles access tokens (short‑lived, typically a few minutes) and refresh tokens (long‑lived, configurable up to several days). By default, the access token expires in 1 hour and the refresh token in 24 hours, but you can change these values in the `Session.init` configuration:

Session.init({
  sessionExpiredStatusCode: 401,
  cookieSameSite: "lax",
  exposeAccessTokenToFrontendInCookieBasedAuth: false,
  antiCsrf: "VIA_TOKEN",
  sessionTokenBackend: "viaCookie",
  refreshTokenValidity: 60 * 24 * 7, // 7 days in minutes
  accessTokenValidity: 30, // 30 minutes
})

For RBAC, you can leverage JWT payload claims. The session recipe allows you to add custom claims to the access token. For example, you can add a `role` claim during signup or update it via an API endpoint. In your backend SDK, after verifying the session, you can access these claims:

let session = req.session;
let role = session.getAccessTokenPayload().role;

You can also use the UserMetadata recipe to store arbitrary JSON data per user (like preferences, profile information, etc.). Install the UserMetadata recipe on both sides and then use `super.setUserMetadata(userId, metadata)` on the backend. This is great for storing non‑sensitive data without creating your own user table. However, for critical role data, it’s better to keep it as a session claim or in your own database. SuperTokens also supports email verification and password reset out of the box – the email password recipe includes flows for sending verification emails and resetting passwords. You just need to provide your email sending configuration (SMTP settings or use a service like SendGrid) either in the core configuration or via a custom email password reset using the backend SDK’s `sendEmail` callback.

Tips and Best Practices for SuperTokens Authentication

1. Always Use HTTPS in Production

While this might seem obvious, it’s worth emphasising: SuperTokens relies on cookies to store session tokens. In production, you must serve your website and API over HTTPS to prevent session hijacking via network sniffing. Additionally, set the `cookieSecure: true` property in your session configuration. When developing locally, you can leave it as `false` because your localhost is not served over HTTPS. If you use the `cookieSameSite` attribute, set it to `”lax”` or `”strict”` to mitigate CSRF attacks. For added security, SuperTokens includes an anti‑CSRF token mechanism that you can enable by setting `antiCsrf: “VIA_TOKEN”`. This adds a custom header to API requests that must match a value stored in the session. The frontend SDK does this automatically, so you just need to enable it in the configuration.

2. Use the Pre‑built UI for Rapid Prototyping, but Customise for Production

The pre‑built SuperTokens UI is great for getting a working authentication screen in minutes, but it uses generic styling that might clash with your brand. For a production application, you should either override the CSS by providing a custom styles object or build a completely custom UI using the hooks like `useSessionContext` and `useAuthRecipe`. The custom UI approach gives you full control over the form fields, error messages, and layout. SuperTokens provides several hooks – for example, `useAuth` from the recipe returns functions like `signUp`, `signIn`, `signOut`, and `getAuthState`. This allows you to build your own pages while still leveraging SuperTokens’ session management and token handling. Avoid exposing raw credentials in client‑side logs, and never store the session tokens in localStorage (SuperTokens uses httpOnly cookies by default, which is the safest option).

3. Plan for Scaling Your Authentication Infrastructure

SuperTokens is designed to scale horizontally. The core service is stateless with respect to the authentication logic, but it does rely on your database. As your user base grows, ensure your database can handle the load. You can run multiple instances of the SuperTokens core behind a load balancer, as long as they all point to the same database. The core service also caches some data, but for high‑throughput applications, consider using a dedicated PostgreSQL or MySQL instance with connection pooling (e.g., PgBouncer). Additionally, you can tune the core’s memory and CPU limits in your Docker configuration. If you choose the managed service, scaling is handled for you, but you lose some fine‑grained control. For startups, starting with the free tier of the managed service is reasonable, but once you hit thousands of users, self‑hosting becomes more cost‑effective.

4. Implement Rate Limiting and Brute‑Force Protection

SuperTokens core includes built‑in rate limiting for login attempts. By default, after 5 failed sign‑in attempts within 5 minutes, the user’s account is temporarily locked out. You can configure these thresholds in the core’s configuration file. If you are self‑hosting, you can also add custom rate limiting at the reverse proxy level (e.g., Nginx or Cloudflare) to protect against DDoS attacks on your authentication endpoints. Additionally, use strong password policies – the email password recipe allows you to validate password strength via a custom `validatePassword` function. For example, you can enforce a minimum length, require special characters, or check against common password lists. This adds an extra layer of security beyond what SuperTokens provides out of the box.

5. Monitor Your Authentication Flows

Once your application is live, you need visibility into how users are authenticating. SuperTokens exposes metrics via its `/metrics` endpoint (if enabled) that shows counts of sign‑ups, sign‑ins, session refreshes, and errors. You can integrate this with Prometheus or send logs to your monitoring system. Also, implement logging of failed authentication attempts and session revocations. If you suspect a security incident, you can use the SuperTokens API to invalidate all sessions for a specific user or even all users via the `revokeAllSessionsForUser` function. This is critical for responding to credential leaks. Finally, set up alerts for unusual patterns, such as a sudden spike in sign‑ups or many failed logins from a single IP range, which might indicate an automated attack.

Frequently Asked Questions (FAQ)

Q1: Can I use SuperTokens with a non‑Node.js backend?

Absolutely! SuperTokens provides official backend SDKs for Node.js, Python (with Flask and Django), Go, and Java. The framework‑specific middleware might differ slightly, but the core concepts are identical. For example, in Python with Flask, you would install `supertokens-python` and initialise it with `super.init()` and then add the `super.middleware()` to your app. The session verification is done with a decorator. The community is also working on SDKs for Ruby and PHP. All backend SDKs communicate with the same core service, so you can mix languages in a microservice architecture – just ensure the `appInfo` is consistent across all services.

Q2: How do I migrate my existing user database to SuperTokens?

SuperTokens allows you to import users into its core database using the User Metadata recipe and the core API. For password‑based users, you’ll need to import their password hashes. SuperTokens supports bcrypt, argon2, and SHA‑256 (with a salt). You can write a script that reads your existing user table and inserts records via the SuperTokens core’s `/recipe/signup` endpoint (but you must set the password as a pre‑hashed value). However, be aware that the password hash algorithm must match SuperTokens’ configuration. If your existing hashes are incompatible, you may need to force users to reset their passwords on first login. A safer approach is to integrate SuperTokens and your existing auth system side‑by‑side during a transition period, then gradually migrate users. SuperTokens also supports a “passwordless” migration where users login via email magic links and then set a password later – this avoids the hash compatibility problem entirely. For detailed guidance, refer to the official SuperTokens migration documentation.

Q3: Does SuperTokens support multi‑factor authentication (MFA)?

As of the latest version, SuperTokens does not yet have an official MFA recipe, but it is on the roadmap. However, you can implement MFA yourself by using the session claims and a custom recipe. For example, you could add a TOTP (Time‑based One‑Time Password) flow after initial email‑password authentication. You would store the MFA secret in User Metadata and use a library like `otplib` on the backend. The session token could then have a claim `mfaVerified: false` until the user completes the second factor. Many developers have built such integrations and shared their patterns in the SuperTokens forum. Alternatively, you could delegate MFA to an external service like Auth0 or Twilio, but that partially defeats the purpose of using an open‑source solution. For now, if MFA is a strict requirement, evaluate whether SuperTokens fits your timeline or if you need a partner solution.

Q4: What databases does SuperTokens support?

The SuperTokens core supports PostgreSQL, MySQL, and SQLite (for development/testing only). In production, you should use PostgreSQL or MySQL because SQLite does not handle concurrent writes well. The core automatically creates the necessary tables (like `users`, `user_info`, `session_info`, `password_reset_tokens`, etc.) when it starts up. You can also pre‑populate these tables if you have a specific schema migration strategy. The core does not require any external database migration tools; it manages its own schema. If you switch databases later, you would need to export and import the data, but the schema is well‑documented in the SuperTokens GitHub repository.

Q5: How do I customise the email templates for verification and password reset?

SuperTokens sends emails (for email verification and password reset) via the core service. You can customise the email content by providing a `config.yaml` file when running the core Docker container. In this file, you can set the email HTML template, the subject line, and the sender name. For example, you can overwrite the default template with your brand’s HTML and CSS. If you are using an external email sending service (like SendGrid, Mailgun, or SES), you need to configure SMTP credentials in the core configuration. The core does not require you to have an email server; it uses SMTP to send emails on your behalf. If you prefer to handle email sending yourself (e.g., to use a transactional email service with dynamic templates), you can disable the core’s email feature and handle the email sending in your backend code by listening to the `emailverify` and `passwordreset` callbacks in the backend SDK. The callback is triggered when a user requests verification or reset, and you can then use your own email service to send the link.

Q6: Is SuperTokens free for commercial use?

Yes, SuperTokens is completely open source under the Apache 2.0 license, which means you can use it for any commercial application without paying any licensing fees. The managed cloud service (SuperTokens Cloud) has a free tier that is suitable for small projects, and paid tiers for larger workloads. If you self‑host, there are no usage limits – you are only limited by your own infrastructure. This is a huge advantage over many competitors that charge per active user or per monthly authentication request. The only potential cost is if you need commercial support or enterprise features (like single sign‑on or advanced audit logs), which SuperTokens offers as paid add‑ons. But for the vast majority of applications, the free, self‑hosted version is fully capable.

Conclusion

Integrating SuperTokens for authentication may initially seem like an additional setup step compared to simpler third‑party login buttons, but the long‑term benefits are enormous. You retain full ownership of your user data, you are not locked into a vendor‑specific API, and you can customise every aspect of the authentication flow – from the UI to the session lifetime to the password hashing algorithm. In this guide, we have covered the entire lifecycle: setting up the core service, integrating the backend and frontend SDKs, adding social login, managing sessions and roles, and following best practices for security and scalability. By now, you should have a working authentication system that handles sign‑ups, logins, session refresh, and user verification. The next steps would be to add passwordless login (if that fits your use case), implement role‑based access control, and set up monitoring. SuperTokens is continuously evolving – its community is active, and the development team regularly releases new recipes and improvements. Whether you are building a side project or a large‑scale SaaS, SuperTokens provides a solid, maintainable foundation for authentication that grows with your application. Start with the simple email‑password flow, then iterate. Your users will appreciate the seamless experience, and you will appreciate the peace of mind that comes with a secure, self‑hosted auth system.

Comparison of Authentication Approaches
Feature SuperTokens (Self‑Hosted) Firebase Authentication Auth0
Data Ownership Full – data stays in your database Shared with Google Shared with Auth0
Pricing Model Free (Apache 2.0) + infrastructure costs Free tier, then per active user Free tier up to 7,000 users, then expensive
Session Management Highly configurable (access/refresh tokens, cookies, custom JWT claims) Limited to Firebase SDK Customisable but complex
Supported Auth Methods Email‑Password, Passwordless, OAuth, Social Email‑Password, OAuth, Phone Many, including MFA
Open Source Yes No No
Common SuperTokens Configuration Parameters
Parameter Location Description Default Value
connectionURI Backend SDK supertokens config URI of the SuperTokens core service http://localhost:3567
apiKey Backend SDK supertokens config API key defined in core config for security Empty (not required by default)
accessTokenValidity Session.init() How long an access token is valid (in minutes) 60
refreshTokenValidity Session.init() How long a refresh token is valid (in minutes) 1440 (24 hours)
cookieSameSite Session.init() SameSite attribute for session cookies lax
antiCsrf Session.init() CSRF protection mechanism (NONE or VIA_TOKEN) NONE
sarah antaboga
Author: sarah antaboga

Leave a Reply

Your email address will not be published. Required fields are marked *