Skip to main content

SMS Delivery

Overview

SuperTokens sends SMS in different authentication scenarios. The method applies to the Passwordless and MFA recipes.

The following page shows you how to configure the SMS delivery method and adjust the content that gets sent to your users.

Delivery methods

Default method

If you provide no configuration for SMS delivery, the backend SDK sends SMSs by talking to SuperTokens servers on https://api.supertokens.com. This applies to both self hosted and managed services.

Important
  • This is a free service and is globally rate limited. This is not suitable for production use. If you do not receive an SMS using this method, then the SDK prints the SMS content on the terminal.
  • We do not log / store any of the info sent to the API that sends out emails on behalf of your app.
  • You cannot customize the SMS content when using this method. If you want to customize the content, please see one of the other methods in this section.

Twilio

Using this method, you can provide your own Twilio account details to the backend SDK, and the SMS is sent using those.

import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";
import { TwilioService } from "supertokens-node/recipe/passwordless/smsdelivery";

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE",
smsDelivery: {
service: new TwilioService({
twilioSettings: {
accountSid: "...",
authToken: "...",
opts: {
// optionally extra config to pass to Twilio client
},

// give either from or messagingServiceSid
from: "...",
messagingServiceSid: "...",
},
})
},
}),
Session.init()
]
});

To learn about how to customize the SMS templates, please see the next section.

SuperTokens SMS Service

Using this method, SuperTokens sends messages to your users automatically. Use this method if:

  • You are already using the managed service. This is the quickest way to set up SMS sending.
  • You want to take advantage of some SMS sending optimizations we do over time:
    • Reduce SMS cost by picking a local SMS service based on the destination country.
    • Fight spam / misuse of SMS.
important

This is a paid service and charges apply for every SMS based on the cost incurred. New users receive $10 worth of credits.

1. Get the SMS API key

1Sign up on SuperTokens.com
2Create a new development env
3Scroll down and create a new production env (it takes a few minutes to create one)
4Once the production env is set up, you can find your SMS API key under the setup section:
SMS API key screen

2. Set the SMS API key in the backend SDK configuration

import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";
import { SupertokensService } from "supertokens-node/recipe/passwordless/smsdelivery"

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE",
smsDelivery: {
service: new SupertokensService("<SMS API KEY GOES HERE>")
},
}),
Session.init()
]
});

Custom method

This method allows you to send messages however you like. The input to the send function consists of SMS template variables, allowing you to create the content of the SMS as well. Use this method if you are:

  • Using a third party SMS service that is not Twilio.
  • You want to use another delivery method like WhatsApp or Facebook Messenger.
  • You want to do some custom spam protection before sending the SMS.
  • You already have an SMS sending infrastructure and want to use that.
import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE",
smsDelivery: {
override: (originalImplementation) => {
return {
...originalImplementation,
sendSms: async function ({
codeLifetime, // amount of time the code is alive for (in MS)
phoneNumber,
urlWithLinkCode, // magic link
userInputCode, // OTP
}) {
// TODO: create and send SMS
}
}
}
},
}),
Session.init()
]
});

If you call the original implementation function for sendSms, it uses the service that you have configured. If you have not configured any service, it uses the default service.

Important

When using this callback, you must manage sending the SMS yourself.

SMS Customization

You can see the default SMS content:

To change the content of the default SMS templates, you can override the getContent function in the smsDelivery object. It allows you to return an object that has the following properties:

  • body: This is the email's body. This can be HTML or text as well.
  • toPhoneNumber: The phone number where the SMS is sent to.
import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";
import { TwilioService } from "supertokens-node/recipe/passwordless/smsdelivery";

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE",
smsDelivery: {
service: new TwilioService({
twilioSettings: { /*...*/ },
override: (originalImplementation) => {
return {
...originalImplementation,
getContent: async function ({
isFirstFactor,
codeLifetime, // amount of time the code is alive for (in MS)
phoneNumber,
urlWithLinkCode, // magic link
userInputCode, // OTP
}) {
if (isFirstFactor) {
// send some custom SMS content
return {
toPhoneNumber: phoneNumber,
body: "SMS BODY"
}
} else {
// for second factor, urlWithLinkCode will always be
// undefined since we only support OTP based for second factor
return {
toPhoneNumber: phoneNumber,
body: "SMS BODY"
}
}

// You can even call the original implementation and
// modify its content:

/*let originalContent = await originalImplementation.getContent(input)
originalContent.body = "My custom body";
return originalContent;*/

}
}
}
})
}
}),
Session.init()
]
});

Overrides

You can use the override functionality to trigger any kind of behavior before and after SMS sending. This can include things like:

  • Logging
  • Spam protection actions
  • Modifying the email template variables before sending the emails
import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";

supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE",
smsDelivery: {
override: (originalImplementation) => {
return {
...originalImplementation,
sendSms: async function (input) {
// TODO: before sending SMS

await originalImplementation.sendSms(input)

// TODO: after sending SMS
}
}
}
},
}),
Session.init()
]
});