Securing your API and frontend routes
Protecting APIs#
Requiring an active session#
For your APIs that require a user to be logged in, use the verifySession middleware
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - AWS Lambda / Netlify
 - Next.js
 - NestJS
 
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 { verifySession } from "supertokens-node/recipe/session/framework/awsLambda";import { SessionEventV2 } from "supertokens-node/framework/awsLambda";
async function likeComment(awsEvent: SessionEventV2) {    let userId = awsEvent.session!.getUserId();    //....};
exports.handler = verifySession(likeComment);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 { superTokensNextWrapper } from 'supertokens-node/nextjs'import { verifySession } from "supertokens-node/recipe/session/framework/express";import { SessionRequest } from "supertokens-node/framework/express";
export default async function likeComment(req: SessionRequest, res: any) {    await superTokensNextWrapper(        async (next) => {            await verifySession()(req, res, next);        },        req,        res    )
    let userId = req.session!.getUserId();    //....}import { Controller, Post, UseGuards, Session } from "@nestjs/common";import { SessionContainer } from "supertokens-node/recipe/session";import { AuthGuard } from './auth/auth.guard';
@Controller()export class ExampleController {  @Post('example')  @UseGuards(new AuthGuard()) // For more information about this guard please read our NestJS guide.  async postExample(@Session() session: SessionContainer): Promise<boolean> {    let userId = session.getUserId();
    //....    return true;  }}- Chi
 - net/http
 - Gin
 - Mux
 
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 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()    }}
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)}- 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())):    user_id = session.get_user_id()
    print(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 
    user_id = session.get_user_id()
    print(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 
    user_id = session.get_user_id()        print(user_id)The verifySession 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.
Microservice authentication#
For authentication between microservices on your backend, checkout the microservice auth guide.
Protecting frontend routes#
- Web
 - Mobile
 
- Via NPM
 - Via Script Tag
 
You can use the doesSessionExist function to check if a session exists.
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    }}You can use the doesSessionExist function to check if a session exists.
async function doesSessionExist() {    if (await Session.doesSessionExist()) {        // user is logged in    } else {        // user has not logged in yet    }}- React Native
 - Android
 - iOS
 
You can use the doesSessionExist function to check if a session exists.
import SuperTokens from 'supertokens-react-native';
async function doesSessionExist() {    if (await SuperTokens.doesSessionExist()) {        // user is logged in    } else {        // user has not logged in yet    }}You can use the doesSessionExist function to check if a session exists.
import android.app.Applicationimport com.supertokens.session.SuperTokens
class MainApplication: Application() {    fun doesSessionExist() {        if (SuperTokens.doesSessionExist(this.applicationContext)) {            // user is logged in        } else {            // user has not logged in yet        }    }}You can use the doesSessionExist function to check if a session exists.
import UIKitimport SuperTokensIOS
class ViewController: UIViewController {    func doesSessionExist() {        if SuperTokens.doesSessionExist() {            // User is logged in        } else {            // User is not logged in        }    }}See also#
- Optional sessions for APIs and the frontend
 - Verifying session without using a middleware
 - Session claim validation for APIs and the frontend
 - Changing session lifetime
 - Sharing session across sub domains