Installation
composer require symfonycasts/reset-password-bundle
Add to config/bundles.php:
Symfonycasts\ResetPasswordBundle\ResetPasswordBundle::class => ['all' => true],
Configure the Bundle
Update .env with:
RESET_PASSWORD_SECRET=your-strong-secret-key-here
RESET_PASSWORD_EXPIRATION_MINUTES=60
First Use Case: Basic Password Reset Flow
ForgotPasswordController with a form to submit emails.
use Symfonycasts\ResetPasswordBundle\Controller\ForgotPasswordController;
templates/ResetPasswordBundle/email/reset_password.html.twig).ResetPasswordController to handle token validation and password updates.Key Files to Review
config/packages/reset_password.yaml (default config)templates/ResetPasswordBundle/ (customize emails/emails)src/Entity/User.php (ensure resetPasswordToken and resetPasswordTokenExpiresAt fields exist).User Requests Reset
ForgotPasswordController::send()./reset-password?token=XYZ123&email=user@example.com.Token Validation
ResetPasswordController::validateToken() to check token expiry/validity.use Symfonycasts\ResetPasswordBundle\Security\ResetPasswordVoter;
// In security.yaml
access_control:
- { path: ^/reset-password, roles: public, requirements: "reset_password.token_valid" }
Password Update
ResetPasswordController::reset().Custom User Model
Extend the bundle’s UserInterface:
use Symfonycasts\ResetPasswordBundle\Model\UserInterface as ResetPasswordUserInterface;
class User implements ResetPasswordUserInterface {
// ...
}
Email Customization
Override templates in templates/ResetPasswordBundle/email/ or configure the sender in reset_password.yaml:
reset_password:
email:
from: no-reply@yourdomain.com
subject: 'Reset Your Password'
Testing
Use the bundle’s ResetPasswordTestTrait for unit/integration tests:
use Symfonycasts\ResetPasswordBundle\Tests\ResetPasswordTestTrait;
class ResetPasswordTest extends TestCase {
use ResetPasswordTestTrait;
}
API Integration For APIs, bypass Twig emails and use a custom mailer service:
# config/services.yaml
Symfonycasts\ResetPasswordBundle\Mailer\MailerInterface: '@your.custom.mailer'
Token Expiry
RESET_PASSWORD_EXPIRATION_MINUTES (60 mins).resetPasswordTokenExpiresAt in the user model.Token Reuse
ResetPasswordController::validateToken().Database Schema
User model has:
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $resetPasswordToken;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $resetPasswordTokenExpiresAt;
ResetPasswordException.Email Delivery
RESET_PASSWORD_SECRET is set.from email in reset_password.yaml is valid.Log Tokens Enable debug mode to log token generation/validation:
reset_password:
debug: true
Check logs for RESET_PASSWORD_DEBUG entries.
Token Validation Errors Common errors:
TokenNotFoundException: Token not found in DB or expired.TokenExpiredException: Token older than expiresAt.ForgotPasswordController::send().CSRF Protection
The reset form includes CSRF by default. Disable in reset_password.yaml if using API tokens:
reset_password:
csrf_protection: false
Custom Token Storage
Override token storage logic by implementing Symfonycasts\ResetPasswordBundle\TokenStorage\TokenStorageInterface.
Token Generation
Extend Symfonycasts\ResetPasswordBundle\TokenGenerator\TokenGeneratorInterface for custom token formats (e.g., UUIDs).
Password Validation
Add custom rules in ResetPasswordController::reset():
$validator = $this->validator;
$errors = $validator->validate($password, [
new Assert\Length(['min' => 10]),
new Custom\PasswordStrength(),
]);
Event Listeners Listen for token generation/validation events:
use Symfonycasts\ResetPasswordBundle\Event\ResetPasswordEvents;
// In services.yaml
Symfony\Component\EventDispatcher\EventSubscriberInterface:
tags: ['kernel.event_subscriber']
Example subscriber:
class ResetPasswordSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
ResetPasswordEvents::TOKEN_GENERATED => 'onTokenGenerated',
];
}
public function onTokenGenerated(TokenGeneratedEvent $event) {
// Log or modify the token
}
}
Rate Limiting
Prevent brute-force attacks by adding rate limiting to ForgotPasswordController:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Firewall\RateLimiter;
// In security.yaml
access_control:
- { path: ^/forgot-password, roles: public, requires_channel: https }
How can I help you explore Laravel packages today?