Protecting API and website routes
#
Protecting API routesIn your API routes you:
- Verify that a session exists
- Read the userId from the session information
- Read and verify that the user has the correct role
- NodeJS
- GoLang
- Python
- Express
- Hapi
- Fastify
- Koa
- Loopback
- AWS Lambda / Netlify
- Next.js
- NestJS
import { verifySession } from "supertokens-node/recipe/session/framework/express";import express from "express";import { SessionRequest } from "supertokens-node/framework/express";import UserRoles from "supertokens-node/recipe/userroles";
let app = express();
app.post("/set-role", verifySession(), async (req: SessionRequest, res) => {
let userId = req.session!.getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // ... } else { // ... }
//....});
import Hapi from "@hapi/hapi";import { verifySession } from "supertokens-node/recipe/session/framework/hapi";import {SessionRequest} from "supertokens-node/framework/hapi";import UserRoles from "supertokens-node/recipe/userroles";
let server = Hapi.server({ port: 8000 });
server.route({ path: "/set-role", method: "post", options: { pre: [ { method: verifySession() }, ], }, handler: async (req: SessionRequest, res) => { let userId = req.session!.getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//.... }})
import Fastify from "fastify";import { verifySession } from "supertokens-node/recipe/session/framework/fastify";import { SessionRequest } from "supertokens-node/framework/fastify";import UserRoles from "supertokens-node/recipe/userroles";
let fastify = Fastify();
fastify.post("/set-role", { preHandler: verifySession(),}, async (req: SessionRequest, res) => { let userId = req.session!.getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//....});
import { verifySession } from "supertokens-node/recipe/session/framework/awsLambda";import { SessionEvent } from "supertokens-node/framework/awsLambda";import UserRoles from "supertokens-node/recipe/userroles";
async function setRole(awsEvent: SessionEvent) { let userId = awsEvent.session!.getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//....};
exports.handler = verifySession(setRole);
import KoaRouter from "koa-router";import { verifySession } from "supertokens-node/recipe/session/framework/koa";import {SessionContext} from "supertokens-node/framework/koa";import UserRoles from "supertokens-node/recipe/userroles";
let router = new KoaRouter();
router.post("/set-role", verifySession(), async (ctx: SessionContext, next) => { let userId = ctx.session!.getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } //....});
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";import UserRoles from "supertokens-node/recipe/userroles";
class SetRole { constructor(@inject(RestBindings.Http.CONTEXT) private ctx: MiddlewareContext) { } @post("/set-role") @intercept(verifySession()) @response(200) async handler() { let userId = ((this.ctx as any).session as Session.SessionContainer).getUserId();
let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//.... }}
import { superTokensNextWrapper } from 'supertokens-node/nextjs'import { verifySession } from "supertokens-node/recipe/session/framework/express";import { SessionRequest } from "supertokens-node/framework/express";import UserRoles from "supertokens-node/recipe/userroles";
export default async function setRole(req: SessionRequest, res: any) { await superTokensNextWrapper( async (next) => { await verifySession()(req, res, next); }, req, res )
let userId = req.session!.getUserId(); let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//....}
import { Controller, Post, UseGuards, Request, Response, Session } from "@nestjs/common";import { SessionContainer } from "supertokens-node/recipe/session";import { AuthGuard } from './auth/auth.guard';import UserRoles from "supertokens-node/recipe/userroles";
@Controller()export class ExampleController { @Post('example') @UseGuards(AuthGuard) async postExample(@Session() session: SessionContainer): Promise<boolean> { // For more information about "AuthGuard" and the "Session" decorator please read our NestJS guide. let userId = session.getUserId(); let roles = (await UserRoles.getRolesForUser(userId)).roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. }
//.... return true; }}
- Chi
- net/http
- Gin
- Mux
import ( "net/http"
"github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/userroles" "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 == "/set-role" && r.Method == "POST" { // Calling the API with session verification session.VerifySession(nil, setRole).ServeHTTP(rw, r) return } }))))}
func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, r *http.Request) { // from previous step... })}
func setRole(w http.ResponseWriter, r *http.Request) { // Fetching the session object and reading the userID sessionContainer := session.GetSessionFromRequestContext(r.Context()) userId := sessionContainer.GetUserID()
response, err := userroles.GetRolesForUser(userId, nil) if err != nil { // TODO: Handle error return }
if contains(response.OK.Roles, "admin") { // ... } else { // ... } // ...}
func contains(s []string, e string) bool { for _, a := range s { if a == e { return true } } return false}
import ( "net/http"
"github.com/gin-gonic/gin" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/recipe/userroles")
func main() { router := gin.New()
router.POST("/set-role", verifySession(nil), setRole)}
// 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 setRole(c *gin.Context) { // Fetching the session object and reading the userID sessionContainer := session.GetSessionFromRequestContext(c.Request.Context()) userId := sessionContainer.GetUserID()
response, err := userroles.GetRolesForUser(userId, nil) if err != nil { // TODO: Handle error return }
if contains(response.OK.Roles, "admin") { // ... } else { // ... } // ...}
func contains(s []string, e string) bool { for _, a := range s { if a == e { return true } } return false}
import ( "net/http"
"github.com/go-chi/chi" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/userroles")
func main() { r := chi.NewRouter()
r.Post("/set-role", session.VerifySession(nil, setRole))}
// This is the API handler.func setRole(w http.ResponseWriter, r *http.Request) { // Fetching the session object and reading the userID sessionContainer := session.GetSessionFromRequestContext(r.Context()) userId := sessionContainer.GetUserID()
response, err := userroles.GetRolesForUser(userId, nil) if err != nil { // TODO: Handle error return }
if contains(response.OK.Roles, "admin") { // ... } else { // ... } // ...}
func contains(s []string, e string) bool { for _, a := range s { if a == e { return true } } return false}
import ( "net/http"
"github.com/gorilla/mux" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/userroles")
func main() { router := mux.NewRouter()
router.HandleFunc("/set-role", session.VerifySession(nil, setRole)).Methods(http.MethodPost)}
// This is the API handler.func setRole(w http.ResponseWriter, r *http.Request) { // Fetching the session object and reading the userID sessionContainer := session.GetSessionFromRequestContext(r.Context()) userId := sessionContainer.GetUserID()
response, err := userroles.GetRolesForUser(userId, nil) if err != nil { // TODO: Handle error return }
if contains(response.OK.Roles, "admin") { // ... } else { // ... } // ...}
func contains(s []string, e string) bool { for _, a := range s { if a == e { return true } } return false}
- FastAPI
- Flask
- Django
from fastapi import Depends, FastAPIfrom supertokens_python.recipe.session.framework.fastapi import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom supertokens_python.recipe.userroles.asyncio import get_roles_for_user
app = FastAPI()
@app.post('/set-role') async def set_role_api(session: SessionContainer = Depends(verify_session())): user_id = session.get_user_id()
roles = (await get_roles_for_user(user_id)).roles
if "admin" in roles: pass else: pass
from flask import Flask, gfrom supertokens_python.recipe.session.framework.flask import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom supertokens_python.recipe.userroles.syncio import get_roles_for_user
app = Flask(__name__)
@app.route('/set-role', methods=['POST']) @verify_session()def set_role_api(): """Set roles Flask API""" session: SessionContainer = g.supertokens user_id = session.get_user_id()
roles = get_roles_for_user(user_id).roles
if "admin" in roles: pass else: pass
from django.http import HttpRequestfrom supertokens_python.recipe.session.framework.django.asyncio import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom supertokens_python.recipe.userroles.asyncio import get_roles_for_user
@verify_session()async def get_user_info_api(request: HttpRequest): session: SessionContainer = request.supertokens user_id = session.get_user_id()
roles = (await get_roles_for_user(user_id)).roles
if "admin" in roles: pass else: pass
#
Protecting website routesOn your frontend:
- Verify that a session exists
- Use the
getAccessTokenPayloadSecurely
function to get session information - Read and verify that the user has the correct role
- ReactJS
- Angular
- Plain JavaScript
- React Native
- With React Context
- Without React Context
import React from "react";import { useSessionContext } from 'supertokens-auth-react/recipe/session';
function Dashboard(props: any) { let session = useSessionContext();
if (session.loading) { return null; }
if (!session.doesSessionExist) { // TODO } else { // we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = session.accessTokenPayload.roles;
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}
import Session from 'supertokens-auth-react/recipe/session';
async function getRoles() { if (await Session.doesSessionExist()) {
// we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = (await Session.getAccessTokenPayloadSecurely())["roles"];
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}
- Via NPM
- Via Script Tag
import Session from 'supertokens-web-js/recipe/session';
async function getRoles() { if (await Session.doesSessionExist()) {
// we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = (await Session.getAccessTokenPayloadSecurely())["roles"];
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}
async function getRoles() { if (await supertokensSession.doesSessionExist()) {
// we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = (await supertokensSession.getAccessTokenPayloadSecurely())["roles"];
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}
import SuperTokens from 'supertokens-react-native';
async function getRole() { if (await SuperTokens.doesSessionExist()) {
// we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = (await SuperTokens.getAccessTokenPayloadSecurely())["roles"];
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}
import Session from 'supertokens-web-js/recipe/session';
async function getRoles() { if (await Session.doesSessionExist()) {
// we use the key "roles" here since that's what we // used while setting the payload in the backend. let roles: string[] = (await Session.getAccessTokenPayloadSecurely())["roles"];
if (roles.includes("admin")) { // TODO.. } else { // TODO.. } }}