laravel-rebel-bridge-spatie-otp
GitHub repository · Composer: padosoft/laravel-rebel-bridge-spatie-otp · MIT
Email and SMS one-time codes, done right. Turn spatie/laravel-one-time-passwords into an AAL2 Rebel step-up factor — graded on the assurance model and fully audited, with the code never reaching the log.
What it is
A bridge that registers spatie/laravel-one-time-passwords as a Rebel step-up driver (SpatieOtpStepUpDriver). It generates and verifies one-time passwords delivered over email or SMS through the OneTimePasswordBroker contract — backed by SpatieOneTimePasswordBroker — and reports an AAL2 / AMR otp outcome into Rebel’s assurance model and audit trail. spatie keeps owning generation, storage and expiry.
The problem it solves
Email and SMS OTP is the most familiar second factor, but spatie/laravel-one-time-passwords on its own has no shared assurance grade and no cross-package audit trail, and it’s easy to accidentally log the code. The bridge maps each verification to an AAL2 grade, records every send and outcome once in rebel_auth_events, and routes the secret through the core redactor so it can never leak.
What you get
| Capability | What it does |
|---|---|
| OTP step-up driver | SpatieOtpStepUpDriver exposes email/SMS one-time passwords as an AAL2 (AMR otp) Rebel factor. |
| Broker abstraction | OneTimePasswordBroker contract with SpatieOneTimePasswordBroker as the default. |
| Full audit telemetry | Every challenge and verification is recorded through the core audit trail — never the code. |
| Test double | FakeOneTimePasswordBroker for deterministic generate/verify tests. |
When to use it
- You already use spatie/laravel-one-time-passwords and want it graded and audited inside Rebel.
- You need an email or SMS OTP step-up factor with the lowest user friction.
- You want a familiar fallback factor alongside stronger ones, on the same assurance scale.
- You’re consolidating mixed providers into one audit trail.
When not to use it
Email/SMS OTP is AAL2, not phishing-resistant — codes can be relayed or intercepted. For high-value actions, pair it with laravel-rebel-bridge-passkeys (AAL3).
Worked example
composer require padosoft/laravel-rebel-bridge-spatie-otp
php artisan vendor:publish
The bridge auto-registers SpatieOtpStepUpDriver; config/rebel-bridge-spatie-otp.php exposes its options. Bind your own OneTimePasswordBroker to customize delivery, or use FakeOneTimePasswordBroker in tests.
How it fits
This package wraps spatie/laravel-one-time-passwords (the upstream OTP implementation) and registers it with laravel-rebel-step-up (the step-up consumer). It maps each verification onto the AAL/AMR model and audit contract from laravel-rebel-core, placing email/SMS OTP at AAL2 — below the phishing-resistant passkey bridge in audit reasoning.
A standalone OTP package sends a code; this one grades it AAL2, redacts the secret and audits it alongside every other factor. See Why Rebel.
Reference
Runtime files
src\Contracts\OneTimePasswordBroker.phpsrc\Drivers\SpatieOtpStepUpDriver.phpsrc\Support\SpatieOneTimePasswordBroker.phpsrc\Testing\FakeOneTimePasswordBroker.phpsrc\RebelSpatieOtpBridgeServiceProvider.php
Service providers
src\RebelSpatieOtpBridgeServiceProvider.php
Services and managers
src\Contracts\OneTimePasswordBroker.phpsrc\Support\SpatieOneTimePasswordBroker.phpsrc\Testing\FakeOneTimePasswordBroker.phpsrc\RebelSpatieOtpBridgeServiceProvider.php
Contracts
src\Contracts\OneTimePasswordBroker.php
Controllers
None detected in the package tree.
Middleware
None detected in the package tree.
Models
None detected in the package tree.
Config
config\rebel-bridge-spatie-otp.php
Migrations
None detected in the package tree.
Routes
None detected in the package tree.
Commands
None detected in the package tree.
Composer requirements
| Dependency | Constraint |
|---|---|
illuminate/contracts |
`^12.0 |
illuminate/support |
`^12.0 |
padosoft/laravel-rebel-core |
^0.1 |
padosoft/laravel-rebel-step-up |
^0.1 |
php |
^8.3 |
spatie/laravel-package-tools |
^1.92 |
Development requirements
| Dependency | Constraint |
|---|---|
larastan/larastan |
^3.0 |
laravel/pint |
^1.18 |
orchestra/testbench |
`^10.0 |
pestphp/pest |
^4.0 |
pestphp/pest-plugin-laravel |
^4.0 |
spatie/laravel-one-time-passwords |
^1.0 |
ADR
Problem: keep laravel-rebel-bridge-spatie-otp replaceable
Decision: document its public responsibility and use Rebel core contracts at integration boundaries.
Consequences: applications can adopt the package without coupling every other Rebel module to its internals.
Problem: package-specific behavior must remain auditable
Decision: all security-significant outcomes should emit or feed audit events through the core vocabulary.
Consequences: admin API, admin UI and AI guard can reason across packages without bespoke parsers for every provider.
Test and verification surface
tests\Feature\SpatieOtpDriverTest.phptests\Fixtures\User.phptests\Fixtures\UserWithoutOtp.phptests\Pest.phptests\TestCase.php
Do not copy internal test-only classes into an application. Treat file lists as a source map for maintainers and auditors, not as an installation recipe by themselves.