Assigning roles to a session
This can be done at two points in time:
- 1) During user login / sign up
- 2) In any API call post login
#
1) During user login / sign upWe can set the user's role in the access token by overriding the createNewSession
function in the init
function:
- NodeJS
- GoLang
- Python
import SuperTokens from "supertokens-node";import Session from "supertokens-node/recipe/session";
SuperTokens.init({ supertokens: { connectionURI: "...", }, appInfo: { apiDomain: "...", appName: "...", websiteDomain: "..." }, recipeList: [ Session.init({ override: { functions: (originalImplementation) => { return { ...originalImplementation, createNewSession: async function (input) { let userId = input.userId;
let role = "admin"; // TODO: fetch role based on userId
input.accessTokenPayload = { ...input.accessTokenPayload, role };
return originalImplementation.createNewSession(input); }, }; }, }, }) ]});
import ( "net/http"
"github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/supertokens")
func main() {
supertokens.Init(supertokens.TypeInput{ RecipeList: []supertokens.Recipe{ session.Init(&sessmodels.TypeInput{ Override: &sessmodels.OverrideStruct{ Functions: func(originalImplementation sessmodels.RecipeInterface) sessmodels.RecipeInterface {
// first we create a copy of the original implementation originalCreateNewSession := *originalImplementation.CreateNewSession
// we override the create new session function (*originalImplementation.CreateNewSession) = func(res http.ResponseWriter, userID string, accessTokenPayload, sessionData map[string]interface{}, userContext supertokens.UserContext) (sessmodels.SessionContainer, error) { role := "admin" // TODO: fetch role based on userID
if accessTokenPayload == nil { accessTokenPayload = map[string]interface{}{} } accessTokenPayload["role"] = role
return originalCreateNewSession(res, userID, accessTokenPayload, sessionData, userContext) }
return originalImplementation }, }, }), }, })}
from supertokens_python import init, InputAppInfofrom supertokens_python.recipe.session.interfaces import RecipeInterfacefrom supertokens_python.recipe import sessionfrom typing import Union, Dict, Any
def override_functions(original_implementation: RecipeInterface): original_implementation_create_new_session = original_implementation.create_new_session
async def create_new_session(request: Any, user_id: str, access_token_payload: Union[None, Dict[str, Any]], session_data: Union[None, Dict[str, Any]], user_context: Dict[str, Any]): if session_data is None: session_data = {}
if access_token_payload is None: access_token_payload = {}
role = "admin"; # TODO: fetch role based on user_id access_token_payload["role"] = role
return await original_implementation_create_new_session(request, user_id, access_token_payload, session_data, user_context)
original_implementation.create_new_session = create_new_session return original_implementation
init( app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."), framework='...', recipe_list=[ session.init( override=session.InputOverrideConfig( functions=override_functions ) ) ])
#
2) In any API call post loginPost session verification, you can use the updateAccessTokenPayload
function to store the user's 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";
let app = express();
app.post("/set-role", verifySession(), async (req: SessionRequest, res) => {
let userId = req.session!.getUserId();
let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await req.session!.updateAccessTokenPayload( { role } );
//....});
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: "/set-role", method: "post", options: { pre: [ { method: verifySession() }, ], }, handler: async (req: SessionRequest, res) => { let userId = req.session!.getUserId();
let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await req.session!.updateAccessTokenPayload( { role } );
//.... }})
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("/set-role", { preHandler: verifySession(),}, async (req: SessionRequest, res) => { let userId = req.session!.getUserId();
let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await req.session!.updateAccessTokenPayload( { role } );
//....});
import { verifySession } from "supertokens-node/recipe/session/framework/awsLambda";import { SessionEvent } from "supertokens-node/framework/awsLambda";
async function setRole(awsEvent: SessionEvent) { let userId = awsEvent.session!.getUserId();
let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await awsEvent.session!.updateAccessTokenPayload( { role } );
//....};
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";
let router = new KoaRouter();
router.post("/set-role", verifySession(), async (ctx: SessionContext, next) => { let userId = ctx.session!.getUserId();
let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await ctx.session!.updateAccessTokenPayload( {role} ); //....});
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 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 role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await ((this.ctx as any).session as Session.SessionContainer).updateAccessTokenPayload( { role } );
//.... }}
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 setRole(req: SessionRequest, res: any) { await superTokensNextWrapper( async (next) => { await verifySession()(req, res, next); }, req, res )
let userId = req.session!.getUserId(); let role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await req.session!.updateAccessTokenPayload( { role } );
//....}
import { Controller, Post, UseGuards, Request, Response, Session } from "@nestjs/common";import { SessionContainer } from "supertokens-node/recipe/session";import { AuthGuard } from './auth/auth.guard';
@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 role = "admin"; // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. await session.updateAccessTokenPayload( {role} );
//.... return true; }}
import ( "net/http"
"github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/supertokens")
// Make sure that you wrap this API with the session.VerifySession() functionfunc setRoleAPI(w http.ResponseWriter, r *http.Request) { sessionContainer := session.GetSessionFromRequestContext(r.Context())
currAccessTokenPayload := sessionContainer.GetAccessTokenPayload()
currAccessTokenPayload["role"] = "newRole" // TODO: fetch based on user
// Note that this will override any existing access token payload // that you may have provided earlier. err := sessionContainer.UpdateAccessTokenPayload(currAccessTokenPayload) if err != nil { err = supertokens.ErrorHandler(err, r, w) if err != nil { // TODO: return 500 status code to the client } return }}
- FastAPI
- Flask
- Django
from supertokens_python.recipe.session.framework.fastapi import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom fastapi import Dependsfrom fastapi.responses import PlainTextResponse
@app.post('/update-access-token-payload') async def update_access_token_payload(session: SessionContainer = Depends(verify_session())): # retrieve the session object as shown below current_access_token_payload = session.get_access_token_payload()
current_access_token_payload['role'] = 'admin'
await session.update_access_token_payload(current_access_token_payload)
return PlainTextResponse(content='success')
from supertokens_python.recipe.session.framework.flask import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom flask import g
@app.route('/update-access-token-payload', methods=['POST']) @verify_session()def update_access_token_payload(): session: SessionContainer = g.supertokens
# retrieve the session object as shown below current_access_token_payload = session.get_access_token_payload()
current_access_token_payload['role'] = 'admin'
session.sync_update_access_token_payload(current_access_token_payload)
return 'success'
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 update_access_token_payload(request: HttpRequest): session: SessionContainer = request.supertokens # retrieve the session object as shown below current_access_token_payload = session.get_access_token_payload()
current_access_token_payload['role'] = 'admin'
await session.update_access_token_payload(current_access_token_payload)