IndexPackages

verify-phone-sms

SMS Phone Verification API using AWS SNS HTTP API with Hono server on Cloudflare Workers

DocumentationOpen in StackBlitz
NPM Monthly Downloadsnpm versionNPM Total DownloadsTypeScript typesInstall sizeCoverage

πŸ€– Agent skill β€” npx skills@latest add https://github.com/OpenSourceAGI/dev-tools-starter-agent --skill verify-phone-sms (what it covers)

A complete Hono-based server for SMS verification using AWS SNS. Built for Cloudflare Workers with comprehensive API documentation and security features.

Features

  • βœ… SMS Verification: Send verification codes via AWS SNS
  • βœ… VoIP Blocking: Optional blocking of VoIP numbers
  • βœ… API Authentication: Secure API key-based authentication
  • βœ… Rate Limiting: Built-in rate limiting protection
  • βœ… OpenAPI Documentation: Auto-generated API documentation
  • βœ… CORS Support: Cross-origin resource sharing enabled
  • βœ… Security Headers: Secure headers middleware
  • βœ… Error Handling: Comprehensive error handling
  • βœ… Health Checks: Built-in health monitoring
  • βœ… General SMS: Send custom SMS messages

Quick Start

Install

npm install verify-phone-sms   # use verifyPhone() from your own backend

Or clone the repo and install its dependencies to run the server itself:

npm install

Set Environment Variables

Create a .env file or set environment variables:

# AWS Credentials
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=us-east-1

# API Configuration
API_KEY=sms_1234567890abcdef1234567890abcdef
SMS_SENDER_ID=Verify

Run Development Server

npm run dev

The server will be available at http://localhost:8787

Deploy to Cloudflare Workers

# Deploy API only
npm run deploy

# Deploy docs only
npm run build:docs
npm run deploy:docs

# Deploy both API and docs
npm run deploy:all

# Deploy to specific environments
npm run deploy:staging
npm run deploy:production
npm run deploy:all:staging
npm run deploy:all:production

Quick Deployment Script

# Deploy everything to default environment
./scripts/deploy.sh

# Deploy to staging
./scripts/deploy.sh staging

# Deploy to production
./scripts/deploy.sh production

# Deploy only API
./scripts/deploy.sh default api

# Deploy only docs
./scripts/deploy.sh default docs

Deployment

Prerequisites

  1. Install Wrangler CLI:

    npm install -g wrangler
  2. Login to Cloudflare:

    wrangler login
  3. Set Secrets:

    wrangler secret put AWS_ACCESS_KEY_ID
    wrangler secret put AWS_SECRET_ACCESS_KEY
    wrangler secret put API_KEY

Environment Configuration

The project supports multiple deployment environments:

  • Default: Development/testing environment
  • Staging: Pre-production testing
  • Production: Live production environment

Each environment can have its own configuration and secrets.

Automated Deployment

GitHub Actions workflows are included for automated deployment:

  • Push to main: Deploys to production
  • Push to staging: Deploys to staging
  • Pull Requests: Runs tests and builds

Required GitHub Secrets:

  • CLOUDFLARE_API_TOKEN
  • CLOUDFLARE_ACCOUNT_ID

For detailed deployment instructions, see DEPLOYMENT.md.

API Endpoints

Health Check

GET /
GET /health

Send Verification Code

POST /api/send
Content-Type: application/json
X-API-Key: your_api_key

{
  "phoneNumber": "+1234567890",
  "code": "123456", // optional, auto-generated if not provided
  "blockVoip": true, // optional, default: false
  "senderId": "MyApp", // optional, default: "Verify"
  "messageTemplate": "Your code is: {code}", // optional
  "smsType": "Transactional" // optional, "Transactional" or "Promotional"
}

Response:

{
  "success": true,
  "message": "Verification code sent successfully",
  "messageId": "abc123def456",
  "code": "123456",
  "phoneNumber": "+1234567890",
  "expiresIn": 600
}

Verify Code

POST /api/verify
Content-Type: application/json
X-API-Key: your_api_key

{
  "phoneNumber": "+1234567890",
  "code": "123456"
}

Response:

{
  "success": true,
  "message": "Code verified successfully",
  "verified": true
}

Send General SMS

POST /api/sms
Content-Type: application/json
X-API-Key: your_api_key

{
  "phoneNumber": "+1234567890",
  "message": "Hello from your app!",
  "senderId": "MyApp",
  "smsType": "Transactional"
}

Response:

{
  "success": true,
  "message": "SMS sent successfully",
  "messageId": "abc123def456",
  "phoneNumber": "+1234567890"
}

API Documentation

Visit /docs to see the interactive OpenAPI documentation.

Authentication

All API endpoints require authentication using an API key. Include the key in the request header:

X-API-Key: your_api_key

Or as a Bearer token:

Authorization: Bearer your_api_key

Configuration

Environment Variables

VariableDescriptionDefault
AWS_ACCESS_KEY_IDAWS Access Key IDRequired
AWS_SECRET_ACCESS_KEYAWS Secret Access KeyRequired
AWS_REGIONAWS Regionus-east-1
API_KEYAPI Key for authenticationRequired
SMS_SENDER_IDDefault SMS sender IDVerify

Rate Limiting

  • Window: 15 minutes
  • Max Requests: 100 per IP
  • Headers: Standard rate limit headers included

Phone Number Validation Options

The API supports two methods for phone number validation and VoIP detection:

External API Method (Default)

  • Uses external phone lookup service for VoIP detection
  • Basic phone number formatting and validation
  • Requires internet access for VoIP checks
  • More accurate VoIP detection

libphonenumber-js Method

  • Uses Google's libphonenumber library for local analysis
  • Advanced phone number formatting and validation
  • No external API calls required
  • Heuristic-based VoIP detection
  • Smaller bundle size (145 kB vs 550 kB for full libphonenumber)
  • Better international number support

Usage Examples

// Using libphonenumber-js for VoIP detection with full metadata
const result = await verifyPhone({
    phoneNumber: '+1-800-555-0123',
    code: '123456',
    blockVoip: true,
    voipDetectionMethod: 'libphonenumber', // Use local analysis
    useLibPhoneNumber: true, // Use libphonenumber-js for formatting/validation
    metadataType: 'full' // Use full metadata (140KB) for better phone type detection
});

// Using libphonenumber-js for formatting only
const result = await verifyPhone({
    phoneNumber: '555-123-4567', // US number without country code
    code: '789012',
    useLibPhoneNumber: true, // Use libphonenumber-js for formatting/validation
    blockVoip: false // Don't block VoIP numbers
});

// Traditional approach (external API)
const result = await verifyPhone({
    phoneNumber: '+44 20 7946 0958', // UK number
    code: 'ABCDEF',
    blockVoip: true,
    voipDetectionMethod: 'api', // Use external API (default)
    useLibPhoneNumber: false // Use basic formatting/validation
});

VoIP Detection Methods

External API (voipDetectionMethod: 'api'):

  • Checks carrier information from phone lookup service
  • Identifies Bandwidth, VoIP, and mobile line types
  • More accurate but requires external API calls

libphonenumber-js (voipDetectionMethod: 'libphonenumber'):

  • Analyzes phone number patterns and structure
  • Identifies common VoIP area codes (800, 888, 877, etc.)
  • Detects non-geographic numbers
  • Recognizes patterns like repeated digits, sequential numbers
  • Heuristic-based approach for common VoIP characteristics

Metadata Options

Minimal Metadata (metadataType: 'minimal' - Default, 75KB):

  • Uses pattern-based heuristics for VoIP detection
  • Smaller bundle size
  • Works with all countries
  • Less accurate but faster

Full Metadata (`metadataType: 'full' - 140KB):

  • Uses phone number type detection (MOBILE, FIXED_LINE, VOIP, etc.)
  • More accurate VoIP detection
  • Larger bundle size (65KB additional)
  • Matches Google's libphonenumber behavior
  • Phone number types: MOBILE, FIXED_LINE, VOIP, PREMIUM_RATE, TOLL_FREE, SHARED_COST

Development

Running Tests

npm test
npm run test:run
npm run test:ui

Local Development

npm run dev

Deployment

# Deploy to production
npm run deploy

# Deploy to staging
npm run deploy:staging

# Deploy to specific environment
npm run deploy:production

Example Usage

JavaScript/Node.js

// Send verification code
const response = await fetch('https://your-api.workers.dev/api/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your_api_key'
  },
  body: JSON.stringify({
    phoneNumber: '+1234567890',
    blockVoip: true,
    senderId: 'MyApp'
  })
});

const result = await response.json();
console.log(result);

cURL

# Send verification code
curl -X POST https://your-api.workers.dev/api/send \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key" \
  -d '{
    "phoneNumber": "+1234567890",
    "blockVoip": true,
    "senderId": "MyApp"
  }'

# Verify code
curl -X POST https://your-api.workers.dev/api/verify \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key" \
  -d '{
    "phoneNumber": "+1234567890",
    "code": "123456"
  }'

Error Handling

The API returns consistent error responses:

{
  "success": false,
  "error": "Error message",
  "details": "Additional error details"
}

Common HTTP status codes:

  • 200: Success
  • 400: Bad request (invalid input)
  • 401: Unauthorized (invalid API key)
  • 429: Too many requests (rate limited)
  • 500: Internal server error

Security Features

  • βœ… API key authentication
  • βœ… Rate limiting
  • βœ… CORS protection
  • βœ… Secure headers
  • βœ… Input validation
  • βœ… Error sanitization
  • βœ… VoIP number blocking (optional)

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client App    │───▢│  Hono Server    │───▢│   AWS SNS       β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚ - Web App       β”‚    β”‚ - Rate Limiting β”‚    β”‚ - SMS Delivery  β”‚
β”‚ - Mobile App    β”‚    β”‚ - Auth          β”‚    β”‚ - Message ID    β”‚
β”‚ - API Client    β”‚    β”‚ - Validation    β”‚    β”‚ - Error Handlingβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Roadmap: Identity Verification

Phone verification proves control of a number. The next tier proves the person behind that number is real β€” and turns that proof into something businesses pay for.

Planned integrations

  • Persona API β€” document and selfie identity verification. Entry plan is **250/month,including166verificationsβˆ—βˆ—(Β 250/month, including 166 verifications** (~1.50 each); volume past the included allowance is billed per verification.
  • Auto sign-in by phone β€” once a registered user's number is verified and on file, authenticate them from the phone itself instead of re-sending a code on every login.
  • Address history over legal ID β€” a chain of past addresses is a stronger identity signal than a photo of a government ID, which can be AI-generated or reused across accounts. Treat document capture as corroboration, not proof.
  • Liveness and face check β€” confirm a live human is present at capture time, rather than a printed photo, a replayed video, or a generated face.

Product opportunities

  • Verification as a service β€” sell corporations the ability to confirm their customers are real people, with this stack as the verification backend.
  • Verified demographics β€” verified age, location, and demographic attributes make high-quality ad targeting inventory, subject to user consent and applicable privacy law.

References

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.


PRs Welcome

Please star this repo for updates! 🌟


Source: packages/verify-phone-sms/README.md

Last updated on

On this page