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.
See all the functions that can be overridden here
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);
},
};
},
},
})