Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Authy Bundle Laravel Package

grizzlylab/authy-bundle

Symfony bundle that integrates Authy two-factor authentication, offering configuration and services to add SMS, voice, or TOTP verification and token validation to your application's login and security flows.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package. There is no service provider, no config publish tag, no facade, no config/authy.php to publish. If you are in a Laravel codebase, do not composer require it into your app/ — you will pull in Symfony DI glue you have to strip out anyway. Treat it as a working reference for how to wire the official authy/php SDK behind a container, and port the ~200 lines of useful logic into a first-party service.

If you are genuinely on Symfony (5.x/6.x, per the bundle's constraints), the minimal path is:

  1. composer require grizzlylab/authy-bundle — it pulls in authy/php.
  2. With Symfony Flex the bundle should auto-register in config/bundles.php. If not, add the GrizzlyLab\AuthyBundle\AuthyBundle class manually.
  3. Create config/packages/authy.yaml (or .php in more recent scaffolding) with the API key and sandbox flag — the bundle's DependencyInjection/Configuration tree will define the exact keys; inspect it before guessing.
  4. Inject the Authy client service (typically type-hinted under the GrizzlyLab\AuthyBundle namespace — read Resources/config/services.yaml) into the controller or service that owns login.

First use case to validate the wiring end to end: register a single user via the Authy client (requestSms / registerUser), then verify one token you actually received on a phone. This confirms three things at once — the API key resolves, the sandbox flag matches the key you were issued, and the SDK's response shape matches what the bundle exposes. Do not proceed to building enrollment UI until you have seen one real token verify successfully. Two-factor failures are almost always configuration (wrong key for the environment) rather than code.

If you are on Laravel: skip installation. Read the bundle's AuthyExtension, the service definition, and any client wrapper class. That is the entire value — a worked example of the Authy request/response contract. Then build App\Services\TwoFactor\TwoFactorProvider (interface) plus a TwilioVerifyDriver, and wire it in a service provider. Budget 1–3 days; you would spend more than that fighting Composer's Symfony constraint graph against Laravel's symfony/* transitive deps.

Implementation Patterns

Symfony: inject, don't instantiate. The bundle's whole point is that the Authy client is a container service. Type-hint it in your constructor or controller action; never new Authy(...) with a key from env() inline. This is what makes the integration testable — you can swap the service for a fake in functional tests via services_test.yaml.

Registration and verification are two calls, not one. The typical day-to-day shape is:

  • At enrollment (after password verification, before granting access): call the client to register the user with Authy, given an email, phone, and country code. Persist the returned Authy user ID against your users row. Never re-register — re-registration creates duplicate Authy users and strands the old ID.
  • At each subsequent login: call the "send token" endpoint (SMS/voice), then accept a code from a form and call "verify token" with the stored Authy user ID and the submitted code. The verify call returns a boolean-ish result; treat anything other than the documented success value as failure, including null and unexpected shapes.

Persist the Authy user ID, gate everything on it. A user without an authy_id is not enrolled. Route that state to enrollment, not to a verification screen. This single check prevents the most common production bug — calling "verify" with a null ID and getting a confusing error back from the API.

Configuration lives in the bundle config tree, not your code. Read DependencyInjection/Configuration.php for the exact keys (the names for API key and sandbox are defined there — do not assume api_key vs key vs authy_key). Feed them from environment variables via Symfony's config, not by reading getenv() inside a service. The sandbox boolean in particular is a footgun (see Gotchas).

Test against a mocked HTTP boundary, not against Authy. The SDK ultimately makes HTTP calls. Use Symfony's HttpClient mock where the bundle uses it, or authy/php's client seams where it does not, so tests assert the request you would send and the response you handle — not a live round-trip. If the bundle does not expose a seam, that is a strong signal to not depend on it and to build your own wrapper where you control the boundary.

Laravel adaptation — mirror the interface, invert the vendor. If you are porting the pattern:

  • Define TwoFactorProvider with enroll(User): string, sendChallenge(string $twoFactorId): void, verify(string $twoFactorId, string $code): bool, remove(string $twoFactorId): void. The bundle's client surface should map onto this cleanly; anything it does not cover (recovery codes, device trust) is yours regardless.
  • Bind it in a TwoFactorServiceProvider with a driver selected by config/two_factor.php ('driver' => env('TWO_FACTOR_DRIVER', 'twilio_verify')).
  • Ship only a TwilioVerify driver initially. Authy is on Twilio's deprecation path — adding a fresh Authy driver in 2024+ inverts the vendor's direction. Add an Authy driver only if you already have users holding Authy IDs.
  • Use the official twilio/sdk rather than hand-rolled HTTP; you get Verify v2 endpoints and maintained timeout semantics.
  • Route through Laravel's Http client or the SDK's configured timeouts so 2FA latency shows up in the same logs and metrics as the rest of your app.

Sandbox as a first-class toggle. The bundle exposes sandbox mode because Authy has a separate sandbox environment with its own test phone numbers and predictable codes. The pattern is: sandbox on in APP_ENV=local/test, sandbox off everywhere else, and a boot-time assertion that the key matches the environment. Skipping that assertion is how a sandbox key ends up in production and quietly validates test codes for real users.

Fail-open vs. fail-closed is a policy, not a default. Twilio outages happen. Decide explicitly whether a 2FA API failure blocks login (secure, user-hostile) or degrades to password-only (unsafe). Whichever you pick, log it loudly, and implement recovery codes and trusted-device cookies at your layer — the bundle will not provide them.

Gotchas and Tips

Wrong framework is the first gotcha. Despite appearing in PHP package evaluations, there is no Laravel integration. Composer will resolve, but you inherit Symmfony kernel contracts (Bundle subclasses, extension trees, tagged services) that do nothing in Laravel. Any time you spend understanding those is pure cost. The reusable asset is the Authy HTTP contract, and it is small.

Sandbox flag inversion is the classic production incident. The bundle configures sandbox usage as a boolean. Confirm the polarity against the SDK — is sandbox: true "use the sandbox environment" or "enable production"? Getting it wrong either breaks every login (sandbox key against production API) or, worse, uses the sandbox validation path against production user data. Assert the pairing at boot: sandbox mode should imply a specific key prefix or a known test key, and vice versa.

API keys belong in a secret manager, not a bundle config file. Symfony's config/packages/authy.yaml will accept an env var reference — use it. The bundle does not provide secret rotation, redaction in logs, or leak detection. The SDK may log request bodies on debug; verify your logging configuration before shipping, because the Authy API key and per-user IDs are auth-path secrets.

Verification attempts need your own throttle. The bundle wraps "verify token" but not lockout policy. Without an attempt counter on the user row (and a cooldown between "send" calls), you expose a token brute-force surface and pay per-SMS for abuse. Twilio enforces per-account rate limits, not per-user policy — that is yours to build.

Response handling is not boolean. Authy's verify endpoint returns an object; a truthy check is not sufficient. Read the SDK's success field explicitly. Network errors, auth errors, and "invalid token" all come back through the same call — distinguish them so metrics and alerting can tell "user typed the wrong code" (normal) from "our key is broken" (page someone).

Sandbox test numbers expire and drift. The bundle documentation and the Authy sandbox docs diverge over time on which test numbers are valid and what code they accept. If sandbox verification suddenly stops working with no code change, it is the sandbox, not your integration — check the current test-number list before debugging code.

Upstream is effectively unmaintained. One star, zero dependents, single author. That means: no community pressure to keep symfony/* constraints current, no security disclosure channel, no test coverage you can rely on. Pin the version explicitly, run composer audit in CI, and plan to fork or vendor within a release cycle or two. For an authentication path, unreviewed third-party code is a finding, not a convenience — read the wrapper before trusting it.

Authy's lifecycle is the looming gotcha. Twilio has been steering customers from the Authy API toward Twilio Verify (v2). Building new surface on Authy is a bet against the vendor's stated direction. Even if you adopt the pattern, put it behind your provider interface so Authy retirement is a config change, not a rewrite. Confirm Authy's current API status before you commit roadmap to it.

The bundle does not cover the product surface. Enrollment UX, recovery codes, device trust, step-up auth policy, audit evidence for SOC 2, and the "I lost my phone" support flow all live above this package. The bundle is one API call in a much larger journey, and that journey is where the actual effort lives. Do not read "supports SMS/voice and TOTP" as "two-factor done" — it means "two-factor's API call available."

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core