Weave Code
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

Multimodal Php Laravel Package

betterauth/multimodal-php

View on GitHub
Deep Wiki
Context7
0.1.0

Security

Hardening pass from the 2026-07-22 security audit. All changes are test-backed.

  • Tokens hashed at rest — magic-link, password-reset, email-verification, OAuth authorization codes and guest-session tokens are now SHA-256 hashed before storage and looked up by hash (matching refresh/session tokens). OAuth client_secret is hashed too (OAuthClient::hashSecret() / verifySecret()). Breaking: existing plaintext values of these ephemeral tokens become invalid on deploy (no re-hash migration — see MIGRATION note).
  • Account-takeover fixes — OAuth providers (GitHub/Microsoft/Twitter) now report the real per-address emailVerified instead of a hard-coded true; auto-linking to an existing account still requires a verified email. Password reset/change now revokes all sessions and refresh tokens.
  • Mass-assignment / SQL-structure injection — PDO repositories restrict writable columns to an explicit allow-list (ColumnFilterTrait).
  • OIDC — PKCE (S256) is mandatory for public clients; refresh tokens are bound to the issuing client; a request nonce is stored and echoed in the id_token; and id_tokens can be signed as RS256 JWTs with a published JWKS (opt-in via a RsaJwt signer — OidcProvider::getJwks()).
  • TOTP — anti-replay (a code's time-step cannot be reused) and a rate limiter is now required (allowNoRateLimit: true to opt out).
  • 2FAAuthManager::completeTwoFactorLogin() now verifies the TOTP code before creating a session. Breaking: its signature now requires TotpProvider $totpProvider, string $code.
  • Rate limiter — refuses to run without a shared PSR-6 cache unless allowInMemoryFallback: true (no more silent no-op). Breaking for new RateLimiter() with no cache.
  • Misc — email header-injection guard + template escaping in PdoEmailSender; refresh-token reuse detection revokes the family; unified strong-password policy on reset; timing-equalization dummy verify derived from configured Argon2id cost; opportunistic rehash in token mode; token fragments/PII removed from logs; Crypto::decrypt(..., strict: true) anti-downgrade mode; SecurityMonitor/ThreatDetector now persist extra fields in metadata.
0.0.3

Added

  • Opaque session id, decoupled from the secret token. A session now carries an id (generated with Crypto::randomToken(16), distinct from the token) so it can be listed and revoked by a non-secret handle. Session::getId()/setId(), SimpleSession::fromArray()/toArray() (now carry id), and SessionService::getById()/deleteById() were added.
  • SessionAuthManager::revokeSession($userId, $sessionId) now resolves the session by its opaque id instead of the token, and resolves via findById() (not validate()) so an expired session stays revocable. Ownership and missing-session behaviour are unchanged.
  • Optional TOTP verification rate limiting. TotpProvider accepts an optional RateLimiterInterface; verify()/verifyAndEnable() throttle attempts (keyed on totp:verify:{userId}) when one is supplied.
  • AuthManager::verifyCredentials() + completeSignIn(). Credential verification and auth-result creation are now separate single-source primitives, so a caller can gate (e.g. require 2FA) between verifying the password and creating the session/tokens without verifying the password twice.
  • PdoTotpStorage now persists the TOTP algorithm, so the SHA-1 → SHA-256 migration state survives storage round-trips (it was previously always read back as SHA-1).

Changed (breaking — PDO storage / interface)

  • SessionRepositoryInterface gains two methods: findById(string $id): ?Session and deleteById(string $id): bool. Any custom implementation must add them.
  • PdoSessionRepository::createTable() now creates an id VARCHAR(64) NOT NULL column with a UNIQUE constraint. Since the DDL is CREATE TABLE IF NOT EXISTS, existing PDO deployments are not migrated automatically — add the column manually, e.g. ALTER TABLE sessions ADD COLUMN id VARCHAR(64) NULL, ADD UNIQUE KEY uniq_id (id); then backfill ids for current rows. (Doctrine/Symfony migration is handled separately.)

Fixed

  • SessionAuthManager::signUp() writes the hashed password under the canonical password_hash key (was password), so user creation through PdoUserRepository no longer persists a NULL password.
  • TOTP requires2fa: removed a dead 24-hour branch (DateInterval::$h is always < 24) so the elapsed-time check is correct.
  • Magic-link session mode no longer returns the session token as a bogus refresh_token; it returns token_type: session instead.
  • The bundled PDO storage is now consistently MySQL/MariaDB. Replaced SQLite-only INTEGER PRIMARY KEY AUTOINCREMENT with INT AUTO_INCREMENT PRIMARY KEY in PdoTotpStorage and PdoEmailVerificationStorage, and the SQLite/PostgreSQL ON CONFLICT … DO UPDATE upsert in PdoTotpStorage::store() with MySQL ON DUPLICATE KEY UPDATE. Previously the DDL mixed dialects and ran cleanly on no single engine. For SQLite/PostgreSQL, supply your own storage implementation.
0.0.2

Security

  • TOTP backup codes are now verified correctly. PdoTotpStorage::useBackupCode() compared the submitted code against stored hashes with in_array(), which always failed — backup codes (and 2FA recovery/disable) were effectively unusable. They are now verified with password_verify().
  • TOTP secret encryption at rest. PdoTotpStorage accepts an optional master key (3rd constructor argument) and encrypts the TOTP seed with AES-256-GCM. A DB read no longer exposes usable TOTP secrets.
  • Session and refresh tokens are hashed at rest. PdoSessionRepository and PdoRefreshTokenRepository store sha256(token) (and replaced_by), look up by hash, and re-inject the plaintext token on the returned entity. A DB read no longer yields usable tokens.
  • SQL injection hardening. PdoUserRepository::findByProvider() now validates the provider name against an allowlist before interpolating it into the JSON_EXTRACT path.
  • OAuth state can no longer be bypassed. Once an expected state is supplied, OAuthManager::handleCallback() requires a matching state (an attacker can no longer skip CSRF verification by omitting the parameter).
  • PKCE plain removed. Only S256 is accepted in AuthorizationCode::verifyChallenge() and advertised in the OIDC discovery document.

Added

  • Crypto::encrypt() / Crypto::decrypt() — authenticated encryption (AES-256-GCM) with an enc:v1: version marker; decrypt() returns unmarked legacy values unchanged for safe migration.

Migration notes

  • Token hashing changes the at-rest storage format. Lookups hash the incoming token, so the public API is unchanged. When integrating the PDO storage in an existing deployment, hash existing token values in place (token = sha256(token)) to preserve active sessions.
  • TOTP secret encryption is opt-in: pass the app secret as the 3rd argument of PdoTotpStorage. Existing plaintext secrets keep working (legacy passthrough) and are encrypted on their next store(). Keep the master key stable — rotating it makes existing encrypted secrets unreadable.
0.0.1
  • Initial release.
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle