AuthTwilioChannel
WIPTwilio Programmable Messaging for SMS magic-link and MFA codes.
Install
bun add twilio
Setup
import { AuthTwilioChannel } from '@gentleduck/auth/channels/twilio'
const channel = new AuthTwilioChannel({
accountSid: process.env.TWILIO_ACCOUNT_SID!,
authToken: process.env.TWILIO_AUTH_TOKEN!,
from: '+15005550006', // your purchased Twilio phone number
kind: 'sms',
id: 'twilio',
})
For toll-free numbers in the US, ensure your sending profile is verified - otherwise SMS will fail.
With magic-link
import { magicLink } from '@gentleduck/auth/providers/magic-link'
auth.providers.use(
magicLink({
channels: {
email: emailChannel,
sms: channel,
},
findIdentityByEmail: (email) => auth.identities.findByEmail(email),
}),
)
// Client picks SMS:
await client.beginProvider('magic-link', { email: 'ada@example.com', channel: 'sms' })
Important: magic-link over SMS still uses email as the identity key - the user enters their email; the SMS goes to the phone number on the identity. You need to seed the phone in the identity profile (or collect it before sending).
Templating
Default body:
Your sign-in link: https://app.example.com/auth/magic-link/callback?token=...
Expires in 10 minutes.
Customise by subclassing:
class BrandedTwilio extends AuthTwilioChannel {
async renderMessage({ templateId, vars }) {
return {
to: vars.phone, // resolve from identity.profile.phone
body: `${vars.appName}: tap to sign in -> ${vars.url}`,
}
}
}
Carrier filtering
Carriers in the US (Verizon, AT&T) filter messages aggressively. To maximise deliverability:
- Avoid all-caps subject lines.
- Don't include shortened URLs (
bit.ly,t.co) - they trigger spam filters. - Use a Toll-Free Verified Sender or a 10DLC campaign for production volume.
MFA codes
For 6-digit MFA codes (TOTP / phone verification):
class MfaTwilio extends AuthTwilioChannel {
async renderMessage({ templateId, vars }) {
if (templateId === 'mfa-code') {
return {
to: vars.phone,
body: `Your ${vars.appName} verification code is ${vars.code}.`,
}
}
return super.renderMessage({ templateId, vars })
}
}
For SMS-based MFA, consider WebAuthn-MFA instead - it's phishing- resistant, where SMS is increasingly attacked via SIM-swap fraud.