Overview
The SMSProvider interface enables phone-based authentication by defining the contract for sending SMS messages. Implement this interface to integrate any SMS service provider with Arraf Auth.
Interface Definition
The SMSProvider interface is defined in @arraf-auth/core:
export interface SMSProvider {
send(params: SMSSendParams): Promise<SMSSendResult>
}
Method
send
Sends an SMS message to the specified phone number.
Parameters for sending the SMS message
Promise resolving to the result of the SMS send operation
SMSSendParams
export interface SMSSendParams {
to: string
message: string
}
The recipient’s phone number in E.164 format (e.g., “+966501234567”)
The SMS message content to send
SMSSendResult
export interface SMSSendResult {
success: boolean
messageId?: string
error?: string
}
Whether the SMS was sent successfully
Provider-specific message identifier for tracking
Error message if the send operation failed
Implementation Examples
Unifonic Provider (Saudi Arabia)
import type { SMSProvider, SMSSendParams, SMSSendResult } from "@arraf-auth/core"
export interface UnifonicConfig {
appSid: string
}
export function unifonic(config: UnifonicConfig): SMSProvider {
return {
async send(params: SMSSendParams): Promise<SMSSendResult> {
try {
const response = await fetch(
"https://api.unifonic.com/rest/SMS/messages",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
AppSid: config.appSid,
Recipient: params.to,
Body: params.message,
}),
}
)
const data = await response.json()
if (data.success) {
return {
success: true,
messageId: data.data?.MessageID,
}
}
return {
success: false,
error: data.message || "Failed to send SMS",
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
}
}
},
}
}
Taqnyat Provider (Saudi Arabia)
import type { SMSProvider, SMSSendParams, SMSSendResult } from "@arraf-auth/core"
export interface TaqnyatConfig {
bearerToken: string
sender: string
}
export function taqnyat(config: TaqnyatConfig): SMSProvider {
return {
async send(params: SMSSendParams): Promise<SMSSendResult> {
try {
const response = await fetch(
"https://api.taqnyat.sa/v1/messages",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${config.bearerToken}`,
},
body: JSON.stringify({
recipients: [params.to],
body: params.message,
sender: config.sender,
}),
}
)
const data = await response.json()
if (response.ok && data.statusCode === 200) {
return {
success: true,
messageId: data.messageId,
}
}
return {
success: false,
error: data.message || "Failed to send SMS",
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
}
}
},
}
}
Msegat Provider (Saudi Arabia)
import type { SMSProvider, SMSSendParams, SMSSendResult } from "@arraf-auth/core"
export interface MsegatConfig {
userName: string
apiKey: string
userSender: string
}
export function msegat(config: MsegatConfig): SMSProvider {
return {
async send(params: SMSSendParams): Promise<SMSSendResult> {
try {
const response = await fetch(
"https://www.msegat.com/gw/sendsms.php",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userName: config.userName,
apiKey: config.apiKey,
numbers: params.to,
userSender: config.userSender,
msg: params.message,
msgEncoding: "UTF8",
}),
}
)
const data = await response.json()
if (data.code === "1") {
return {
success: true,
messageId: data.messageID,
}
}
return {
success: false,
error: data.message || "Failed to send SMS",
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
}
}
},
}
}
Usage
Add your SMS provider to the Arraf Auth configuration:
import { ArrafAuth } from "@arraf-auth/core"
import { unifonic } from "./providers/unifonic"
const auth = new ArrafAuth({
secret: process.env.AUTH_SECRET,
database: adapter,
sms: unifonic({
appSid: process.env.UNIFONIC_APP_SID!,
}),
})
Always handle SMS sending errors gracefully and provide clear error messages to users. Most providers have rate limits and delivery constraints.
Best Practices
- Error Handling: Always wrap API calls in try-catch blocks and return appropriate error messages
- Phone Format: Ensure phone numbers are in E.164 format before sending
- Message Length: Be mindful of SMS character limits (typically 160 characters for GSM-7)
- Rate Limiting: Implement rate limiting to prevent abuse and control costs
- Testing: Use provider sandbox environments for development and testing