Download the PHP package makraz/verify-email-change-bundle without Composer
On this page you can find all versions of the php package makraz/verify-email-change-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download makraz/verify-email-change-bundle
More information about makraz/verify-email-change-bundle
Files in makraz/verify-email-change-bundle
Package verify-email-change-bundle
Short Description Symfony bundle for secure email address changes with verification
License MIT
Informations about the package verify-email-change-bundle
Makraz Verify Email Change Bundle
A Symfony bundle that provides secure email address change functionality with verification.
Features
- Cryptographically Secure: Uses selector + hashed token pattern to prevent timing attacks
- Configurable Expiration: Set custom lifetimes for verification links
- Built-in Throttling: Prevents abuse with configurable rate limiting
- Flexible: You control email sending, UI, and password verification
- Twig Integration: Built-in Twig functions for checking pending email changes
- Max Verification Attempts: Auto-invalidation after configurable failed attempts
- Dual Verification Mode: Optional confirmation from both old and new email addresses
- CSRF Protection: Built-in helper for cancel endpoint security
- Email Notifications: Built-in
EmailChangeNotifierservice with Twig templates - Translations: Built-in translations for English, French, and Arabic
- API/Headless Support: JSON response factory for SPA and mobile app integration
- OTP Verification: Numeric code verification alternative to signed URLs
- Audit Events: Security-relevant events for logging and compliance
- Pluggable Persistence: Doctrine ORM, PSR-6 Cache, or in-memory adapters
- Well Tested: Comprehensive test suite with 480+ tests
- Event-Driven: Dispatches events for extensibility
- Symfony Flex: Auto-discovery support for seamless installation
Installation
The bundle supports Symfony Flex auto-discovery and will be registered automatically. If you're not using Flex, enable it manually:
Quick Start
Step 1: Update Your User Entity
Your User entity must implement EmailChangeableInterface:
Note:
EmailChangeableInterfaceonly requiresgetId(),getEmail(), andsetEmail().
Step 2: Create the Database Table
Run the following command to create the migration:
Or create the table manually:
Step 3: Configure the Bundle (Optional)
Step 4: Create Your Controller
Displaying Pending Email Changes
The bundle provides Twig functions to easily display pending email change status in your templates.
Using Twig Functions (Recommended)
Available Twig Functions
has_pending_email_change(user): Returnstrueif the user has a pending, non-expired email change requestget_pending_email(user): Returns the pending new email address, ornullif none exists
How It Works
Flow Diagram
API Reference
EmailChangeHelper
generateSignature()
validateTokenAndFetchUser()
confirmEmailChange()
Returns the user's old email address.
cancelEmailChange()
hasPendingEmailChange()
getPendingEmail()
Maintenance
Purging Expired Requests
Expired email change requests remain in the database until purged. Use the built-in console command to clean them up:
Recommended: Add a cron job or Symfony Scheduler task to purge regularly:
Or with Symfony Scheduler:
Events
The bundle dispatches events for extensibility:
EmailChangeInitiatedEvent
Dispatched when an email change request is initiated.
EmailChangeConfirmedEvent
Dispatched when an email change is confirmed.
EmailChangeCancelledEvent
Dispatched when an email change is cancelled.
Security
Dual Verification Mode
For high-security applications, enable dual verification to require confirmation from both the old and new email addresses:
When enabled, generateSignature() returns an EmailChangeDualSignature with two URLs:
Handle old email verification in your controller:
Max Verification Attempts
The bundle automatically invalidates verification links after a configurable number of failed attempts (default: 5):
After exceeding the limit, a TooManyVerificationAttemptsException is thrown and the request is removed.
CSRF Protection for Cancel Endpoint
The bundle provides a CsrfTokenHelper to protect the cancel endpoint:
In your Twig template:
Security Recommendations
- Always require password confirmation before initiating an email change
- Enable dual verification (
require_old_email_confirmation: true) for sensitive applications - Use CSRF protection on the cancel endpoint (see above)
- Send a notification to the old email address when an email change is initiated
- Keep verification link lifetimes short (1 hour is recommended)
- Set up the purge command as a cron job to clean expired requests
- Use HTTPS for all verification URLs (the bundle uses
UrlGeneratorInterface::ABSOLUTE_URL) - Monitor events — listen to
EmailChangeInitiatedEventfor audit logging
Email Notifications
The bundle includes an optional EmailChangeNotifier service that handles sending verification and notification emails using the built-in Twig templates.
Enabling the Notifier
Using the Notifier
Customizing Email Templates
Override the default templates by creating files in your project:
Translations
The bundle includes translations for exception messages and email templates in:
- English (
en) - French (
fr) - Arabic (
ar)
Translations are loaded automatically. To override them, create your own translation files:
API / Headless Mode
For SPA, mobile apps, and API-first applications, use the EmailChangeResponseFactory to generate consistent JSON responses:
OTP Verification
For mobile apps and API flows, use numeric OTP codes instead of signed URL links:
Audit Events
The EmailChangeAuditEvent provides security-relevant information for logging:
Available actions: initiated, verified, confirmed, cancelled, failed_verification, max_attempts_exceeded, expired_access, old_email_confirmed.
Storage Backends
The bundle supports multiple storage backends. The default is database (Doctrine ORM).
Database (default)
Uses Doctrine ORM to persist email change requests. Requires doctrine/orm and doctrine/doctrine-bundle.
Stateless
Uses a PSR-6 cache pool (Redis, Memcached, filesystem, etc.) instead of a database. Ideal for applications that don't use Doctrine ORM or want faster lookups. Requires a CacheItemPoolInterface service and a user provider callback.
In-Memory (Testing)
The InMemoryEmailChangeRequestRepository is intended for testing. Register it as a service manually:
Custom Adapter
Implement EmailChangeRequestRepositoryInterface and point the configuration to your service:
When storage_service is set, it takes precedence over the storage option.
Configuration Reference
Exception Reference
All exceptions implement VerifyEmailChangeExceptionInterface.
| Exception | When | Message |
|---|---|---|
SameEmailException |
New email equals current email | "The new email address is identical to the current one." |
EmailAlreadyInUseException |
Email taken by another user | "This email address is already in use." |
TooManyEmailChangeRequestsException |
Request too soon after previous | "You have already requested an email change..." |
TooManyVerificationAttemptsException |
Max attempts exceeded | "Too many verification attempts (max: N)." |
ExpiredEmailChangeRequestException |
Verification link expired | "The email change link has expired." |
InvalidEmailChangeRequestException |
Invalid or tampered link | Varies |
Upgrading
From v1.4 to v2.0
Breaking changes:
EmailChangeInterfacehas been removed. UseEmailChangeableInterfaceinstead.Persistence\EmailChangeRequestRepositoryhas been removed. UsePersistence\Doctrine\DoctrineEmailChangeRequestRepositoryinstead.persistenceconfig option renamed tostorage(values:database,stateless).persistence_serviceconfig option renamed tostorage_service.
New features:
EmailChangeResponseFactoryfor JSON/API responses- OTP-based email verification (
OtpEmailChangeHelper) EmailChangeAuditEventfor security logging
Migration:
From v1.3 to v1.4
New features (non-breaking):
- Pluggable persistence adapters: Doctrine ORM, PSR-6 Cache, In-Memory
DoctrineEmailChangeRequestRepositorymoved toPersistence\Doctrinenamespacestorageandstorage_serviceconfiguration optionsEmailChangeRequestRepositoryis now deprecated (useDoctrineEmailChangeRequestRepository)
No database migration required.
From v1.2 to v1.3
New features (non-breaking):
- Translation support for English, French, and Arabic
- Default Twig email templates (
@MakrazVerifyEmailChange/email/...) - Optional
EmailChangeNotifierservice for sending emails
No database migration required. Enable the notifier in configuration if desired.
From v1.1 to v1.2
New features (non-breaking):
- Max verification attempts protection — enabled by default (5 attempts). Configure with
max_attempts. - Dual verification mode — opt-in with
require_old_email_confirmation: true. - CSRF token helper — optional service for cancel endpoint protection.
Database migration required: The email_change_request table has new columns:
Or use Doctrine migrations:
From v1.0 to v1.1
Interface change (non-breaking):
EmailChangeInterfaceis now deprecated. Migrate toEmailChangeableInterfacewhich only requiresgetId(),getEmail(), andsetEmail().- Classes implementing
EmailChangeInterfacecontinue to work without changes.
Testing
License
This bundle is released under the MIT License. See the LICENSE file for details.
Support
For issues, questions, or contributions, please visit: https://github.com/makraz/verify-email-change-bundle
All versions of verify-email-change-bundle with dependencies
symfony/framework-bundle Version ^6.4|^7.0|^8.0
symfony/security-core Version ^6.4|^7.0|^8.0
symfony/http-foundation Version ^6.4|^7.0|^8.0
symfony/routing Version ^6.4|^7.0|^8.0
symfony/event-dispatcher Version ^6.4|^7.0|^8.0
symfony/translation Version ^6.4|^7.0|^8.0
twig/twig Version ^3.0