Skip to content
Esc
navigateopen⌘Jpreview
Dashboard
On this page

Quickstart Guide

Add SuperTokens authentication to your frontend and backend, then prepare the integration for production.

Overview

Ask an agent to integrate SuperTokens into an existing application.

This guide walks through adding Email/Password authentication with either the SuperTokens prebuilt UI or your own custom UI. Configure the frontend first, then connect your backend and prepare the integration for production.

Steps

1. Integrate the frontend SDK

Start the setup by configuring your frontend application to use SuperTokens for authentication.

This guide uses the SuperTokens pre-built UI components. If you want to create your own interface please check the Custom UI tutorial.

UI type

1.1 Install the SDK

Run the following command in your terminal to install the package.

  npm i -s supertokens-auth-react
yarn add supertokens-auth-react supertokens-web-js
pnpm add supertokens-auth-react supertokens-web-js
bun add supertokens-auth-react supertokens-web-js
npm i -s supertokens-web-js
yarn add supertokens-web-js
pnpm add supertokens-web-js
bun add supertokens-web-js
npm i -s supertokens-web-js
yarn add supertokens-web-js
pnpm add supertokens-web-js
bun add supertokens-web-js

1.2 Initialize the SDK

In your main application file call the SuperTokens.init function to initialize the SDK. The init call includes the main configuration details, as well as the recipes that you use in your setup. After that you have to wrap the application with the SuperTokensWrapper component. This provides authentication context for the rest of the UI tree.

Before we initialize the supertokens-web-js SDK let’s see how we use it in our Angular app.

Architecture

  • The supertokens-web-js SDK is responsible for session management and providing helper functions to check if a session exists, or validate the access token claims on the frontend (for example, to check for user roles before showing some UI). We initialise this SDK on the root of your Angular app, so that all pages in your app can use it.
  • You have to create a /auth* route in the Angular app which renders our pre-built UI. which also needs to be initialised, but only on that route.
Creating the /auth route
  • Use the Angular CLI to generate a new route

Before we initialize the supertokens-web-js SDK let’s see how we use it in our Vue app

Architecture

  • The supertokens-web-js SDK is responsible for session management and providing helper functions to check if a session exists, or validate the access token claims on the frontend (for example, to check for user roles before showing some UI). We initialise this SDK on the root of your Vue app, so that all pages in your app can use it.
  • We create a /auth* route in the Vue app which renders our pre-built UI which also needs to be initialised, but only on that route.

Creating the /auth route

  • Create a new file AuthView.vue, this Vue component is used to render the auth component:
import React from "react";

import SuperTokens, { SuperTokensWrapper } 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/references/frontend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [EmailPassword.init(), Session.init()],
});

/* Your App */
class App extends React.Component {
  render() {
    return <SuperTokensWrapper>{/*Your app components*/}</SuperTokensWrapper>;
  }
}
      ng generate module auth --route auth --module app.module
  <script lang="ts">
      import { defineComponent, onMounted, onUnmounted } from 'vue';
      export default defineComponent({
          setup() {
              const loadScript = (src: string) => {
                  const script = document.createElement('script');
                  script.type = 'text/javascript';
                  script.src = src;
                  script.id = 'supertokens-script';
                  script.onload = () => {
                      supertokensUIInit("supertokensui", {
                          appInfo: {
                              appName: "<YOUR_APP_NAME>",
                              apiDomain: "<YOUR_API_DOMAIN>",
                              websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
                              apiBasePath: "/auth",
                              websiteBasePath: "/auth"
                          },
                          recipeList: [
                              supertokensUIEmailPassword.init(),
                              supertokensUISession.init(),
                          ],
                      });
                  };
                  document.body.appendChild(script);
              };

              onMounted(() => {
                  loadScript('https://cdn.jsdelivr.net/gh/supertokens/prebuiltui@v0.48.0/build/static/js/main.81589a39.js');
              });

              onUnmounted(() => {
                  const script = document.getElementById('supertokens-script');
                  if (script) {
                      script.remove();
                  }
              });
          },
      });
  </script>

  <template>
      <div id="supertokensui" />
  </template>
  • Add the following code to your auth angular component
  • In the loadScript function, we provide the SuperTokens config for the UI. We add the emailpassword and session recipes.

  • Initialize the supertokens-web-js SDK in your Vue app’s main.ts file. This provides session management across your entire application.

  • In the loadScript function, we provide the SuperTokens config for the UI. We add the emailpassword and session recipes.

  • Initialize the supertokens-web-js SDK in your angular app’s root component. This provides session management across your entire application.

1.3 Configure routing

In order for the pre-built UI to be rendered inside your application, you have to specify which routes show the authentication components. The React SDK uses React Router under the hood to achieve this. Based on whether you already use this package or not in your project, there are two different ways of configuring the routes.

Call the getSuperTokensRoutesForReactRouterDom method from within any react-router-dom Routes component.

Add the route handling shown below to your root-level render function.

Update your angular router so that all auth related requests load the auth component

Update your Vue router so that all auth related requests load the AuthView component

import React from "react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import * as reactRouterDom from "react-router-dom";

class App extends React.Component {
  render() {
    return (
      <SuperTokensWrapper>
        <BrowserRouter>
          <Routes>
            {/*This renders the login UI on the /auth route*/}
            {getSuperTokensRoutesForReactRouterDom(reactRouterDom, [EmailPasswordPreBuiltUI])}
            {/*Your app routes*/}
          </Routes>
        </BrowserRouter>
      </SuperTokensWrapper>
    );
  }
}
import React from "react";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import SuperTokens, { SuperTokensWrapper } from "supertokens-auth-react";
import { canHandleRoute, getRoutingComponent } from "supertokens-auth-react/ui";

class App extends React.Component {
  render() {
    if (canHandleRoute([EmailPasswordPreBuiltUI])) {
      // This renders the login UI on the /auth route
      return getRoutingComponent([EmailPasswordPreBuiltUI]);
    }

    return <SuperTokensWrapper>{/*Your app*/}</SuperTokensWrapper>;
  }
}
    import { NgModule } from "@angular/core";
    import { RouterModule, Routes } from "@angular/router";

    const routes: Routes = [
      {
        path: "auth",
        loadChildren: () => import("./auth/auth.module").then((m) => m.AuthModule),
      },

      {
        path: "**",
        loadChildren: () => import("./home/home.module").then((m) => m.HomeModule),
      },
    ];

    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule],
    })
    export class AppRoutingModule {}
    import { createRouter, createWebHistory } from "vue-router";
    import HomeView from "../views/HomeView.vue";
    import AuthView from "../views/AuthView.vue";

    const router = createRouter({
      history: createWebHistory(import.meta.env.BASE_URL),
      routes: [
        {
          path: "/",
          name: "home",
          component: HomeView,
        },
        {
          path: "/auth/:pathMatch(.*)*",
          name: "auth",
          component: AuthView,
        },
      ],
    });

    export default router;

1.4 Handle session tokens

This part is handled automatically by the Frontend SDK. You don’t need to do anything. The step serves more as a way for us to tell you how is this handled under the hood.

After you call the init function, the SDK adds interceptors to both fetch and XHR, XMLHTTPRequest. The latter is used by the axios library. The interceptors save the session tokens that are generated from the authentication flow. Those tokens are then added to requests initialized by your frontend app which target the backend API. By default, the tokens are stored through session cookies but you can also switch to header based authentication.

1.5 Secure application routes

In order to prevent unauthorized access to certain parts of your frontend application you can use our utilities. Follow the code samples below to understand how to do this.

You can wrap your components with the <SessionAuth> react component. This ensures that your component renders only if the user is logged in. If they are not logged in, the user is redirected to the login page.

You can use the doesSessionExist function to check if a session exists in all your routes.

You can use the doesSessionExist function to check if a session exists in all your routes.

import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
import MyDashboardComponent from "./dashboard";

class App extends React.Component {
  render() {
    return (
      <BrowserRouter>
        <Routes>
          <Route
            path="/dashboard"
            element={
              <SessionAuth>
                {/*Components that require to be protected by authentication*/}
                <MyDashboardComponent />
              </SessionAuth>
            }
          />
        </Routes>
      </BrowserRouter>
    );
  }
}
import Session from "supertokens-web-js/recipe/session";

async function doesSessionExist() {
  if (await Session.doesSessionExist()) {
    // user is logged in
  } else {
    // user has not logged in yet
  }
}
import Session from "supertokens-web-js/recipe/session";

async function doesSessionExist() {
  if (await Session.doesSessionExist()) {
    // user is logged in
  } else {
    // user has not logged in yet
  }
}

2. Integrate the backend SDK

Let’s go through the changes required so that your backend can expose the SuperTokens authentication features.

2.1 Install the backend SDK

Run the following command in your terminal to install the package.

npm i -s supertokens-node
yarn add supertokens-node
pnpm add supertokens-node
bun add supertokens-node
go get github.com/supertokens/supertokens-golang
pip install supertokens-python

2.2 Initialize the backend SDK

You will have to initialize the Backend SDK alongside the code that starts your server. The init call will include configuration details for your app, how the backend will connect to the SuperTokens Core, as well as the Recipes that will be used in your setup.

import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import EmailPassword from "supertokens-node/recipe/emailpassword";

supertokens.init({
  framework: "express",
  supertokens: {
    // We use try.supertokens for demo purposes.
    // At the end of the tutorial we will show you how to create
    // your own SuperTokens core instance and then update your config.
    connectionURI: "https://try.supertokens.io",
    // apiKey: <YOUR_API_KEY>
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/references/backend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import EmailPassword from "supertokens-node/recipe/emailpassword";

supertokens.init({
  framework: "hapi",
  supertokens: {
    // We use try.supertokens for demo purposes.
    // At the end of the tutorial we will show you how to create
    // your own SuperTokens core instance and then update your config.
    connectionURI: "https://try.supertokens.io",
    // apiKey: <YOUR_API_KEY>
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/references/backend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import EmailPassword from "supertokens-node/recipe/emailpassword";

supertokens.init({
  framework: "fastify",
  supertokens: {
    // We use try.supertokens for demo purposes.
    // At the end of the tutorial we will show you how to create
    // your own SuperTokens core instance and then update your config.
    connectionURI: "https://try.supertokens.io",
    // apiKey: <YOUR_API_KEY>
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/references/backend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import EmailPassword from "supertokens-node/recipe/emailpassword";

supertokens.init({
  framework: "koa",
  supertokens: {
    // We use try.supertokens for demo purposes.
    // At the end of the tutorial we will show you how to create
    // your own SuperTokens core instance and then update your config.
    connectionURI: "https://try.supertokens.io",
    // apiKey: <YOUR_API_KEY>
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/references/backend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});
import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import EmailPassword from "supertokens-node/recipe/emailpassword";

supertokens.init({
  framework: "loopback",
  supertokens: {
    // We use try.supertokens for demo purposes.
    // At the end of the tutorial we will show you how to create
    // your own SuperTokens core instance and then update your config.
    connectionURI: "https://try.supertokens.io",
    // apiKey: <YOUR_API_KEY>
  },
  appInfo: {
    // learn more about this on https://supertokens.com/docs/references/backend-sdks/reference#sdk-configuration
    appName: "<YOUR_APP_NAME>",
    apiDomain: "<YOUR_API_DOMAIN>",
    websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
    apiBasePath: "/auth",
    websiteBasePath: "/auth",
  },
  recipeList: [
    EmailPassword.init(), // initializes signin / sign up features
    Session.init(), // initializes session features
  ],
});
  import (
    "github.com/supertokens/supertokens-golang/recipe/emailpassword"
    "github.com/supertokens/supertokens-golang/recipe/session"
    "github.com/supertokens/supertokens-golang/supertokens"
  )

  func main() {
      apiBasePath := "/auth"
      websiteBasePath := "/auth"
      err := supertokens.Init(supertokens.TypeInput{
          Supertokens: &supertokens.ConnectionInfo{
          // We use try.supertokens for demo purposes.
          // At the end of the tutorial we will show you how to create
          // your own SuperTokens core instance and then update your config.
          ConnectionURI: "https://try.supertokens.io",
          // APIKey: <YOUR_API_KEY>
          },
          AppInfo: supertokens.AppInfo{
            AppName: "<YOUR_APP_NAME>",
            APIDomain: "<YOUR_API_DOMAIN>",
            WebsiteDomain: "<YOUR_WEBSITE_DOMAIN>",
                  APIBasePath: &apiBasePath,
                  WebsiteBasePath: &websiteBasePath,
          },
          RecipeList: []supertokens.Recipe{
            emailpassword.Init(nil),
            session.Init(nil),
          },
      })

      if err != nil {
        panic(err.Error())
      }
  }
from supertokens_python import init, InputAppInfo, SupertokensConfig
from supertokens_python.recipe import emailpassword, session

init(
    app_info=InputAppInfo(
        app_name="<YOUR_APP_NAME>",
        api_domain="<YOUR_API_DOMAIN>",
        website_domain="<YOUR_WEBSITE_DOMAIN>",
        api_base_path="/auth",
        website_base_path="/auth"
    ),
    supertokens_config=SupertokensConfig(
        # We use try.supertokens for demo purposes.
        # At the end of the tutorial we will show you how to create
        # your own SuperTokens core instance and then update your config.
        connection_uri="https://try.supertokens.io",
        # api_key: <YOUR_API_KEY>
    ),
    framework='fastapi',
    recipe_list=[
	    session.init(), # initializes session features
        emailpassword.init()
    ],
    mode='asgi' # use wsgi if you are running using gunicorn
)
from supertokens_python import init, InputAppInfo, SupertokensConfig
from supertokens_python.recipe import emailpassword, session

init(
    app_info=InputAppInfo(
        app_name="<YOUR_APP_NAME>",
        api_domain="<YOUR_API_DOMAIN>",
        website_domain="<YOUR_WEBSITE_DOMAIN>",
        api_base_path="/auth",
        website_base_path="/auth"
    ),
    supertokens_config=SupertokensConfig(
        # We use try.supertokens for demo purposes.
        # At the end of the tutorial we will show you how to create
        # your own SuperTokens core instance and then update your config.
        connection_uri="https://try.supertokens.io",
        # api_key: <YOUR_API_KEY>
    ),
    framework='flask',
    recipe_list=[
	    session.init(), # initializes session features
        emailpassword.init()
    ]
)
from supertokens_python import init, InputAppInfo, SupertokensConfig
from supertokens_python.recipe import emailpassword, session

init(
    app_info=InputAppInfo(
        app_name="<YOUR_APP_NAME>",
        api_domain="<YOUR_API_DOMAIN>",
        website_domain="<YOUR_WEBSITE_DOMAIN>",
        api_base_path="/auth",
        website_base_path="/auth"
    ),
    supertokens_config=SupertokensConfig(
        # We use try.supertokens for demo purposes.
        # At the end of the tutorial we will show you how to create
        # your own SuperTokens core instance and then update your config.
        connection_uri="https://try.supertokens.io",
        # api_key: <YOUR_API_KEY>
    ),
    framework='django',
    recipe_list=[
	    session.init(), # initializes session features
        emailpassword.init()
    ],
    mode='asgi' # use wsgi if you are running django server in sync mode
)

2.3 Add the SuperTokens APIs and configure CORS

Now that the SDK is initialized you need to expose the endpoints that will be used by the frontend SDKs. Besides this, your server’s CORS, Cross-Origin Resource Sharing, settings should be updated to allow the use of the authentication headers required by SuperTokens.

Register the plugin.

Register the plugin. Also register @fastify/formbody plugin.

Use the supertokens.Middleware and the supertokens.GetAllCORSHeaders() functions as shown below.

Use the Middleware (BEFORE all your routes) and the get_all_cors_headers() functions as shown below.

  • Use the Middleware (BEFORE all your routes and after calling init function) and the get_all_cors_headers() functions as shown below.
  • Add a route to catch all paths and return a 404. This is needed because if we don’t add this, then OPTIONS request for the APIs exposed by the Middleware will return a 404.
Configure Django CORS

Use the Middleware and the get_all_cors_headers() functions as shown below in your settings.py.

import express from "express";
import cors from "cors";
import supertokens from "supertokens-node";
import { middleware } from "supertokens-node/framework/express";

let app = express();

app.use(
  cors({
    origin: "<YOUR_WEBSITE_DOMAIN>",
    allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
    credentials: true,
  }),
);

// IMPORTANT: CORS should be before the below line.
app.use(middleware());

// ...your API routes
import Hapi from "@hapi/hapi";
import supertokens from "supertokens-node";
import { plugin } from "supertokens-node/framework/hapi";

let server = Hapi.server({
  port: 8000,
  routes: {
    cors: {
      origin: ["<YOUR_WEBSITE_DOMAIN>"],
      additionalHeaders: [...supertokens.getAllCORSHeaders()],
      credentials: true,
    },
  },
});

(async () => {
  await server.register(plugin);

  await server.start();
})();

// ...your API routes
import cors from "@fastify/cors";
import supertokens from "supertokens-node";
import { plugin } from "supertokens-node/framework/fastify";
import formDataPlugin from "@fastify/formbody";

import fastifyImport from "fastify";

let fastify = fastifyImport();

// ...other middlewares
fastify.register(cors, {
  origin: "<YOUR_WEBSITE_DOMAIN>",
  allowedHeaders: ["Content-Type", ...supertokens.getAllCORSHeaders()],
  credentials: true,
});

(async () => {
  await fastify.register(formDataPlugin);
  await fastify.register(plugin);

  await fastify.listen({ port: 8000 });
})();

// ...your API routes
import Koa from "koa";
import cors from "@koa/cors";
import supertokens from "supertokens-node";
import { middleware } from "supertokens-node/framework/koa";

let app = new Koa();

app.use(
  cors({
    origin: "<YOUR_WEBSITE_DOMAIN>",
    allowHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
    credentials: true,
  }),
);

app.use(middleware());

// ...your API routes
import { RestApplication } from "@loopback/rest";
import supertokens from "supertokens-node";
import { middleware } from "supertokens-node/framework/loopback";

let app = new RestApplication({
  rest: {
    cors: {
      origin: "<YOUR_WEBSITE_DOMAIN>",
      allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
      credentials: true,
    },
  },
});

app.middleware(middleware);

// ...your API routes
import (
	"net/http"
	"strings"

	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
    // SuperTokens init...

	http.ListenAndServe("SERVER ADDRESS", corsMiddleware(
		supertokens.Middleware(http.HandlerFunc(func(rw http.ResponseWriter,
        r *http.Request) {
			// TODO: Handle your APIs..

		}))))
}

func corsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(response http.ResponseWriter, r *http.Request) {
		response.Header().Set("Access-Control-Allow-Origin", "<YOUR_WEBSITE_DOMAIN>")
		response.Header().Set("Access-Control-Allow-Credentials", "true")
		if r.Method == "OPTIONS" {
			// we add content-type + other headers used by SuperTokens
			response.Header().Set("Access-Control-Allow-Headers",
				strings.Join(append([]string{"Content-Type"},
					supertokens.GetAllCORSHeaders()...), ","))
			response.Header().Set("Access-Control-Allow-Methods", "*")
			response.Write([]byte(""))
		} else {
			next.ServeHTTP(response, r)
		}
	})
}
import (
	"net/http"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
    // SuperTokens init...

	router := gin.New()

	// CORS
	router.Use(cors.New(cors.Config{
		AllowOrigins: []string{"<YOUR_WEBSITE_DOMAIN>"},
		AllowMethods: []string{"GET", "POST", "DELETE", "PUT", "OPTIONS"},
		AllowHeaders: append([]string{"content-type"},
			supertokens.GetAllCORSHeaders()...),
		AllowCredentials: true,
	}))

	// Adding the SuperTokens middleware
	router.Use(func(c *gin.Context) {
		supertokens.Middleware(http.HandlerFunc(
			func(rw http.ResponseWriter, r *http.Request) {
				c.Next()
			})).ServeHTTP(c.Writer, c.Request)
		// we call Abort so that the next handler in the chain is not called, unless we call Next explicitly
		c.Abort()
	})

	// Add APIs and start server
}
import (
	"github.com/go-chi/chi"
	"github.com/go-chi/cors"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
    // SuperTokens init...

	r := chi.NewRouter()

	// CORS
	r.Use(cors.Handler(cors.Options{
		AllowedOrigins: []string{"<YOUR_WEBSITE_DOMAIN>"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowedHeaders: append([]string{"Content-Type"},
			supertokens.GetAllCORSHeaders()...),
		AllowCredentials: true,
	}))

	// SuperTokens Middleware
	r.Use(supertokens.Middleware)

	// Add APIs and start server
}
import (
	"net/http"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	// SuperTokens init...

	// TODO: Add APIs

	router := mux.NewRouter()

	// Adding handlers.CORS(options)(supertokens.Middleware(router)))
	http.ListenAndServe("SERVER ADDRESS", handlers.CORS(
		handlers.AllowedHeaders(append([]string{"Content-Type"},
			supertokens.GetAllCORSHeaders()...)),
		handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
		handlers.AllowedOrigins([]string{"<YOUR_WEBSITE_DOMAIN>"}),
		handlers.AllowCredentials(),
	)(supertokens.Middleware(router)))
}
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware

from supertokens_python import get_all_cors_headers
from supertokens_python.framework.fastapi import get_middleware

app = FastAPI()
app.add_middleware(get_middleware())

# TODO: Add APIs

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "<YOUR_WEBSITE_DOMAIN>"
    ],
    allow_credentials=True,
    allow_methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"],
    allow_headers=["Content-Type"] + get_all_cors_headers(),
)

# TODO: start server
from supertokens_python import get_all_cors_headers
from flask import Flask, abort
from flask_cors import CORS
from supertokens_python.framework.flask import Middleware

app = Flask(__name__)
Middleware(app)

# TODO: Add APIs

CORS(
    app=app,
    origins=[
        "<YOUR_WEBSITE_DOMAIN>"
    ],
    supports_credentials=True,
    allow_headers=["Content-Type"] + get_all_cors_headers(),
)

# This is required since if this is not there, then OPTIONS requests for
# the APIs exposed by the supertokens' Middleware will return a 404
@app.route('/', defaults={'u_path': ''})
@app.route('/<path:u_path>')
def catch_all(u_path: str):
    abort(404)

# TODO: start server
from typing import List

from corsheaders.defaults import default_headers

from supertokens_python import get_all_cors_headers

CORS_ORIGIN_WHITELIST = [
    "<YOUR_WEBSITE_DOMAIN>"
]

CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = [
    "<YOUR_WEBSITE_DOMAIN>"
]

CORS_ALLOW_HEADERS: List[str] = list(default_headers) + [
    "Content-Type"
] + get_all_cors_headers()

INSTALLED_APPS = [
    'corsheaders',
    'supertokens_python'
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...,
    'supertokens_python.framework.django.django_middleware.middleware',
]
# TODO: start server

You can review all the endpoints that are added through the use of SuperTokens by visiting the API Specs.

2.4 Add the SuperTokens error handler

Depending on the language and framework that you are using, you might need to add a custom error handler to your server. The handler will catch all the authentication related errors and return proper HTTP responses that can be parsed by the frontend SDKs.

No additional errorHandler is required.

Add the errorHandler Before all your routes and plugin registration

No additional errorHandler is required.
No additional errorHandler is required.
import express, { Request, Response, NextFunction } from "express";
import { errorHandler } from "supertokens-node/framework/express";

let app = express();

// ...your API routes

// Add this AFTER all your routes
app.use(errorHandler());

// your own error handler
app.use((err: unknown, req: Request, res: Response, next: NextFunction) => {
  /* ... */
});
import Fastify from "fastify";
import { errorHandler } from "supertokens-node/framework/fastify";

let fastify = Fastify();

fastify.setErrorHandler(errorHandler());

// ...your API routes

2.5 Secure application routes

Now that your server can authenticate users, the final step that you need to take care of is to prevent unauthorized access to certain parts of the application.

For your APIs that require a user to be logged in, use the verifySession middleware.

For your APIs that require a user to be logged in, use the VerifySession middleware.

For your APIs that require a user to be logged in, use the verify_session middleware.

import express from "express";
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import { SessionRequest } from "supertokens-node/framework/express";

let app = express();

app.post("/like-comment", verifySession(), (req: SessionRequest, res) => {
  let userId = req.session!.getUserId();
  //....
});
import Hapi from "@hapi/hapi";
import { verifySession } from "supertokens-node/recipe/session/framework/hapi";
import { SessionRequest } from "supertokens-node/framework/hapi";

let server = Hapi.server({ port: 8000 });

server.route({
  path: "/like-comment",
  method: "post",
  options: {
    pre: [
      {
        method: verifySession(),
      },
    ],
  },
  handler: async (req: SessionRequest, res) => {
    let userId = req.session!.getUserId();
    //...
  },
});
import Fastify from "fastify";
import { verifySession } from "supertokens-node/recipe/session/framework/fastify";
import { SessionRequest } from "supertokens-node/framework/fastify";

let fastify = Fastify();

fastify.post(
  "/like-comment",
  {
    preHandler: verifySession(),
  },
  (req: SessionRequest, res) => {
    let userId = req.session!.getUserId();
    //....
  },
);
import KoaRouter from "koa-router";
import { verifySession } from "supertokens-node/recipe/session/framework/koa";
import { SessionContext } from "supertokens-node/framework/koa";

let router = new KoaRouter();

router.post("/like-comment", verifySession(), (ctx: SessionContext, next) => {
  let userId = ctx.session!.getUserId();
  //....
});
import { inject, intercept } from "@loopback/core";
import { RestBindings, MiddlewareContext, post, response } from "@loopback/rest";
import { verifySession } from "supertokens-node/recipe/session/framework/loopback";
import { SessionContext } from "supertokens-node/framework/loopback";

class LikeComment {
  constructor(@inject(RestBindings.Http.CONTEXT) private ctx: MiddlewareContext) {}
  @post("/like-comment")
  @intercept(verifySession())
  @response(200)
  handler() {
    let userId = (this.ctx as SessionContext).session!.getUserId();
    //....
  }
}
import (
	"fmt"
	"net/http"

	"github.com/supertokens/supertokens-golang/recipe/session"
)

func main() {
	_ = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
		// Wrap the API handler in session.VerifySession
		session.VerifySession(nil, likeCommentAPI).ServeHTTP(rw, r)
	})
}

func likeCommentAPI(w http.ResponseWriter, r *http.Request) {
	// retrieve the session object as shown below
	sessionContainer := session.GetSessionFromRequestContext(r.Context())

	userID := sessionContainer.GetUserID()

	fmt.Println(userID)
}
import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/supertokens/supertokens-golang/recipe/session"
	"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
)

func main() {
	router := gin.New()

	// Wrap the API handler in session.VerifySession
	router.POST("/likecomment", verifySession(nil), likeCommentAPI)
}

// This is a function that wraps the supertokens verification function
// to work the gin
func verifySession(options *sessmodels.VerifySessionOptions) gin.HandlerFunc {
	return func(c *gin.Context) {
		session.VerifySession(options, func(rw http.ResponseWriter, r *http.Request) {
			c.Request = c.Request.WithContext(r.Context())
			c.Next()
		})(c.Writer, c.Request)
		// we call Abort so that the next handler in the chain is not called, unless we call Next explicitly
		c.Abort()
	}
}

func likeCommentAPI(c *gin.Context) {
	// retrieve the session object as shown below
	sessionContainer := session.GetSessionFromRequestContext(c.Request.Context())

	userID := sessionContainer.GetUserID()

	fmt.Println(userID)
}
import (
	"fmt"
	"net/http"

	"github.com/go-chi/chi"
	"github.com/supertokens/supertokens-golang/recipe/session"
)

func main() {
	r := chi.NewRouter()

	// Wrap the API handler in session.VerifySession
	r.Post("/likecomment", session.VerifySession(nil, likeCommentAPI))
}

func likeCommentAPI(w http.ResponseWriter, r *http.Request) {
	// retrieve the session object as shown below
	sessionContainer := session.GetSessionFromRequestContext(r.Context())

	userID := sessionContainer.GetUserID()

	fmt.Println(userID)
}
import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/supertokens/supertokens-golang/recipe/session"
)

func main() {
	router := mux.NewRouter()

	// Wrap the API handler in session.VerifySession
	router.HandleFunc("/likecomment", session.VerifySession(nil, likeCommentAPI)).Methods(http.MethodPost)
}

func likeCommentAPI(w http.ResponseWriter, r *http.Request) {
	// retrieve the session object as shown below
	sessionContainer := session.GetSessionFromRequestContext(r.Context())

	userID := sessionContainer.GetUserID()

	fmt.Println(userID)
}
from fastapi import Depends

from supertokens_python.recipe.session import SessionContainer
from supertokens_python.recipe.session.framework.fastapi import verify_session


@app.post('/like_comment')
async def like_comment(session: SessionContainer = Depends(verify_session())):
    user_id = session.get_user_id()

    print(user_id)
from flask import g

from supertokens_python.recipe.session import SessionContainer
from supertokens_python.recipe.session.framework.flask import verify_session


@app.route('/update-jwt', methods=['POST'])
@verify_session()
def like_comment():
    session: SessionContainer = g.supertokens

    user_id = session.get_user_id()

    print(user_id)
from typing import cast

from django.http import HttpRequest

from supertokens_python.recipe.session import SessionContainer
from supertokens_python.recipe.session.framework.django.asyncio import verify_session


@verify_session()
async def like_comment(request: HttpRequest):
    session: SessionContainer = cast(SessionContainer, request.supertokens)

    user_id = session.get_user_id()

    print(user_id)

The middleware function returns a 401 to the frontend if a session doesn’t exist, or if the access token has expired, in which case, our frontend SDK automatically refreshes the session.

In case of successful session verification, you get access to a session object using which you can get the user’s ID, or manipulate the session information.

3. Configure the Core Service

If you have signed up and deployed a SuperTokens environment already, you can skip this step. Otherwise, please follow these instructions to use the correct SuperTokens Core instance in your application.

The steps show you how to connect to a SuperTokens Managed Service Environment. If you want to self host the core instance please check the following guide.

3.1 Sign up for a SuperTokens account

Open this page in order to access the account creation page. Select the account that you want to use and wait for the action to complete.

3.2 Create a deployment

After signing in, open the SuperTokens dashboard and select Managed. Enter a name for the deployment, select the region closest to your backend services, and click Deploy Core.

Our internal service will deploy a separate environment based on your selection. After this process is complete, open the new deployment from the list.

3.3 Connect the backend SDK with SuperTokens

In the SuperTokens dashboard, open the newly created deployment and select Overview. In Connection Information, copy the Connection URI and one of the API Keys, then use them as connectionURI and apiKey in your backend SDK configuration. If no suitable key exists, click Generate Key to create one.

import supertokens from "supertokens-node";

supertokens.init({
  supertokens: {
    connectionURI: "<CONNECTION_URI>",
    apiKey: "<API_KEY>",
  },
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [],
});
import "github.com/supertokens/supertokens-golang/supertokens"

func main() {
	supertokens.Init(supertokens.TypeInput{
		Supertokens: &supertokens.ConnectionInfo{
            ConnectionURI: "<CONNECTION_URI>",
            APIKey:        "<API_KEY>",
		},
	})
}
from supertokens_python import init, InputAppInfo, SupertokensConfig

init(
   app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
   supertokens_config=SupertokensConfig(
      connection_uri='<CONNECTION_URI>',
      api_key='<API_KEY>'
   ),
   framework='...',
   recipe_list=[
      #...
   ]
)

Next steps

Review this SuperTokens integration for production readiness.

Now that you have completed the quickstart, continue configuring SuperTokens for your application’s authentication and authorization requirements.

API reference

API schema and response details