Skip to main content

APIs override

Overview

Overriding APIs allows you to take full control of what happens when the frontend SDK calls the backend authentication endpoints. You can send analytics events, syncronize additional information in your own database, or adjust the request input.

General example

Like with the functions override feature, you need to call the original implementation reference to avoid any errors in the authentication flow.

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

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

// here we are only overriding the function that signs out a user
signOutPOST: async function (input) {

if (originalImplementation.signOutPOST === undefined) {
throw Error("Should never come here")
}
// TODO: some custom logic

// or call the default behaviour as show below
return await originalImplementation.signOutPOST(input);
},
// ...
// TODO: override more apis
}
}
}
}),
EmailPassword.init({
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
emailExistsGET: async function (input) {

// we can send a custom response like this:
input.options.res.setStatusCode(200); // or any other status code
input.options.res.sendJSONResponse({
message: "my custom response",
//...
})

// this return doesn't matter. But we must do it
// cause the function signature expects a response.
return {
status: "OK",
exists: false
};
}
}
}
}
})
]
});

Error management

If you want to send a custom error message from the API override function you can send a GENERAL_ERROR response.

If you are using the pre-built UI, the response renders directly in the frontend UI. For custom UI, you can read this response and display the message in an error UI.

The next example shows you how to prevent the user from signing up unless their email is pre-approved by the application's admin.

import EmailPassword from "supertokens-node/recipe/emailpassword";

EmailPassword.init({
override: {
apis: (oI) => {
return {
...oI,
signUpPOST: async function (input) {
let email = input.formFields.find(i => i.id === "email")!.value as string;

if (emailNotAllowed(email)) {
return {
status: "GENERAL_ERROR",
message: "You are not allowed to sign up. Please contact the app's admin to get permission"
}
}
return oI.signUpPOST!(input);
}
}
}
}
})

function emailNotAllowed(email: string) {
// TODO: your impl to check if email is allowed or not
return true;
}

Disable APIs

To disable an API entirely, all you need to do is override the API implementation with undefined.

For example, if you want to disable the sign up / sign in API from this recipe, all you do is this:

import SuperTokens from "supertokens-node";
import ThirdParty from "supertokens-node/recipe/thirdparty";
import EmailPassword from "supertokens-node/recipe/emailpassword";

SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
signInPOST: undefined, // disable sign in with email & password
signUpPOST: undefined, // disable sign up with email & password
}
}
}
}),
ThirdParty.init({
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
signInUpPOST: undefined // disable sign in & up with third party
}
}
}
})
]
});
Important

You then need to define your own routes that handle this API call. You can see the Frontend driver interface API spec here

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: {
apis: (oI) => {
return {
...oI,
signOutPOST: async (input) => {
if (oI.signOutPOST === undefined) {
throw Error("Signout API is disabled");
}

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.signOutPOST(input);
},
};
}
},
})