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

Symfony Bundle Laravel Package

betterauth/symfony-bundle

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Scope correction first: despite the framing as a "Laravel/PHP package," betterauth/symfony-bundle is a Symfony bundle (Symfony ^6.4 | ^7.0 | ^8.0). A sibling Laravel package exists and shares the betterauth/multimodal-php core (the changelog references "synchronized core between Symfony and Laravel packages"), but this artifact cannot be installed into a Laravel application. If the roadmap target is Laravel, this repo is a reference implementation at best, and the decision should be re-run against the Laravel sibling — which carries the same maintainer and maturity risk. Everything below assumes a Symfony target.

Architecture fit. The bundle sits in the right layer for a Symfony shop: it plugs into the Security component, offers three explicit operating modes (API / session / hybrid), and — most importantly — is application-owned persistence. The User entity and schema stay in our codebase, not the vendor's. That is the single most valuable property here: it makes the package replaceable and keeps PII inside our data boundary. On the crypto side the choices are defensible and above the norm for a 0.0.x package: PASETO v4.local (avoids the JWT algorithm-confusion family of bugs), refresh rotation with replaced_by stored hashed, session tokens stored as SHA-256 hashes, TOTP seeds AES-256-GCM encrypted at rest, callbackUrl validated against a trusted frontend origin, and login/TOTP rate limiting applied before password verification. The v0.0.20 release notes read like a real security review, which is a positive signal about maintainer intent.

Integration feasibility. Mechanically easy: composer require, better-auth:install, better-auth:setup-features --preset=full --with-controllers --migrate. The command surface is unusually broad (mode switching, config generation, feature presets, entity field extension, session/token cleanup). CI covers PostgreSQL, SQLite, MySQL, and MariaDB, and the project runs PHPStan 2.x at level 7 with a daily security audit job. Feasibility is therefore high if the platform constraints are already satisfied.

Technical risk. This is an authentication package — maximum blast radius — with 4 stars, 0 dependents, a single maintainer, and a 0.0.x version line. There is no evidence of third-party production usage, which means we would be an early adopter on the highest-risk surface in the application. Four specific risks:

  1. Pre-1.0 API churn. The README of v0.0.2 explicitly warned "API may change before v1.0.0"; the version is still 0.0.20.
  2. Self-migrating repositories. Legacy plaintext sessions and TOTP seeds are rehashed/re-encrypted in place on first read. This is elegant (no forced logout, no build-time migration) but it introduces implicit writes on read paths — a latency and lock-contention surprise, and an opaque mechanism for anyone who hasn't read the changelog.
  3. Irreversible secret coupling. BETTER_AUTH_SECRET rotation renders existing encrypted TOTP seeds unreadable. That is a permanent operational constraint on key management, and it converts a routine security hygiene task into a user-facing break-glass event.
  4. Dependency chain. Core logic lives in betterauth/multimodal-php, a small package from the same author; the PHP floor is 8.4, which excludes most organizations today.

Key questions to resolve before committing:

  • Is the target platform Symfony or Laravel? If Laravel, this package is out of scope.
  • Can we meet PHP 8.4 and Doctrine ORM 3 / Migrations 4 now, or is that a 2–3 quarter platform dependency?
  • Who owns the User entity schema, and are we prepared to own migrations for auth tables indefinitely?
  • What is our secret-management story given rotation breaks TOTP enrollment?
  • Do we accept implicit on-read data migration, or do we require an explicit migration?
  • What is the exit plan if the maintainer stops shipping — can we fork multimodal-php plus this bundle and support it internally?
  • Has anyone on the team shipped PASETO? If not, our incident-response runbooks will need new material.

Integration Approach

Stack fit. Fits a modern Symfony service: Symfony 6.4/7/8, Doctrine ORM 3, Doctrine Migrations 4, API Platform 4, PHP 8.4. The four-database CI matrix maps cleanly onto typical managed-Postgres or managed-MySQL estates. The API/session/hybrid mode switch is genuinely useful for a TPM: it lets one team serve a first-party web session app and a token-based API from a single auth substrate, and it lets us change our mind later via better-auth:switch-mode rather than a rewrite.

Migration path. For a greenfield Symfony service, integration is days, not weeks. For an existing app the realistic paths are:

  • From FOSUserBundle or hand-rolled auth: best case. Application-owned persistence means we keep the existing users table and bolt on the auth tables; the migration guide (docs/14) plus better-auth:user-fields covers entity extension.
  • From LexikJWT / JWT-based services: expect a credential break. Token format changes from JWT to PASETO and there is no dual-verify shim documented. Plan for forced re-authentication or a dual-issuance window with a custom token extractor, and price that in.
  • Within this package's own version line: v0.0.20's on-read rehash/re-encrypt means upgrades are transparent — but only if BETTER_AUTH_SECRET is unchanged.

Compatibility. Two constraints are non-negotiable and should be validated in a spike, not assumed: PHP 8.4, and Doctrine ORM 3. The Symfony 8 / API Platform 4 combination is asserted in the README but is the least battle-tested corner given the package's youth — verify against our actual Symfony minor. Also confirm the QueryParameterTokenExtractor stays disabled (it is off by default); any temptation to enable it for convenience should be rejected.

Sequencing I would recommend:

  1. Timeboxed spike (1 sprint) in a disposable Symfony 8.4/Doctrine 3 app: full preset install, all four auth flows exercised, plus a load probe against the refresh-rotation path.
  2. Security review gate — internal AppSec reads docs/11 and the v0.0.20 diff. This is mandatory for any auth dependency at 4 stars.
  3. Pin exactly (v0.0.20, not a caret range) and record the resolved multimodal-php commit. Vendor the lockfile.
  4. Non-critical surface first — an internal tool or a low-traffic API consumer — before customer-facing login.
  5. Progressive rollout behind a feature flag with a fallback to the incumbent auth path for one release cycle.
  6. Only then retire the old auth stack.

Operational Impact

Maintenance. Assume meaningful upgrade cadence and occasional breaking config changes — the 0.0.9 → 0.0.20 history includes repeated fixes to secret-length validation against %env()% placeholders, a Google OAuth verified_email field change breaking account linking, and invalid route-attribute registrations. None of these are unusual for a young package, but each is a reminder that we will be doing the hardening. Budget roughly 10–15% of one backend engineer's time in steady state, spiking around releases. Pin versions, subscribe to releases, and treat composer update on this dependency as a change requiring review — not routine maintenance.

Support. MIT, no commercial backing, no SLA, no published security policy beyond the daily audit job. The docs corpus is genuinely good (14+ focused guides including security, testing, migration, customization), which materially lowers support load. But escalation for a production auth outage ends at a GitHub issue. Mitigation: budget for an internal fork. Because persistence is application-owned and the core is a separate Composer package, a fork is survivable — a decisive advantage over a hosted auth vendor.

Scaling. API mode is stateless PASETO verification and scales horizontally with the app tier; that is the right default for high-throughput services. Session and hybrid modes add a database write per rotation — the sessions and refresh-token tables become hot, write-heavy tables. Two concrete actions: index the token-hash lookup column (hash lookups are not free index scans by default), and schedule better-auth:cleanup:sessions and better-auth:cleanup:tokens as cron jobs from day one. Without cleanup, these tables grow unbounded with expired rows and the rotation queries degrade.

Failure modes to instrument and rehearse:

  • Secret rotation → all stored TOTP seeds become undecryptable; 2FA users are locked out until re-enrollment. This belongs in the DR runbook, not in a wiki.
  • Rate limiter keyed on IP+email (5 attempts / 15 min) → shared NAT, corporate proxies, and mobile carrier IPs can lock out legitimate users. Tune or front with a WAF; add a distinct alert for "rate-limit rejections spiking."
  • callbackUrl origin allowlist misconfiguration → magic-link and email-verification endpoints return 400, silently breaking passwordless onboarding. Assert the configured frontend origin in a smoke test.
  • On-read legacy migration → first access after deploy performs a hash/encrypt write. Anticipate a latency bump and row-level lock contention on the first traffic wave; consider a warm-up script rather than relying on organic traffic.
  • Cookie defaults (secure, httpOnly, sameSite=lax) → correct for production, will break local HTTP development and any cross-site frontend on a different registrable domain. Document the dev override before the first developer hits it.
  • Secret length validated only at runtime → a misconfigured environment fails at token issuance, not at container boot. Add a startup health check.

Ramp-up. Two distinct learning curves. First, the bundle's command-and-config surface — mitigated by the presets and the install wizard, roughly 1–2 days for a Symfony-fluent engineer. Second, PASETO and refresh-rotation semantics, which most teams have not operated; add 3–5 days and make sure on-call has a written runbook covering token validation failures, rotation anomalies, and 2FA lockout recovery. Realistic estimate: 2–3 weeks of one senior engineer to reach confident production ownership, plus AppSec review time. That is competitive against building OAuth + TOTP + rotation + passwordless from scratch — which is the actual build-vs-buy comparison — but only if the team genuinely accepts the ownership burden above.

TPM recommendation: promising, well-documented, security-conscious, and architecturally respectful of application data ownership — but at 0.0.20 with 4 stars and 0 dependents, it is not yet a default choice for customer-facing authentication. Approve for an internal or low-blast-radius service, gated on the PHP 8.4 platform check, a pinned version, an AppSec review, and a documented fork/exit plan. Re-evaluate for primary auth once it reaches a 1.0 line or accumulates independent production adopters.

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.
encore2/laravel-admin2
cboxdk/laravel-console-kit
shapecode/doctrine-dbal-datetimeutc
gilads-otiannoh254/inertia-protocol
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
adachsoft/cli-process-tester
adachsoft/changelog-linter
adachsoft/collection
adachsoft/php-code-style
adachsoft/api-version-bundle
cgv/localized-resource