9

Craft’s only password requirements are that it is between 6 and 160 characters long. I want to require my users to enter passwords that are at least 7 characters long, with at least one number and one capital letter.

Is it possible to enforce these stricter requirements, or do we have to wait for this feature request to be accepted?

1 Answer 1

10

In Craft 2

Plugins have the power to enforce stricter password requirements using the users.onBeforeSetPassword event.

Add this code to your plugin’s primary class:

public function init()
{
    craft()->on('users.beforeSetPassword', array($this, 'onBeforeSetPassword'));
}

public function onBeforeSetPassword(Event $e)
{
    $user = $e->params['user'];
    $password = $e->params['password'];

    // Perform our custom validation logic here
    $validates = true;

    if (mb_strlen($password) < 7)
    {
        $validates = false;
    }
    else if (!preg_match('/(\d.*[A-Z]|[A-Z].*\d)/', $password))
    {
        $validates = false;
    }

    if (!$validates)
    {
        // Set $performAction = false so the password doesn't get saved
        $e->performAction = false;

        // Add a custom validation error on the user
        $user->addError('newPassword', 'Sorry but your password must contain an uppercase letter, a number, a haiku, a gang sign, hieroglyph, and the blood of a virgin.');
    }
}

In Craft 3

Craft 3 doesn't have a beforeSetPassword event, but you can pull the same thing off from your plugin's init() method using the User element's User::EVENT_BEFORE_VALIDATE event like so:

public function init()
{
    parent::init();

    Event::on(
        User::class,
        User::EVENT_BEFORE_VALIDATE,
        function (ModelEvent $event) {
            // Check if a new password was set on the user
            if ($event->sender->newPassword) {
                $password = $event->sender->newPassword;
                $errors = [];

                // Perform our custom validation logic here
                $validates = true;

                if (mb_strlen($password) < 7) {
                    $validates = false;
                    $errors[] = 'Too Short!';
                }
                else if (!preg_match('/(\d.*[A-Z]|[A-Z].*\d)/', $password)) {
                    $validates = false;
                    $errors[] = 'Too Simple!';
                }

                $event->isValid = $validates;

                if (!$validates) {
                    /** @var User $user */
                    $user = $event->sender;
                    foreach ($errors as $error) {
                        $user->addError('newPassword', $error);
                    }
                }
            }
        }
    );
}
3
  • I've adapted Brandon Kelly's answer into a plugin, craft-password-enforcer.
    – kotyy
    Commented Sep 19, 2016 at 19:05
  • @BrandonKelly is there a way to stop the default craft error displaying if the password is less then 6 characters? As it is confusing for the user to show one error stating it needs to be 6 then another error again if I set my default length to be higher than this (10 for example). Commented Oct 1, 2016 at 21:28
  • @TerryUpton Good question. Right now I don't think that’s possible, unfortunately. Commented Oct 11, 2016 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.