happyr/google-site-authenticator-bundle
Symfony bundle for adding Google Authenticator two-factor authentication to login flows. It generates and verifies time-based six-digit codes, integrates with Symfony security, and gives older Symfony apps a simple way to add TOTP-based 2FA without external services.
Architecture fit — poor as a package, good as a pattern. This remains a Symfony bundle (Happyr\GoogleSiteAuthenticatorBundle) whose value proposition is a thin wrapper over google/apiclient: it holds per-"site" credentials, builds a Google_Client, calls setSubject() to impersonate a Workspace user, and returns an authenticated client. Its integration surface is a Symfony Extension/DependencyInjection bundle class and YAML config tree — concepts that do not exist in Laravel's container or bootstrap lifecycle. There is no service provider, no facade, no publishable Laravel config, and Composer will not auto-register anything useful to a Laravel app. Release 1.2.0 does not change this: adding Symfony 5.0 support and removing Symfony 3.x support moves the package along the Symfony support matrix, which is orthogonal to Laravel. The bundle is now nominally compatible with a framework version released in late 2019 and remains two majors behind current Symfony — while still exposing no Laravel entry point of any kind.
What it actually delivers is ~50–100 lines of glue. The authenticating work is done by google/apiclient (Google\Client::setAuthConfig + setScopes + setSubject + fetchAccessTokenWithAssertion). The bundle's contribution is config aggregation and a container service. A TPM should treat this as a reference implementation to read, not a dependency to install. 1.2.0 adds no functionality; it is a constraint-range edit.
Integration feasibility — low as-is, unchanged by 1.2.0. Installing it into Laravel still drags in Symfony HttpKernel/DependencyInjection/Config components and a bundle class Laravel will never boot. Symfony 5 support does not reduce that footprint; if anything it confirms the package has no intention of decoupling from the Symfony runtime. The economically correct path remains a native reimplementation.
Technical risk — elevated, with one new signal.
google/apiclient or the Guzzle/firebase/php-jwt chain.Key questions to answer before committing.
.env?Recommended: do not install the bundle. Port the behaviour into a small first-party Laravel package. One config/google.php (multiple named connections: analytics, workspace, etc., each with credentials_path, subject, scopes), one GoogleClientFactory singleton, one optional Google facade. Roughly a day of work, no Symfony dependency, fully owned and testable. 1.2.0 does not move this estimate in either direction.
Stack fit and compatibility. Target PHP 8.2+, Laravel 10+, google/apiclient: ^2.x, credentials loaded from a filesystem path resolved at runtime from a secret store — never committed. Cache access tokens (~1h TTL) in the Laravel cache keyed by connection:subject:scope-hash to avoid re-signing JWTs per request. If you cannot use WIF, wrap the key in a CredentialsRepository interface so the backing store can change without touching call sites.
Migration path. Still likely a build, not a migration. If Symfony code exists, check its Symfony major version first: 1.2.0 drops Symfony 3.x, so a legacy consumer must either be upgraded to Symfony 4/5 before adopting, or pinned to 1.1.x. Otherwise: inventory config keys (client_id, service_account_email, private_key/key path, subject, scopes), map them 1:1 to the Laravel config, and run both in parallel against a read-only API (a Sheets read or Drive listing) to confirm token identity matches (tokeninfo → assert the impersonated email).
Sequencing.
Rejected alternatives, explicitly. Forking the bundle to add a Laravel service provider costs more than the rewrite and leaves you maintaining a two-framework hybrid; 1.2.0's Symfony-only direction makes that fork less attractive, not more. composer require happyr/google-site-authenticator-bundle into Laravel should be rejected on the maintenance and compatibility findings above — a Symfony 5 constraint bump does not constitute Laravel readiness.
Maintenance — we own it either way. Adopting the bundle does not buy support; it buys an extra low-activity dependency to patch. Owning ~100 lines of factory code is strictly cheaper than owning a vendored Symfony bundle plus its Symfony transitive dependencies. 1.2.0 is a reminder that releases here track Symfony's lifecycle, not ours — budget a recurring review of google/apiclient and firebase/php-jwt advisories regardless.
Support and governance. No maintainer SLA, no security response, and the 1.2.0 change shipped as a minor despite removing a supported framework version — treat upgrade notes as unreliable and read diffs. DWD requires a Workspace super admin and re-approval whenever scopes change; that is a recurring cross-team dependency. Every added scope should require a PR-style justification; scope creep here is silent privilege expansion across the entire tenant. Keep an inventory of which impersonated subjects each service touches, because audit will ask.
Scaling and quotas. All impersonation traffic draws on one GCP project's per-API quotas, which is usually the binding constraint long before Laravel throughput is. Token caching per subject is mandatory; without it you will sign a JWT per request and can trip Google's assertion rate behaviour under load. If you impersonate per-tenant users, expect quota and cache-key cardinality to grow with the tenant count, not with request volume.
Failure modes to instrument for.
invalid_grant / unauthorized_client — clock skew, revoked or rotated key, subject not authorized for the client ID, or an admin console scope mismatch. These present identically; log the full Google error body.Ramp-up. The code is trivial; the environment is not. Expect the real onboarding cost to be Google Cloud IAM (service accounts, key or WIF setup) plus the Workspace Admin console DWD screen — knowledge concentrated in one or two people. Document the DWD setup and rotation runbook as a deliverable, not an afterthought, because the original bundle's documentation is the only artifact and it describes a Symfony setup no one on a Laravel team will recognise.
Verdict. Unchanged by 1.2.0. Low code value, high operational tail; the release only realigns Symfony constraints and introduces a minor-version breaking change, neither of which addresses Laravel fit, PHP 8.x support, maintenance credibility, or the credential-model risk. Use it as a specification for a small in-house Laravel integration; do not add it to composer.json.
How can I help you explore Laravel packages today?