Password policies

New in version 12.0

Introduction

TYPO3 includes a password policy validator which can be used to validate passwords against configurable password policies. A default password policy is included which ensures that passwords meet the following requirements:

  • At least 8 characters
  • At least one number
  • At least one upper case character
  • At least one special character
  • It must be different than current password (if available)

Password policies can be configured individually for both frontend and backend context. It is also possible to extend a password policy with custom validation requirements.

The password policy applies to:

  • Creating a backend user during installation
  • Setting a new password for a backend user in User settings
  • Resetting a password for a backend user
  • Resetting a password for a frontend user
  • Password fields in tables be_users and fe_users

Optionally, a password policy can be configured for custom TCA fields of the type password.

Configuring password policies

A password policy is defined in the TYPO3 global configuration. Each policy must have a unique identifier (the identifier default is reserved by TYPO3) and must at least contain one validator.

The password policy identifier is used to assign the defined password policy to the backend and/or frontend context. By default, TYPO3 uses the password policy default:

config/system/settings.php | typo3conf/system/settings.php
$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] = 'default';
$GLOBALS['TYPO3_CONF_VARS']['FE']['passwordPolicy'] = 'default';
Copied!

A custom password policy with the identifier simple can be configured like:

config/system/additional.php | typo3conf/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['passwordPolicies'] = [
    'simple' => [
        'validators' => [
            \TYPO3\CMS\Core\PasswordPolicy\Validator\CorePasswordValidator::class => [
                'options' => [
                    'minimumLength' => 6,
                ],
            ],
        ],
    ],
];
Copied!

Then assign the custom password policy simple to frontend and/or backend context:

config/system/additional.php | typo3conf/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] = 'simple';
$GLOBALS['TYPO3_CONF_VARS']['FE']['passwordPolicy'] = 'simple';
Copied!

Password policy validators

TYPO3 ships with two password policy validators, which are both used in the default password policy.

\TYPO3\CMS\Core\PasswordPolicy\Validator\CorePasswordValidator

This validator has the ability to ensure a complex password with a defined minimum length and four individual requirements.

The following options are available:

minimumLength
type

int

Default

8

The minimum length of a given password.

upperCaseCharacterRequired
type

bool

Default

false

If set to true at least one upper case character (A-Z) is required.

lowerCaseCharacterRequired
type

bool

Default

false

If set to true at least one lower case character (a-z) is required.

digitCharacterRequired
type

bool

Default

false

If set to true at least one digit character (0-9) is required.

specialCharacterRequired
type

bool

Default

false

If set to true at least one special character (not 0-9, a-z, A-Z) is required.

\TYPO3\CMS\Core\PasswordPolicy\Validator\NotCurrentPasswordValidator

This validator can be used to ensure, that the new user password is not equal to the old password. The validator must always be configured with the exclude action \TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction::NEW_USER_PASSWORD, because it should be excluded, when a new user account is created.

Disable password policies globally

To disable the password policy globally (e.g. for local development) an empty string has to be supplied as password policy for frontend and backend context:

config/system/additional.php | typo3conf/system/additional.php
if (\TYPO3\CMS\Core\Core\Environment::getContext()->isDevelopment()) {
    $GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] = '';
    $GLOBALS['TYPO3_CONF_VARS']['FE']['passwordPolicy'] = '';
}
Copied!

Custom password validator

To create a custom password validator, a new class has to be added which extends \TYPO3\CMS\Core\PasswordPolicy\Validator\AbstractPasswordValidator. It is required to overwrite the following functions:

  • public function initializeRequirements(): void
  • public function validate(string $password, ?ContextData $contextData = null): bool

Please refer to \TYPO3\CMS\Core\PasswordPolicy\Validator\CorePasswordValidator for a detailed implementation example.

Validate a password manually

You can use the \TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator to validate a password using the validators configured in $GLOBALS['TYPO3_CONF_VARS']['SYS']['passwordPolicies'].

The class cannot be injected as it must be instantiated with an action. Available actions can be found in enum EXT:core/Classes/PasswordPolicy/PasswordPolicyAction.php (GitHub).

Example:

In the following example a command to generate a public-private key pair validates the password from user input against the default policy of the current TYPO3 installation.

EXT:my_extension/Classes/Command/PrivateKeyGeneratorCommand.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction;
use TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator;

#[AsCommand(
    name: 'myextension:generateprivatekey',
    description: 'Generates an encrypted private key',
)]
final class PrivateKeyGeneratorCommand extends Command
{
    // Implement class MyService
    public function __construct(private readonly MyService $myService)
    {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $passwort = (string)$io->askHidden(
            'Please enter the password to encrypt the key',
        );
        $passwordValidator = new PasswordPolicyValidator(PasswordPolicyAction::NEW_USER_PASSWORD);
        $result = $passwordValidator->isValidPassword($passwort);
        if ($result === true) {
            $this->myService->generatePrivateKey($passwort);
            return Command::SUCCESS;
        }
        $io->error('The password must adhere to the default password policy.');
        return Command::FAILURE;
    }
}
Copied!

Event

The following PSR-14 event is available: