Search justacoding.blog. [Enter] to search. Click anywhere to close.

September 11th, 2022

Build A React Password Strength Checker Component

Let’s walk through a simple React password strength checker component that can be dropped into your form(s) as and when required.

You can find a working example of this component over here: React password strength checker component example.

What this component does

The role of this password validation component is to essentially verify that the user’s password is strong or complex enough. Essentially, we’ll have a series of conditions which we pass the user’s password through in order to evaluate its overall strength.

If the user’s password isn’t strong enough, our strength checker will notify the user of this. It’ll also provide some hints to help the user improve their password’s strength or complexity.

We’ve got some basic visuals in place to help portray the validation information back to the user:

Building the basic form

First and foremost, we’ll want a basic form to apply our password validation/strength checker functionality to.

This form in our example is a simple one, it looks as follows:

<label>
    Password:{" "}
    <input
        type={passwordIsHidden ? "password" : "text"}
        value={password}
        onChange={(e) => setPassword(e.target.value)}
    />
</label>

<br />

<label>
    Confirm password:{" "}
    <input
        type={passwordIsHidden ? "password" : "text"}
        value={passwordConfirmation}
        onChange={(e) => setPasswordConfirmation(e.target.value)}
    />
</label>

As you can see, we have defined two inputs: password and passwordConfirmation.

It’s standard practice to include a field for the user to confirm their password selection. Both passwords must match in order for the user to proceed.

I’ve also included the ability to toggle the fields from a password field to a regular text field. The password field obscures the characters entered; this is the default field type for password fields in general as they are obviously considered to be sensitive information.

<p
    onClick={() =>
        setPasswordIsHidden((passwordIsHidden) => !passwordIsHidden)
    }
>
    {passwordIsHidden ? "Show" : "Hide"}
</p>

The form data is maintained in state via the various variables declared via the useState hooks.

const [password, setPassword] = useState("")
const [passwordConfirmation, setPasswordConfirmation] = useState("")
const [passwordIsHidden, setPasswordIsHidden] = useState(true)

Adding the PasswordStrengthBar component

Now we have a set of functional password input fields, let’s look at adding the password strength checker component to our form.

For the sake of clarity, lets firstly summarise the role of this new PasswordStrengthBar component:

  • Every time the user types into the password field, we evaluate the input provided and discern whether this equates to a strong password or not
  • More specifically, we give the password a “rating” (in this case, from 0-6)
  • We also supply feedback to the user to provide them with additional detail regarding things they can/should improve to make their password stronger

Regarding the output of this component in particular, it’s fairly straightforward:

return (
    <div>
        <p>
            Password strength:{" "}
            <b>
                    {passwordStrengths[passwordValidationResult.strength - 1]}
            </b>
        </p>

        <div className="pillContainer">
            {[...Array(passwordValidationResult.strength)].map((pill) => {
                return (
                    <div
                        className={`pill strength${passwordValidationResult.strength}`}
                    />
                 )
            })}
        </div>

        {passwordValidationResult.feedback.length > 0 && (
            <ul>
                {passwordValidationResult.feedback.map(
                (feedback, index) => {
                    return <li key={index}>{feedback}</li>
                }
                )}
            </ul>
        )}
    </div>
)

There are three aspects here.

We are showing:

  • A textual representation of how strong the password is, ie. weak or strong
  • A list of hints required in order to improve the password strength
  • A visual element that changes colour based on how strong the password is, this works on a scale from 0-6

Combined, these elements provide a nice clear mechanism to feedback the relevant information to the user upon password entry.

Styling the password strength bar

In terms of styling the password strength bar, or the “pills” as they are named, I’ve taken advantage of the simplistic system that’s already in place.

The password strength can be rated from 0 to 6.

As such, I’ve added some CSS classes in line with this:

.strength1 {
    background-color: #ad1212;
}

.strength2 {
    background-color: #bf5323;
}

.strength3 {
    background-color: #d48c40;
}

.strength4 {
    background-color:#b4c87e;
}

.strength5 {
    background-color: #93d855;
}

.strength6 {
    background-color: #7cec17;
}

You can see these classes are utilised here:

<div
    className={`pill strength${passwordValidationResult.strength}`}
/>

So it’s simply a means of effectively composing a string using the password strength value to match up with the CSS classes we’ve already defined. This will automatically apply our styling for us, and allow the password strength checker elements to be styled as appropriate.

Now let’s look at adding the underlying functionality which drives this output, this is the most important part of the component.

A function to measure password strength

The crux of this component is of course the functionality which is responsible for evaluating the overall strength of the user input (the password).

We’ve delegated this responsibility to a function called validatePasswordStrength, and this validatePasswordStrength function also drives the output from the PasswordStrengthCheck component.

The task is to simply take a string (password) and return some sort of indication with regards to how strong this password is deemed to be.

For this, we need an algorithm. An algorithm is, simply put: a programming algorithm is a procedure or formula used for solving a problem.

Building the password checking algorithm

Our password strength checking implementation here is very simple:

const validatePasswordStrength = (password) => {
    let strength = 0
    const feedback = []

    if (password.length >= 10) {
        strength++
    } else {
        feedback.push("Must be 10 characters of greater")
    }

    if (/[a-z]/.test(password)) {
        strength++
    } else {
        feedback.push("Must have at least 1 lowercase letter")
    }

    if (/[A-Z]/.test(password)) {
        strength++
    } else {
        feedback.push("Must have at least 1 uppercase letter")
    }

    if (/[0-9]/.test(password)) {
        strength++
    } else {
        feedback.push("Must have at least 1 number")
    }

    if (/[`!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/.test(password)) {
        strength++
    } else {
        feedback.push("Must have at least 1 special character")
    }

    if (!/(.)\1{1,}/.test(password)) {
        strength++
    } else {
        feedback.push("Must not contain any repeating characters")
    }

    return { strength, feedback }
}

This is essentially a series of conditions composed of regular expressions, the idea being that we “test” the input string (the user’s intended password) under a specific rule in each case.

As you can see, there are 6 aspects in total which are used to measure the password strength.

  • Length (must be 10 characters or more)
  • Must contain a lowercase character
  • Must contain an uppercase character
  • Must have a numeric value
  • Must have a special character (for instance ! or *)
  • Must not have any repeating characters ie. cc or 55.

To keep things simple, we’re allocating 1 point for each scenario that the password passes.

That means the weakest possible password would achieve 0 points under our system; the strongest possible password would achieve 6 points.

Note: this is an extremely basic password validation implementation for the sake of demonstration. Whilst it may provide a good starting point for a more production-ready approach, you’ll likely want to expand on this approach with many more scenarios for a real-world implementation.

For more ideas on how to write a strong password checking algorithm, it’d be wise to do some research on what makes up a strong password to begin with. Then construct your own functionality around these factors.

Providing feedback to the user

To provide some feedback to the user regarding their password’s strength or complexity, you’ll notice we’re also populating an array called feedback.

This is simply a list of strings that is essentially populated each time the password “fails” one aspect of our check.

This feedback is used directly in the output of the PasswordStrengthChecker component, with the idea being to guide the user into providing a stronger password upon each key-stroke.

Comparing passwords and disabling the form

I’ve also added the mechanism to compare passwords:

if (password !== passwordConfirmation) {
    passwordValidationResult.feedback.push("Passwords don't match")
}

You’ll notice that this aspect is not included in our password strength checker implementation specifically; that’s because it’s not part of this functionality, strictly speaking.

It’s a separate thing entirely — so we’re simply appending the results of the password comparison check outside of the password strength functionality (after it).

This result (“do the passwords match?”) is effectively added to the array which contains the feedback items, though, so it’s output in exactly the same manner (ie. as part of the same list).

Now, if this feedback array contains any items at all, we’ll know that either:

  • The password input isn’t strong enough, or
  • The passwords don’t match

In this case, I’ve opted to disable the form to prevent submission.

This is achieved via the utilisation of a function passed down from the parent component, here:

setPasswordIsValid(passwordValidationResult.feedback.length === 0)

In closing

I hope you’ve found this article helpful, and that you’ve gained some insight with regards to creating your own React password strength checker (or validation) component.

As explained, the password validation implementation in this example is fairly rudimentary, but it’s enough to get you started.

If you’re serious about building a production-ready version of this component, it’d be best to firstly research what other factors play into creating a strong password. There are some important aspects lacking in this component; such as the ability to avoid dictionary words entirely.

For similar articles to this one, though, be sure to check out our Code Examples section!

Thanks for reading!

Have any questions? Ping me over at @justacodingblog
← Back to blog