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.
- 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.
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
env
env
(it takes a few minutes to create one)env
is set up, you can find your SMS API key under the setup section:
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.
When using this callback, you must manage sending the SMS yourself.
SMS Customization
You can see the default SMS content:
- Default passwordless login with OTP template.
- Default passwordless login with magic link template.
- Default passwordless login with magic link and OTP template.
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()
]
});