Looking to hire Laravel developers? Try LaraJobs

laravel-rebel-channel-twilio maintained by padosoft

Description
Provider Twilio (Verify SMS/WhatsApp/Voice, Fraud Guard, webhook) per Laravel Rebel.
Author
Last update
2026/06/03 11:58 (dev-main)
License
Downloads
0

Comments
comments powered by Disqus

Laravel Rebel — Twilio Channel

Send phone verifications through Twilio Verify, the Rebel way. This package plugs Twilio Verify (SMS / WhatsApp / voice) into laravel-rebel-channels as a VerificationProvider — so you get Twilio's global delivery plus Rebel's fraud guard, rate limiting, fallback and audit on top. Part of the padosoft/laravel-rebel-* suite.


Table of contents


What it is

A thin, well-tested Twilio Verify provider for Rebel Channels. You don't call it directly — you call the Channels VerificationRouter, and it routes through this provider (with Rebel's bot gate, IRSF defences, per-number rate limit, fallback and audit around it).

A small gateway seam (TwilioVerifyGateway) wraps the Twilio SDK, so the whole thing is unit-testable offline and has a real live test-suite for the actual API.

Depends on padosoft/laravel-rebel-core and padosoft/laravel-rebel-channels.


Quick glossary

Term In plain words
Twilio Verify A Twilio product that sends and checks one-time codes for you — you never store or generate the OTP.
Verify Service A Verify configuration (sender IDs, code length, channels). Identified by a SID starting with VA.
Account SID / Auth Token Your Twilio account credentials (the SID starts with AC).
Channel sms, whatsapp or voice (Twilio calls voice call).
Verification SID The handle (VE...) for an in-flight verification.

Why this package

What In short
★★★ Twilio Verify, fully wrapped Start + check codes over SMS/WhatsApp/voice; you never handle the OTP yourself.
★★★ Rebel guarantees for free Inherits the Channels fraud guard (IRSF), rate limit, fallback and HMAC'd audit.
★★ Never throws out Any SDK/transport error becomes a clean provider_error, so the router can fall back to another provider.
★★ Offline-testable A gateway seam + fake means your tests don't hit Twilio; a separate live suite does.
★★ Safe by default No credentials → nothing registers, and no unauthenticated Twilio client is ever built.
Explicit status mapping Twilio Verify statuses are mapped deliberately (an unexpected status is a failure, not a fake "pending").

Rebel + Twilio vs the alternatives

Sending an OTP with Twilio, three ways:

Capability Rebel + this package Twilio Verify SDK (direct) Raw Twilio SMS + your own OTP
Send/check a code via Twilio ➖ (you build OTP logic)
You never store/generate the OTP
Anti toll-fraud / IRSF guard
Per-number rate limit + bot gate
Provider fallback to another vendor
Signed, phone-bound reference (anti replay)
Unified audit trail (number HMAC'd)
Graceful failure → router fallback

Legend: ✅ built-in · ➖ partial · ❌ not available. Twilio Verify is excellent at delivery; this package keeps all of that and adds the Rebel fraud/routing/audit layer around it.


Twilio portal setup (step by step)

  1. Create a Twilio account at twilio.com/try-twilio. The free trial gives you a small credit and a trial number — note that trial accounts can only send to verified caller IDs (add your test phone under Phone Numbers → Verified Caller IDs).
  2. Grab your credentials: on the Console home page copy your Account SID (AC...) and Auth Token.
  3. Create a Verify Service: go to Verify → Services → Create new, give it a friendly name (e.g. "MyApp Login"), choose the channels (SMS / WhatsApp / Voice), and copy the Service SID (VA...).
  4. (WhatsApp only) enable the WhatsApp channel on the Verify Service and complete Twilio's WhatsApp sender onboarding.
  5. Put the three values in your .env (see below). Done — the provider auto-registers.

Pricing: Twilio Verify is billed per successful verification + the channel cost; the free trial credit is enough to test end-to-end. Always keep the Rebel geo allowlist (in laravel-rebel-channels) tight to avoid IRSF charges.


Installation

composer require padosoft/laravel-rebel-channel-twilio
php artisan vendor:publish --tag="rebel-channel-twilio-config"

Add your credentials to .env:

TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_VERIFY_SERVICE_SID=VAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

That's it — the provider registers itself into the Channels router under the key twilio.


Configuration

File config/rebel-channel-twilio.php:

Key Default What it does
account_sid env(TWILIO_ACCOUNT_SID) Twilio Account SID (AC...).
auth_token env(TWILIO_AUTH_TOKEN) Twilio Auth Token.
verify_service_sid env(TWILIO_VERIFY_SERVICE_SID) Verify Service SID (VA...).
channels ['sms','whatsapp','voice'] Which Rebel channels this provider may handle.
register_provider true Auto-register into the Channels registry (when credentials exist).
webhook.enabled false Enable a delivery-status callback endpoint.
webhook.validate_signature true Validate X-Twilio-Signature on the webhook.
webhook.path rebel/twilio/status The webhook route path.

Usage

You typically don't touch this package directly — you use the Channels router:

use Padosoft\Rebel\Channels\Enums\Channel;
use Padosoft\Rebel\Channels\Routing\VerificationRouter;
use Padosoft\Rebel\Core\Context\SecurityContext;
use Padosoft\Rebel\Core\Identifiers\PhoneIdentifier;

$router = app(VerificationRouter::class);

// Send a code (Twilio Verify delivers it)
$start = $router->start(PhoneIdentifier::from('+39 333 1234567'), Channel::Sms, SecurityContext::fromRequest($request));

// Check what the user typed
$result = $router->check(PhoneIdentifier::from('+39 333 1234567'), $request->string('code'), $reference, SecurityContext::fromRequest($request));
if ($result->approved()) {
    // verified!
}

To force Twilio specifically, set it first in the Channels fallback order:

// config/rebel-channels.php
'providers' => ['twilio'],

Live tests against the real API

The offline suite uses a fake gateway. To exercise the real Twilio Verify API (tests/Live), opt in explicitly — it sends a real message:

# .env (or shell env)
REBEL_TWILIO_LIVE=1
TWILIO_TEST_PHONE=+39XXXXXXXXXX   # a verified number on trial accounts

vendor/bin/pest --group=live

Without REBEL_TWILIO_LIVE=1 or with any credential missing, the live tests self-skip, so composer test and external PRs never trigger a send. In CI, supply the values as secrets and set REBEL_TWILIO_LIVE=1 on a dedicated job.


.env.example

TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_VERIFY_SERVICE_SID=VAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
REBEL_TWILIO_REGISTER=true

REBEL_TWILIO_WEBHOOK=false
REBEL_TWILIO_WEBHOOK_VALIDATE=true
REBEL_TWILIO_WEBHOOK_PATH=rebel/twilio/status

# Live tests (opt-in: SENDS A REAL MESSAGE)
REBEL_TWILIO_LIVE=0
TWILIO_TEST_PHONE=+391234567890

Security notes

  • No unauthenticated client: the Twilio client is only constructed when all three credentials are present.
  • No exception leakage: SDK/transport errors are caught and returned as a generic provider_error — Twilio internals never bubble up to your app or logs.
  • Explicit status mapping: only Twilio's pending is treated as a live challenge; any unexpected status fails closed.
  • Keep IRSF defences on: pair this with the Channels geo allowlist / per-prefix cap to avoid premium-rate fraud charges.

Testing & License

composer test      # Pest (provider + Channels integration; live suite self-skips)
composer phpstan   # static analysis, level max
composer pint      # code style

License: MIT — see LICENSE. Part of the padosoft/laravel-rebel suite.