Backend Integration
Supported frameworks#
1) Install#
- NodeJS
 - GoLang
 - Python
 
npm i -s supertokens-nodego get github.com/supertokens/supertokens-golangpip install supertokens-python2) Initialise SuperTokens#
Add the code below to your server's init file.
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - Serverless
 - Next.js
 - Nest.js
 
info
Please refer the AWS lambda, Vercel or Netlify sections (In the Integrations section on the left nav bar)
info
Please refer the NextJS section (In the Integrations section on the left nav bar)
info
Please refer the NestJS section (In the Integrations section on the left nav bar)
import supertokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
supertokens.init({    framework: "express",    supertokens: {        connectionURI: "",        apiKey: "",    },    appInfo: {        // learn more about this on https://supertokens.com/docs/session/appinfo        appName: "<YOUR_APP_NAME>",        apiDomain: "<YOUR_API_DOMAIN>",        websiteDomain: "<YOUR_WEBSITE_DOMAIN>",        apiBasePath: "/auth",        websiteBasePath: "/auth"    },    recipeList: [        Session.init()    ]});import supertokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
supertokens.init({    framework: "hapi",    supertokens: {        connectionURI: "",        apiKey: "",    },    appInfo: {        // learn more about this on https://supertokens.com/docs/session/appinfo        appName: "<YOUR_APP_NAME>",        apiDomain: "<YOUR_API_DOMAIN>",        websiteDomain: "<YOUR_WEBSITE_DOMAIN>",        apiBasePath: "/auth",        websiteBasePath: "/auth"    },    recipeList: [        Session.init()    ]});import supertokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
supertokens.init({    framework: "fastify",    supertokens: {        connectionURI: "",        apiKey: "",    },    appInfo: {        // learn more about this on https://supertokens.com/docs/session/appinfo        appName: "<YOUR_APP_NAME>",        apiDomain: "<YOUR_API_DOMAIN>",        websiteDomain: "<YOUR_WEBSITE_DOMAIN>",        apiBasePath: "/auth",        websiteBasePath: "/auth"    },    recipeList: [        Session.init()    ]});import supertokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
supertokens.init({    framework: "koa",    supertokens: {        connectionURI: "",        apiKey: "",    },    appInfo: {        // learn more about this on https://supertokens.com/docs/session/appinfo        appName: "<YOUR_APP_NAME>",        apiDomain: "<YOUR_API_DOMAIN>",        websiteDomain: "<YOUR_WEBSITE_DOMAIN>",        apiBasePath: "/auth",        websiteBasePath: "/auth"    },    recipeList: [        Session.init()    ]});import supertokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
supertokens.init({    framework: "loopback",    supertokens: {        connectionURI: "",        apiKey: "",    },    appInfo: {        // learn more about this on https://supertokens.com/docs/session/appinfo        appName: "<YOUR_APP_NAME>",        apiDomain: "<YOUR_API_DOMAIN>",        websiteDomain: "<YOUR_WEBSITE_DOMAIN>",        apiBasePath: "/auth",        websiteBasePath: "/auth"    },    recipeList: [        Session.init()    ]});import (    "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{            ConnectionURI: "",            APIKey: "",        },        AppInfo: supertokens.AppInfo{            AppName: "<YOUR_APP_NAME>",            APIDomain: "<YOUR_API_DOMAIN>",            WebsiteDomain: "<YOUR_WEBSITE_DOMAIN>",            APIBasePath: &apiBasePath,            WebsiteBasePath: &websiteBasePath,        },        RecipeList: []supertokens.Recipe{            session.Init(nil),        },    })
    if err != nil {        panic(err.Error())    }}- FastAPI
 - Flask
 - Django
 
from supertokens_python import init, InputAppInfo, SupertokensConfigfrom supertokens_python.recipe import 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(        connection_uri="",        api_key=""    ),    framework='fastapi',    recipe_list=[        session.init()    ],    mode='asgi' # use wsgi if you are running using gunicorn)from supertokens_python import init, InputAppInfo, SupertokensConfigfrom supertokens_python.recipe import 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(        connection_uri="",        api_key=""    ),    framework='flask',    recipe_list=[        session.init()    ])from supertokens_python import init, InputAppInfo, SupertokensConfigfrom supertokens_python.recipe import 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(        connection_uri="",        api_key=""    ),    framework='django',    recipe_list=[        session.init()    ],    mode='asgi' # use wsgi if you are running django server in sync mode)3) Add the SuperTokens APIs & CORS setup#
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - Serverless
 - Next.js
 - Nest.js
 
info
Please refer the AWS lambda, Vercel or Netlify sections (In the Integrations section on the left nav bar)
info
Please refer the NextJS section (In the Integrations section on the left nav bar)
info
Please refer the NestJS section (In the Integrations section on the left nav bar)
important
- Add the 
middlewareBEFORE all your routes. - Add the 
corsmiddleware BEFORE the SuperTokens middleware as shown below. 
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 routesThis middleware adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
Register the plugin.
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 routesThis plugin adds a few APIs (see all the APIs here) as well take care of all the errors thrown by the Supertokens library:
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
Register the plugin. Also register @fastify/formbody plugin.
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 middlewaresfastify.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(8000);})();
// ...your API routesThis plugin adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
important
Add the middleware BEFORE all your 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();
// ...other middlewaresapp.use(cors({    origin: "<YOUR_WEBSITE_DOMAIN>",    allowHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],    credentials: true,}));
app.use(middleware());
// ...your API routesThis middleware adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
important
Add the middleware BEFORE all your 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 routesThis middleware adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
- Chi
 - net/http
 - Gin
 - Mux
 
Use the supertokens.Middleware and the supertokens.GetAllCORSHeaders() functions as shown below.
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)        }    })}Use the supertokens.Middleware and the supertokens.GetAllCORSHeaders() functions as shown below.
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}Use the supertokens.Middleware and the supertokens.GetAllCORSHeaders() functions as shown below.
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}Use the supertokens.Middleware and the supertokens.GetAllCORSHeaders() functions as shown below.
import (    "net/http"
    "github.com/gorilla/handlers"    "github.com/gorilla/mux"    "github.com/supertokens/supertokens-golang/supertokens")
func main() {    // SuperTokens init...
    // 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)))}This Middleware adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
- FastAPI
 - Flask
 - Django
 
Use the Middleware (BEFORE all your routes) and the get_all_cors_headers() functions as shown below.
from supertokens_python import get_all_cors_headersfrom fastapi import FastAPIfrom starlette.middleware.cors import CORSMiddlewarefrom 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- Use the 
Middleware(BEFORE all your routes and after calling init function) and theget_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 
Middlewarewill return a404. 
from supertokens_python import get_all_cors_headersfrom flask import Flask, abortfrom 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 serverUse the Middleware and the get_all_cors_headers() functions as shown below in your settings.py.
from supertokens_python import get_all_cors_headersfrom typing import Listfrom corsheaders.defaults import default_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 serverThis Middleware adds a few APIs (see all the APIs here):
POST /auth/session/refresh: It is used to get a new refresh and access token in case the older one expires.POST /auth/signout: It is used sign out the currently logged in user.
4) Add the SuperTokens error handler#
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - Serverless
 - Next.js
 - Nest.js
 
info
Please refer the AWS lambda, Vercel or Netlify sections (In the Integrations section on the left nav bar)
info
Please refer the NextJS section (In the Integrations section on the left nav bar)
info
Please refer the NestJS section (In the Integrations section on the left nav bar)
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 routesapp.use(errorHandler())
// your own error handlerapp.use((err: unknown, req: Request, res: Response, next: NextFunction) => { /* ... */ });
No additional errorHandler is required.
Add the errorHandler Before all your routes and plugin registration
import Fastify from "fastify";import { errorHandler } from "supertokens-node/framework/fastify";
let fastify = Fastify();
fastify.setErrorHandler(errorHandler());
// ...your API routesNo additional errorHandler is required.
No additional errorHandler is required.
info
You can skip this step
info
You can skip this step
5) Add session verification to your API#
For your APIs that require a user to be logged in, use the verifySession middleware:
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - Serverless
 - Next.js
 - Nest.js
 
info
Please refer the AWS lambda, Vercel or Netlify sections (In the Integrations section on the left nav bar)
info
Please refer the NextJS section (In the Integrations section on the left nav bar)
info
Please refer the NestJS section (In the Integrations section on the left nav bar)
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 Session from "supertokens-node/recipe/session";
class LikeComment {    constructor(@inject(RestBindings.Http.CONTEXT) private ctx: MiddlewareContext) { }    @post("/like-comment")    @intercept(verifySession())    @response(200)    handler() {        let userId = ((this.ctx as any).session as Session.SessionContainer).getUserId();        //....    }}- Chi
 - net/http
 - Gin
 - Mux
 
import (    "fmt"    "net/http"
    "github.com/supertokens/supertokens-golang/recipe/session"    "github.com/supertokens/supertokens-golang/supertokens")
func main() {    http.ListenAndServe("SERVER ADDRESS", corsMiddleware(        supertokens.Middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {            // Handle your APIs..            if r.URL.Path == "/sessioninfo" {                // Calling the API with session verification                session.VerifySession(nil, sessioninfo).ServeHTTP(rw, r)                return            }        }))))}
func corsMiddleware(next http.Handler) http.Handler {    return http.HandlerFunc(func(response http.ResponseWriter, r *http.Request) {        // from previous step...    })}
// This is the API handler.func sessioninfo(w http.ResponseWriter, r *http.Request) {    // Fetching the session object and reading the userID    sessionContainer := session.GetSessionFromRequestContext(r.Context())    userId := sessionContainer.GetUserID()
    // TODO: API logic..    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()
    router.GET("/sessioninfo", verifySession(nil), sessioninfo)}
// Wrap session.VerifySession to work with Ginfunc 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()    }}
// This is the API handler.func sessioninfo(c *gin.Context) {    // Fetching the session object and reading the userID    sessionContainer := session.GetSessionFromRequestContext(c.Request.Context())    userId := sessionContainer.GetUserID()
    // TODO: API logic..    fmt.Println(userId)}import (    "fmt"    "net/http"
    "github.com/go-chi/chi"    "github.com/supertokens/supertokens-golang/recipe/session")
func main() {    r := chi.NewRouter()
    r.Get("/sessioninfo", session.VerifySession(nil, sessioninfo))}
// This is the API handler.func sessioninfo(w http.ResponseWriter, r *http.Request) {    // Fetching the session object and reading the userID    sessionContainer := session.GetSessionFromRequestContext(r.Context())    userId := sessionContainer.GetUserID()
    // TODO: API logic..    fmt.Println(userId)}import (    "fmt"    "net/http"
    "github.com/gorilla/mux"    "github.com/supertokens/supertokens-golang/recipe/session")
func main() {    router := mux.NewRouter()
    router.HandleFunc("/sessioninfo",        session.VerifySession(nil, sessioninfo)).Methods(http.MethodGet)}
// This is the API handler.func sessioninfo(w http.ResponseWriter, r *http.Request) {    // Fetching the session object and reading the userID    sessionContainer := session.GetSessionFromRequestContext(r.Context())    userId := sessionContainer.GetUserID()
    // TODO: API logic..    fmt.Println(userId)}- FastAPI
 - Flask
 - Django
 
from supertokens_python.recipe.session.framework.fastapi import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom fastapi import Depends
@app.post('/like_comment') async def like_comment(session: SessionContainer = Depends(verify_session())):    _ = session.get_user_id()from supertokens_python.recipe.session.framework.flask import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom flask import g
@app.route('/update-jwt', methods=['POST']) @verify_session()def like_comment():    session: SessionContainer = g.supertokens 
    _ = session.get_user_id()from supertokens_python.recipe.session.framework.django.asyncio import verify_sessionfrom django.http import HttpRequestfrom supertokens_python.recipe.session import SessionContainer
@verify_session()async def like_comment(request: HttpRequest):    session: SessionContainer = request.supertokens 
    _ = session.get_user_id()6) Setup the SuperTokens core#
https://try.supertokens.com as the connection URI in the init function?