Implementing Password Policies In React
Published: 2024-03-17 10:03:29

by [Onyeyaforo Emmanuel](https://blog.openreplay.com/authors/onyeyaforo-emmanuel)


<blockquote><em>
Password policies are rules for creating passwords. Passwords are the keys to your digital world, from emails to social media, but not all passwords are strong. Some are weak and easy to guess, while others are strong and hard to crack. This article will explain what a password policy is, why it matters, and how to implement it.
</em></blockquote>


<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>


Password policies play a critical role in our digital lives, safeguarding financial data, personal emails, and business information. Despite their importance, we often overlook this fundamental aspect of digital security.

Weak passwords are like an open invitation to cybercriminals. They present notable security risks, and the consequences of such breaches can be bad. Here are a few compelling reasons why password policies matter:

* Risks of Weak Passwords: Weak passwords, like “123456” or “password,” are a hacker’s dream. They can crack, allowing unauthorized access to sensitive accounts. This may be personal information and even financial assets.
* Significance of Strong Password Policies: Strong password policies are the first line of defense against online threats. They set standards for creating secure passwords that are difficult for attackers to crack.
* Real-World Examples: Consider the countless high-profile data breaches that have made headlines. Companies, organizations, and even individuals have suffered the consequences of weak password security. From the Yahoo data breach, which affected billions of accounts to others reported. This highlights the devastating effects of insufficient password policies as reported by [Firewalltimes](https://firewalltimes.com/recent-data-breaches/).
* Personal and Business Implications: The importance of strong password policies extends beyond individual users. In case of a security breach, businesses and organizations may not only incur data losses. They can also suffer damage to their reputation and a loss of customer trust.

## Key Components of a Password Policy
As the first line of defense for our digital fortress, here are some common components. They form the foundation of a robust password policy:

* Password Length: The first and most intuitive component is password length. The longer the password, the more difficult it is for hackers to crack. A longer password provides a greater range of combinations. This makes it a formidable barrier against brute-force attacks.

* Password Complexity: This is another critical component. It involves using mixed character types in the combination, such as uppercase and lowercase letters, numbers, and special symbols. A complex password is much more resilient to various types of attacks. The rationale behind complexity is simple yet effective. Mixing various character types boosts the number of potential password combinations. This means hackers have to try a larger number of combinations, thus making it difficult to crack. 

![infographics](https://blog.openreplay.com/images/implementing-password-policies-in-react/images/image1.jpg)

Look at the infographics above, cited from [HiveSystems](https://www.hivesystems.io/blog/are-your-passwords-in-the-green). We can get a basic idea of how password vulnerability decreases with an increase in password length and complexity.

## Project Setup
### UI build
For the sake of this article and to simplify the procedure, all examples and discussions will be on the `App.tsx`.

We shall build a sample user sign-up form to implement the password policy.

In the `App.tsx` file we define the structure of the data using an interface called `FormData`. This specifies the data for our policy should include fields for:
* `email`, 
* `password`, 
* `confirmPassword`, 
* `showPassword`.

The `useState` hook is then used to create a state variable called `formData`. This variable holds the data, and it's initialized with empty values for each field in form data as below.

```typescript]
//App.tsx
interface FormData {
  email: string;
  password: string;
  confirmPassword: string;
  showPassword: boolean;
}

const App = () => {
  const [formData, setFormData] = useState<formData>
    {
      email: "",
      password: "",
      confirmPassword: "",
      showPassword: false,
    };
};
```
Next, we’ll create event handlers to link the input fields to the HTML section of our form. We’ll keep these functions separate and well-organized to make this more beginner-friendly.

* `handleEmailChange` handles changes in the email input field. When the user enters or modifies their email address, the new value is extracted. This updates the email field in the `formData` state while preserving the other fields.
* `handlePasswordChange`: handles changes in the password input field. This function calls for updates when a user enters or changes the password. It extracts the field's `name` and new `value` and updates the corresponding field. The `formData` updates for the specific value while keeping other fields unchanged.

* `handleShowPassword` toggles the `showPassword` property in the `formData` state between *true* and *false*. This state handles password visibility. Users trigger this when they desire to show or hide password characters.

* `handleConfirmPasswordChange`: is like `handlePasswordChange`. This function manages changes in the `confirmPassword` field.

```typescript
//change handlers
  const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target
    setFormData({
      ...formData,
      email: value,
    })
  }

  const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target
    setFormData({
      ...formData,
      [name]: value,
    })
  }

  const handleShowPassword = () => {
    setFormData({ ...formData, showPassword: !formData.showPassword })
  }

  const handleConfirmPasswordChange = (
    e: React.ChangeEvent<HTMLInputElement>,
  ) => {
    const { value } = e.target
    setFormData({
      ...formData,
      confirmPassword: value,
    })
  }
```
Next, we continue by building the user interface. We will be styling using [Tailwind CSS](https://tailwindcss.com/docs/guides/vite), and the created handler functions are added below.

```htmlmixed
//App.tsx 
//Creating the UI
<main className="flex items-center justify-center mx-auto w-full min-h-[100vh] bg-gray-800 py-10">
  <form className="bg-white rounded-lg w-[600px] sm:mx-20 mx-4 sm:p-10 p-6 ">
    <h1 className="sm:text-2xl text-xl text-center">Sign Up Form</h1>
    <p className="sm:text-lg text-sm pt-4 pb-6 text-center">
      Hello there! fill up this form to create your account
    </p>
    <div>
      <label htmlFor="email">Email:</label> <br />
      <input
        type="email"
        name="email"
        id="email"
        className="w-full border-2 border-gray-300 rounded-lg px-6 py-3 !focus:border-green-400"
        value={formData.email}
        onChange={handleEmailChange}
      />
    </div>
    <br />
    <div className="relative">
      <label htmlFor="password">Password:</label> <br />
      <input
        type={formData.showPassword ? "text" : "password"}
        autoComplete="off"
        name="password"
        id="password"
        value={formData.password}
        className="w-full border-2 border-gray-300 rounded-lg px-6 py-3 !focus:border-green-400"
        onChange={handlePasswordChange}
      />
      <button
        className="uppercase absolute top-[38px] right-4 text-gray-500 bg-white"
        type="button"
        onClick={handleShowPassword}
      >
        {formData.showPassword ? "Hide" : "Show"}
      </button>
    </div>

    <div>
      <label htmlFor="confirmPassword">Confirm Password:</label> <br />
      <input
        type="password"
        name="confirmPassword"
        id="confirmPassword"
        autoComplete="off"
        className="w-full border-2 border-gray-300 rounded-lg px-6 py-3 !focus:border-green-400"
        value={formData.confirmPassword}
        onChange={handleConfirmPasswordChange}
      />
    </div>

    <button
      type="submit"
      name="submit-form"
      className={`w-full py-3 rounded-lg text-white text-xl mt-10`}
    >
      Sign Up
    </button>
  </form>
</main>
```
![Project UI Build Alone](https://blog.openreplay.com/images/implementing-password-policies-in-react/images/image2.png)


<CTA_Middle_Security />


### Implementing the password policy rules
The code snippet below implements password policy rules. It checks for the presence of various elements, such as numbers, uppercase and lowercase letters, and symbols, and ensures the password length falls within a specified range.

```typescript
//password policy criteria
interface PasswordValidationCriteria {
  label: string;
  isValid: boolean;
}

const [passwordValidation, setPasswordValidation] = useState<PasswordValidationCriteria[]>([
  { label: 'One number', isValid: false },
  { label: 'One uppercase letter', isValid: false },
  { label: 'One lowercase letter', isValid: false },
  { label: 'One symbol', isValid: false },
  { label: 'One Latin letter', isValid: false },
  { label: 'Use 14-50 characters', isValid: false },
]);

const validatePassword = (password: string) => {
  const updatedPasswordValidation = passwordValidation?.map((criteria) => {
      switch (criteria.label) {
        case 'One number':
          criteria.isValid = /[0-9]/.test(password)
          break
        case 'One uppercase letter':
          criteria.isValid = /[A-Z]/.test(password)
          break
        case 'One lowercase letter':
          criteria.isValid = /[a-z]/.test(password)
          break
        case 'One symbol':
          criteria.isValid = /[!@#$%^&*]/.test(password)
          break
        case 'One Latin letter':
          criteria.isValid = /[a-zA-Z]/.test(password)
          break
        case 'Use 14-50 characters':
          criteria.isValid = password.length >= 14 && password.length <= 50
          break
        default:
          break
      }
      return criteria
    })

    setPasswordValidation([...updatedPasswordValidation])
}
```
Firstly, we define an interface called `PasswordValidationCriteria`. It describes the structure of objects used to represent password validation criteria. This includes a description `label` and a validity indicator `isValid`.

The `useState` hook here creates a state variable named `passwordValidation`. This variable is an array of objects, each representing a specific criterion. At initialization, the criteria are all marked as not met, with `isValid` set to false.

From the code snippet above, the `validatePassword` function employs [regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions) to inspect a password against specific requirements. This might not always be the case as developers can use other methods to inspect against a specific requirement.

Next, under the password input field, we leverage the JavaScript higher-order function `map`. This is to display and show the status of password updates. The `criteria.siValid` property plays a key role in styling attribute determination. It helps to apply these styles based on whether it evaluates to *true* or *false*

```htmlmixed
<div>
  <ul className="grid sm:grid-cols-2 grid-cols-1 pt-2 pb-5 gap-2">
    {passwordValidation.map((criteria, index) => (
      <li
        key={index}
        className={criteria.isValid ? "text-green-500" : "text-gray-400"}
      >
        <span>
          {criteria.isValid ? (
            <span>&#10003;&nbsp;</span>
          ) : (
            <span>&#8226;&nbsp;</span>
          )}
        </span>
        {criteria.label}
      </li>
    ))}
  </ul>
</div>
```
![UI build with criterias set](https://blog.openreplay.com/images/implementing-password-policies-in-react/images/image3.png)

### Validating passwords and handling errors
Here, we use the `validatePassword` function mentioned earlier inside the password handler. This ensures each character the user enters follows the password criteria we've set.

```typescript
//change password handler with validatePassword function
const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  const { name, value } = e.target
  setFormData({
      ...formData,
      [name]: value,
  })

  validatePassword(value) //called here
}
```
We also confirm the password in the `handleConfirmPasswordChange`. This ensures it matches the password entered in the `handlePasswordChange`.

We create a state variable and related functions to handle password confirmation. It guarantees what the user writes in confirmation matches the password.

```typescript
//confirm password change validation
//state to track changes
const [isPasswordMatch, setIsPasswordMatch] = useState<boolean>(false)
```
From the above, `isPasswordMatch` is a boolean state variable. This keeps track of whether the confirmation password matches the password. The `validatePasswordConfirmation` function is used to validate and set the `isPasswordMatch` state. This is based on the comparison between the password and the confirmation.

We also write a function to ensure that the `confirmPassword` value is the same as that of the `password`. This will be nested inside of the confirm password change handler.

The `handleConfirmPasswordChange` function updates the formData state. This then calls `validatePasswordConfirmation` to ensure the confirmation matches the password. It helps in real-time validation and updating the user interface and also informs the user whether the passwords match or not.

By doing this, we help the users help themselves to ensure a more secure online experience.

![UI build with policy validated](https://blog.openreplay.com/images/implementing-password-policies-in-react/images/image4.png)

## Best Practices
Here are some of the best practices for implementing a password policy in React applications

* Client-Side Validation with Feedback: Test the password's complexity in real time. This saves the user from several trials and errors when setting a password.
* Password Strength Meter: Display a visual indicator of how strong the password is. This steers the user in the right direction to know if the password is strong or not.
* Server-side security: Always verify passwords on the server side for added security. This would ensure that both the client and server are in sync, thus providing a robust security system

## Conclusion
In conclusion, password policies play a vital role in online security. These policies are like the protective shields that keep our digital fortress safe.

To see these principles in action, check out the live demonstration on [Vercel](https://article-password-policy.vercel.app/). You can also find the code on the [GitHub repository](https://github.com/keys78/article-password-policy).

Always keep in mind that the ability to safeguard our online presence is a valuable skill to own.