Download the PHP package nowo-tech/password-policy-bundle without Composer

On this page you can find all versions of the php package nowo-tech/password-policy-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package password-policy-bundle

Password Policy Bundle

CI Packagist Version Packagist Downloads

⭐ Found this useful? Give it a star on GitHub! It helps us maintain and improve the project.

Symfony bundle for password policy enforcements including password history, expiry, and validation.

This bundle is FrankenPHP worker mode friendly.

Table of contents

Features

FrankenPHP: The demo uses a single PHP service (FrankenPHP, no nginx). With APP_ENV=dev (default), the Docker entrypoint swaps in Caddyfile.dev — php_server without workers for comfortable local development. The baked-in production Caddyfile can use php_server { worker … }; see docs/DEMO-FRANKENPHP.md. Access the demo at http://localhost:PORT (see demo/README.md and .env).

Installation

Then, register the bundle in your config/bundles.php:

Requirements

Optional dependencies:

Configuration

Step 1: Implement Required Interfaces

  1. Implement Nowo\PasswordPolicyBundle\Model\HasPasswordPolicyInterface in the entities that you want to support password policies.

  2. Implement Nowo\PasswordPolicyBundle\Model\PasswordHistoryInterface in a new entity that will hold the password history records.

Step 2: Add Validation Constraint

Add @PasswordPolicy() validation rules to your $plainPassword field:

Step 3: Configure Bundle

You must define at least one entity under nowo_password_policy.entities (each needs reset_password_route_name, etc.). The Symfony Config tree marks entities as required; without it, the container will not compile.

Default values exist for many keys (password field names, expiry_days, expiry_listener.redirect_on_expiry, logging, cache flags — see Configuration.php and docs/CONFIGURATION.md), but not for the entity list itself.

Important: A config/packages/nowo_password_policy.yaml file is optional only in the sense that Flex may create it for you — you still need the entities section with your App\Entity\… classes.

Symfony Flex Recipe (Automatic - Recommended)

If the bundle is installed via Symfony Flex (from Packagist), the configuration file will be created automatically during composer require:

You don't need to do anything else - the file is created automatically with helpful comments.

Note: Flex Recipes only work when the bundle is published in the official Symfony Flex repository (Packagist). If you're using a private bundle or installing from a Git repository, Flex Recipes won't work and you'll need to create the configuration file manually.

Manual Configuration

If you're installing manually or want to customize the configuration, create config/packages/nowo_password_policy.yaml:

Configure how Password policy will behave on every entity:

Configuration Options

Option Type Default Description
password_field string 'password' The password property name in the entity
password_history_field string 'passwordHistory' The password history property name in the entity
passwords_to_remember int 3 How many previous passwords to track
expiry_days int 90 Number of days before password expires
reset_password_route_name string required Fallback route name for password reset (required)
reset_password_route_pattern string | null null Optional pattern to pick the reset route from the router (first match, alphabetical order); see CONFIGURATION.md
notified_routes array [] Route names or patterns where expiry is enforced. Keep the list minimal; see route configuration recommendations
excluded_notified_routes array [] Routes excluded from expiry handling (login, logout, reset, APIs). See CONFIGURATION.md
detect_password_extensions bool false Detect trivial extensions (e.g. password123 from password). Each check runs password verification against history; keep disabled unless required (see Password History)
extension_min_length int 4 Minimum length of base password to consider for extension detection
expiry_listener.priority int 0 Priority of the expiry listener
expiry_listener.redirect_on_expiry bool false If true, redirect to the resolved reset route when password is expired
expiry_listener.flash_strategy string 'always' How often to add the expiry flash: always, once_per_session, interval, never
expiry_listener.flash_interval_minutes int 30 Minutes between flashes when flash_strategy is interval
expiry_listener.flash_throttle_storage string 'session' session or cache (Redis/Memcached) for multi-pod / FrankenPHP
expiry_listener.flash_throttle_cache_service string 'cache.app' Cache pool service id when using cache storage
expiry_listener.lock_route string - Deprecated — use redirect_on_expiry + reset_password_route_name
expiry_listener.error_msg.text array or string keys nowo_password_policy.title / .message (defaults) Flash title/message (supports translation keys)
expiry_listener.error_msg.type string 'error' Flash message type
enable_cache bool false Cache expiry checks (needs cache.app)
cache_ttl int 3600 TTL in seconds when enable_cache is true

How It Works

Password History

The bundle uses Doctrine lifecycle events to create password history and set last password change on the target entities. When a password is changed:

  1. The old password is stored in the password history
  2. The passwordChangedAt timestamp is updated
  3. Only the configured number of previous passwords are kept

Password Expiry

Expiry works by checking the last password change on notified routes (each entry can be a literal route name, a glob, or a regex; see route configuration recommendations.

  1. On each main request to a locked (notified) route, the bundle checks if the password has expired
  2. If expired, a flash message is shown (with optional translation via expiry_listener.error_msg)
  3. If expiry_listener.redirect_on_expiry is true, the user is redirected to the resolved reset route (reset_password_route_pattern if configured, otherwise reset_password_route_name; not the deprecated lock_route)
  4. If redirect_on_expiry is false, only the flash is shown — the request continues (adjust routes/notifications to match your UX)

Important: The library uses Doctrine lifecycle events (onFlush) to create password history and set last password change. You must be aware that any entity changes after the recalculation will not be persisted to the database.

Password Reuse and Extension Detection

The bundle prevents users from reusing old passwords and can optionally detect password extensions:

  1. Exact Match Detection: Checks if the new password exactly matches any password in history

    • Uses password_verify() for reliable hash comparison
    • Works with bcrypt, argon2, and Symfony's password hashers
    • Always enabled by default
  2. Extension Detection (optional): Detects when a new password is an extension of an old password
    • Detects common patterns: adding numbers (0-999) or special characters (!, @, #, $, %) to the beginning or end
    • Example: If user had "password" and tries "password123", it will be detected and rejected
    • Can be enabled per entity in YAML configuration or per field using constraint attributes
    • Configurable minimum length for the base password (default: 4 characters)

How Extension Detection Works:

Usage Examples

Basic Entity Implementation

Password History Entity

Demo Projects

The bundle includes a complete demo project for Symfony 8. It includes:

Screenshots (Symfony 8 demo)

Login page with demo credentials and password status indicators:

Home page after login: password expiry testing info and quick access to use cases and user management.

Users management: list with password status (Active, Expiring Soon, Expired), password history and actions.

Running the Demo

The make up-* command automatically:

Access the demo at http://localhost:8003 (port from demo/symfony8/.env).

Testing Password Expiry

  1. Login: Access / (root) and authenticate with [email protected] / expired123
  2. Navigate: After login, you'll be redirected to /home - the password expiry listener will trigger
  3. See Warning: A flash message will appear indicating the password has expired
  4. Test Other Users: Try logging in with other demo users to see different expiry states
  5. CRUD Access: The user management CRUD (/user/*) requires authentication - you'll be redirected to login if not authenticated

Use the CRUD interface to:

For more information, see demo/README.md.

Development

Using Docker (Recommended)

Note: All commands execute inside the Docker container. The Makefile automatically handles container management and command execution.

Code Quality

The bundle uses PHP-CS-Fixer to enforce code style (PSR-12).

CI/CD

The bundle uses GitHub Actions for continuous integration:

See .github/workflows/ci.yml for details.

Documentation

Additional documentation

The bundle includes comprehensive test coverage. All tests are located in the tests/ directory.

Important: Tests must be run inside the Docker container. Use the Makefile commands:

Note: The make test and make test-coverage commands automatically execute the tests inside the PHP container created by docker-compose.yml. Do not run composer test or composer test-coverage directly on your host machine - always use the Makefile commands.

Tests and coverage

License

The MIT License (MIT). Please see LICENSE for more information.

Contributing

Please see docs/CONTRIBUTING.md for details on how to contribute to this project.

Changelog

Please see docs/CHANGELOG.md for version history.

Author

Created by Héctor Franco Aceituno at Nowo.tech


All versions of password-policy-bundle with dependencies

PHP Build Version
Package Version
Requires php Version >=8.2 <8.6
doctrine/collections Version ^1.8 || ^2.0
doctrine/orm Version ^2.15 || ^3.0
nesbot/carbon Version ^3.9
psr/clock Version ^1.0
symfony/framework-bundle Version ^6.4 || ^7.0 || ^8.0
symfony/password-hasher Version ^6.4 || ^7.0 || ^8.0
symfony/security-core Version ^6.4 || ^7.0 || ^8.0
symfony/validator Version ^6.4 || ^7.0 || ^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package nowo-tech/password-policy-bundle contains the following files

Loading the files please wait ...