From 78a93870f6584c6a6518de10c2c94101fa0ca9c6 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 5 Apr 2019 12:58:07 +0200 Subject: [PATCH] Added docs for the NotCompromisedPassword constraint --- reference/constraints.rst | 1 + reference/constraints/NotPwned.rst | 133 +++++++++++++++++++++++++++++ reference/constraints/map.rst.inc | 1 + 3 files changed, 135 insertions(+) create mode 100644 reference/constraints/NotPwned.rst diff --git a/reference/constraints.rst b/reference/constraints.rst index 9cbe8bcccf9..142c94f6a4a 100644 --- a/reference/constraints.rst +++ b/reference/constraints.rst @@ -66,6 +66,7 @@ Validation Constraints Reference constraints/All constraints/UserPassword constraints/Valid + constraints/NotCompromisedPassword The Validator is designed to validate objects against *constraints*. In real life, a constraint could be: "The cake must not be burned". In diff --git a/reference/constraints/NotPwned.rst b/reference/constraints/NotPwned.rst new file mode 100644 index 00000000000..30a43828ed1 --- /dev/null +++ b/reference/constraints/NotPwned.rst @@ -0,0 +1,133 @@ +NotCompromisedPassword +====================== + +.. versionadded:: 4.3 + + The ``NotCompromisedPassword`` constraint was introduced in Symfony 4.3. + +Validates that the given password has not been compromised by checking that is +not included in any of the public data breaches tracked by `haveibeenpwned.com`_. + +========== =================================================================== +Applies to :ref:`property or method ` +Options - `groups`_ + - `message`_ + - `payload`_ + - `skipOnError`_ + - `threshold`_ +Class :class:`Symfony\\Component\\Validator\\Constraints\\NotCompromisedPassword` +Validator :class:`Symfony\\Component\\Validator\\Constraints\\NotCompromisedPasswordValidator` +========== =================================================================== + +Basic Usage +----------- + +The following constraint ensures that the ``rawPassword`` property of the +``User`` class doesn't store a compromised password: + +.. configuration-block:: + + .. code-block:: php-annotations + + // src/Entity/User.php + namespace App\Entity; + + use Symfony\Component\Validator\Constraints as Assert; + + class User + { + // ... + + /** + * @Assert\NotCompromisedPassword + */ + protected $rawPassword; + } + + .. code-block:: yaml + + # config/validator/validation.yaml + App\Entity\User: + properties: + rawPassword: + - NotCompromisedPassword + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: php + + // src/Entity/User.php + namespace App\Entity; + + use Symfony\Component\Validator\Mapping\ClassMetadata; + use Symfony\Component\Validator\Constraints as Assert; + + class User + { + public static function loadValidatorMetadata(ClassMetadata $metadata) + { + $metadata->addPropertyConstraint('rawPassword', new Assert\NotCompromisedPassword()); + } + } + +In order to make the password validation, this constraint doesn't send the raw +password value to the ``haveibeenpwned.com`` API. Instead, it follows a secure +process known as `k-anonimity password validation`_. + +In practice, the raw password is hashed using SHA-1 and only the first bytes of +the hash are sent. Then, the ``haveibeenpwned.com`` API compares those bytes +with the SHA-1 hashes of all leaked passwords and returns the list of hashes +that start with those same bytes. That's how the constraint can check if the +password has been compromised without fully disclosing it. + +For example, if the password is ``test``, the entire SHA-1 hash is +``a94a8fe5ccb19ba61c4c0873d391e987982fbbd3`` but the validator only sends +``a94a8`` to the ``haveibeenpwned.com`` API. + +Available Options +----------------- + +.. include:: /reference/constraints/_groups-option.rst.inc + +message +~~~~~~~ + +**type**: ``string`` **default**: ``This password has been leaked in a data breach, it must not be used. Please use another password.`` + +The default message supplied when the password has been compromised. + +.. include:: /reference/constraints/_payload-option.rst.inc + +skipOnError +~~~~~~~~~~~ + +**type**: ``boolean`` **default**: ``false`` + +When the HTTP request made to the ``haveibeenpwned.com`` API fails for any +reason, an exception is thrown (no validation error is displayed). Set this +option to ``true`` to not throw the exception and consider the password valid. + +threshold +~~~~~~~~~ + +**type**: ``integer`` **default**: ``1`` + +This value defines the number of times a password should have been leaked +publicly to consider it compromised. Think carefully before setting this option +to a higher value because it could decrease the security of your application. + +.. _`haveibeenpwned.com`: https://haveibeenpwned.com/ +.. _`k-anonimity password validation`: https://blog.cloudflare.com/validating-leaked-passwords-with-k-anonymity/ diff --git a/reference/constraints/map.rst.inc b/reference/constraints/map.rst.inc index f0a5696648d..7055516d14b 100644 --- a/reference/constraints/map.rst.inc +++ b/reference/constraints/map.rst.inc @@ -88,3 +88,4 @@ Other Constraints * :doc:`Collection ` * :doc:`Count ` * :doc:`UniqueEntity ` +* :doc:`NotCompromisedPassword `