SMS Verification Module
How it works
- Initiate session - Create a session with the
smsVerification
module, optionally providing the user's phone number. - User provides number - If not pre-filled, the user enters their phone number in the verification interface.
- OTP sent - FaceSign sends a secure, time-sensitive OTP to the user's phone.
- User enters OTP - The user enters the OTP from the text message into the interface.
- Verification confirmed - FaceSign validates the OTP and completes the module.
Module configuration
Properties
- Name
type
- Type
- string
- Description
Must be
smsVerification
.
- Name
phone
- Type
- string
- Description
The user's phone number in E.164 format (e.g.,
+14155552671
). If not provided, the user will be prompted to enter it.
Example implementations
Basic SMS verification
A simple setup where the user is prompted to enter their phone number:
Backend: Create session
const { session, clientSecret } = await client.sessions.create({
clientReferenceId: 'user_123',
modules: [
{ type: 'smsVerification' }
]
});
Pre-filled SMS verification
To streamline the process, pre-fill the user's phone number:
Backend: Create session with pre-filled data
const { session, clientSecret } = await client.sessions.create({
clientReferenceId: 'user_123',
modules: [
{
type: 'smsVerification',
phone: '+14155552671'
}
],
metadata: {
userId: 'user_123'
}
});
User experience
Phone number entry
The interface includes a country code selector for easy and accurate phone number entry:
OTP entry
The user enters the OTP they received via text message:
OTP message template
The text message sent to the user is clear and concise:
Handling verification results
Webhook event
After successful verification, you'll receive a session.completed
webhook. The verified phone number will be in the extractedData
field of the session report.
session.completed webhook payload
{
"id": "evt_abc123",
"type": "session.completed",
"data": {
"session": {
"id": "fs_session_xyz789",
"status": "complete",
"report": {
"isVerified": true,
"extractedData": {
"phone": "+14155552671"
}
},
"settings": {
"clientReferenceId": "user_123"
}
}
}
}
Backend logic
Update your database with the verified phone number upon receiving the webhook:
Backend: Webhook handler
app.post('/webhooks/facesign', async (req, res) => {
const { type, data } = req.body;
if (type === 'session.completed' && data.session.report?.isVerified) {
const { session } = data;
const { report, settings } = session;
const phone = report.extractedData?.phone;
const userId = settings.clientReferenceId;
if (phone) {
// Update user record in your database
await db.users.update({
where: { id: userId },
data: {
phoneNumber: phone,
phoneVerified: true,
phoneVerifiedAt: new Date()
}
});
// Enable features requiring a verified phone number
await enableTwoFactorAuth(userId);
}
}
res.status(200).send('OK');
});
Best practices
1. Pre-fill phone number
Whenever possible, pre-fill the phone number to simplify the process for users.
2. E.164 format
Always provide phone numbers in E.164 format to ensure proper delivery of SMS messages across the globe.
3. Combining with other modules
SMS verification is often used as a second factor of authentication. Combine it with emailVerification
or identityVerification
for enhanced security.
Backend: 2FA setup
const { session, clientSecret } = await client.sessions.create({
clientReferenceId: 'user_123',
modules: [
{
type: 'emailVerification',
email: 'john.doe@example.com'
},
{
type: 'smsVerification' // Add as a second factor
}
]
});
4. Cost considerations
Be aware that SMS messages have carrier costs, which may vary by country. FaceSign optimizes for deliverability and cost-effectiveness.
Next steps
- Email Verification - Add email verification to your flow
- Identity Verification - Implement biometric verification for higher security
- Webhooks - Learn more about handling real-time notifications