Skip to main content
Which UI do you use?
Custom UI
Pre built UI

Option 1. Using the access token payload

caution

This guide describes how to add custom claims to SuperTokens Access Tokens.

If you are implementing Unified Login, which makes use of OAuth2 Access Tokens, you will have to check the separate guide.

Add custom claims to the access token payload#

important

There are "protected" claims, reserved for standard or supertokens specific use-cases. Trying to overwrite them in createNewSession or using mergeIntoAccessTokenPayload will result in errors.

They are: sub, iat, exp, sessionHandle, refreshTokenHash1, parentRefreshTokenHash1, antiCsrfToken

There are two ways to add custom claims to the access token payload:

  • During session creation
  • Post session creation

During session creation#

This is the most typical method of adding custom claims. A session is created when a user signs in or signs up, and we can add custom claims to their session by overriding the createNewSession function as shown below:

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;

// This goes in the access token, and is available to read on the frontend.
input.accessTokenPayload = {
...input.accessTokenPayload,
someKey: "someValue",
};

return originalImplementation.createNewSession(input);
},
};
},
},
})
]
});

Post session creation#

In this method, you can modify the access token payload of an existing session. There are two modes in this:

  • With session verification (online mode)
  • Without session verification (offline mode)

With session verification (online mode)#

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("/updateinfo", verifySession(), async (req: SessionRequest, res) => {

let session = req.session;

await session!.mergeIntoAccessTokenPayload(
{ newKey: "newValue" }
);

res.json({ message: "successfully updated access token payload" })
});
  • We first require session verification in order to get the session object
  • Using that object, we call the mergeIntoAccessTokenPayload with new content. This merges the update into the existing object, removing keys set to null in the root of the update object.
  • The result is that the access token is updated in the user's browser cookies. The change is instantly visible on the frontend and the subsequent backend API calls.

Without session verification (offline mode)#

This method can be used to update the access token payload even if the user is not online.

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

async function updateAccessTokenPayload() {
let userId = "...";
// we first get all the sessionHandles (string[]) for a user
let sessionHandles = await Session.getAllSessionHandlesForUser(userId);

// we update all the session's Access Token payloads for this user
sessionHandles.forEach(async (handle) => {
let currSessionInfo = await Session.getSessionInformation(handle);
if (currSessionInfo === undefined) {
return;
}

await Session.mergeIntoAccessTokenPayload(handle,
{ newKey: "newValue" }
);
})
}
caution

Changes to the access token payload via this method are reflected in the session only once the session is refreshed.

Read the access token payload#

Once the custom payload has been added to the session, you can access it on the backend and frontend in the following ways:

Reading the payload on the backend#

With session verification (online mode)#

This method can be used when the user is online and has sent an API request with their session tokens

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

let app = express();

app.get("/myApi", verifySession(), async (req, res) => {

let session = req.session;

let accessTokenPayload = session.getAccessTokenPayload();
let customClaimValue = accessTokenPayload.customClaim
});

Without session verification (offline mode)#

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

async function someFunc() {
let userId = "...";
// we first get all the sessionHandles (string[]) for a user
let sessionHandles = await Session.getAllSessionHandlesForUser(userId);

sessionHandles.forEach(async (handle) => {
let currSessionInfo = await Session.getSessionInformation(handle)
if (currSessionInfo === undefined) {
return;
}
let accessTokenPayload = currSessionInfo.customClaimsInAccessTokenPayload;
let customClaimValue = accessTokenPayload.customClaim;
})
}

Reading the payload on the frontend#

import React from "react";
import { useSessionContext } from 'supertokens-auth-react/recipe/session';

// Your dashboard component
function Dashboard(props: any) {
let session = useSessionContext();

if (session.loading) {
return null;
}

if (!session.doesSessionExist) {
// TODO
} else {
let { accessTokenPayload } = session;
let customClaimValue = accessTokenPayload.customClaim

// TODO
}
}