Skip to main content

Function overrides

Overview

Function overrides let you customize the behavior of the functions used internally, by the SDKs. You can change how actions like signing in, signing up, creating, or revoking sessions or signing out work. This flexibility lets you integrate your own logic into the authentication and session management processes.

For example, if a recipe checks for an active session using the session recipe’s doesSessionExist function, you can override that function to work with your custom session management. Similarly, if you already have a sign-in/sign-up flow and want to integrate with SuperTokens you can use a override to handle the migration process. You can even implement your own userId format by mapping your userIds to those generated by SuperTokens.

Example

The code snippet shows the general flow of overriding a function. You inject your own custom logic while also calling the original implementation of the function.

import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import ThirdParty from "supertokens-node/recipe/thirdparty";

SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
Session.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,

// here we are only overriding the function that's responsible
// for creating a new session
createNewSession: async function (input) {
// TODO: some custom logic

// or call the default behaviour as show below
return await originalImplementation.createNewSession(input);
},
// ...
// TODO: override more functions
}
}
}
}),
ThirdParty.init({
signInAndUpFeature: {
providers: [/* ... */]
},
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,

// here we are only overriding the function that's responsible
// for signing in or signing up a user.
signInUp: async function (input) {
// TODO: some custom logic

// or call the default behaviour as show below
return await originalImplementation.signInUp(input);
},
// ...
// TODO: override more functions
}
}
}
})
]
});

Error management

If you want to throw a custom error from function overrides you have to handle it manually.

Raise the error

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

Session.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
createNewSession: async function (input) {
const existingSessions = await Session.getAllSessionHandlesForUser(input.userId);
if (existingSessions.length > 0) {
// this means that the user already has a session on some other device
throw new Error("Session already exists on another device");
}

// no other session exists, and so we can continue with logging in this user
return originalImplementation.createNewSession(input);
}
}
}
}
})

Handle the error manually

import express from "express";

let app = express();

//...

// in your app's error handler, we catch the custom error
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
if (err.message === "Session already exists on another device") {
// TODO: send a custom response using res
return;
}
res.send(500).send(err.message)
})

Read custom request information

We use the getRequestFromUserContext function provided by the SDK to get the request object from the user context.

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

Session.init({
override: {
functions: (oI) => {
return {
...oI,
revokeSession: async (input) => {
let customHeaderValue = "";
const request = SuperTokens.getRequestFromUserContext(input.userContext);

if (request !== undefined) {
customHeaderValue = request.getHeaderValue("customHeader");
} else {
/**
* This is possible if the function is triggered from the user management dashboard
*
* In this case set a reasonable default value to use
*/
customHeaderValue = "default";
}


// Perform custom logic based on the value of customHeaderValue

return oI.revokeSession(input);
},
};
},
},
})