Skip to main content

How to Manage Password Strength - Angular

In this article, we will discuss "How to Manage Password Strength - Angular". There are multiple ways to implement this feature in your Angular application such as applying pattern validation, creating a password strength meter, or using any existing package. In this example, I'm using the Angular Reactive form. You will learn pattern validation and how to create a password strength meter.

Getting Start


I'm using StackBlitz to run this example. This is an online IDE, so no need to setup Angular on local and you can share your code with the community. And, I'm assuming you are familiar with Angular, so I'm not adding basic steps in this article such as creating an angular project, adding Reactive form and etc.

At the end of this article, we are going to see how to use:

  • Reactive Forms and Validators (In a simple way)

  • Component interactions using @Input and @Output decorators


In the example, I will explain to you using two examples both are using RegExp to validate the form.

  1. Pattern Validation

  2. Password Strength Meter


Pattern Validation


Here, I'm creating a form with three fields name, email, and password. Validating those fields using RegEx.

Let create a component and update the layout. Open "pattern-validate.component.html" and update the following code.
<h1 class="text-primary text-center p-4 bg-light">Pattern Validation</h1>
<div class="col-md-12">
<form [formGroup]="form1">
<div class="mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" formControlName="fullname" />
<div
class="alert alert-danger"
*ngIf="!form1.get('fullname').valid && form1.get('fullname').touched"
>
Atleast 3 characters required and no special character allowed.
</div>
</div>
<div class="mb-3">
<label class="form-label">Email address</label>
<input type="email" class="form-control" formControlName="email" />
<div
class="alert alert-danger"
*ngIf="!form1.get('email').valid && form1.get('email').touched"
>
Invalid email id
</div>
</div>
<div class="mb-3">
<label class="form-label">Password</label>
<input type="password" class="form-control" formControlName="password" />
<div
class="alert alert-danger"
*ngIf="!form1.get('password').valid && form1.get('password').touched"
>
Password must contain more than 8 characters, 1 upper case letter, and 1
special character
</div>
</div>

<button type="submit" class="btn btn-primary" (click)="onSubmit()">
Submit
</button>
</form>
form1.value
</div>

 

Open "pattern-validate.component.ts" and update the following code.
import Component, OnInit from '@angular/core';
import FormBuilder, Validators from '@angular/forms';

@Component(
selector: 'app-pattern-validate',
templateUrl: './pattern-validate.component.html',
styleUrls: ['./pattern-validate.component.css'],
)
export class PatternValidateComponent
constructor(private fb: FormBuilder)

form1 = this.fb.group(
fullname: [
null,
[
Validators.required,
Validators.pattern(/^[A-z0-9]*$/),
Validators.minLength(3),
],
],
email: [
null,
[
Validators.required,
Validators.pattern(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w2,3)+$/),
],
],
password: [
null,
[
Validators.required,
Validators.pattern(
/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#\$%\^&\*])(?=.8,)/
),
Validators.minLength(8),
],
],
);

onSubmit()
if (this.form1.valid)
console.log('Form Submitted');
else
console.error('Form values are invalid.');



Form validation looks like.

Pattern Validation




Password Strength Meter


Here, we are going to add a strength bar with our password field. This will force users to choose a strong password. We are going to apply the following rules to the password.

  • The password contains at least one special character

  • Must contain at least one uppercase and lowercase character

  • Last, must contains at least one number and 8 characters long


Each rule applied to our password using the RegEx. As per the rules, we show some color bars to indicate how strong our password is. If the password is not strong as expected, then the user is not authorized to submit the form.

Here, I'm creating a form with three fields name, email, and password. Validating those fields using RegEx. Additionally, showing a password strength meter with a password field. Let create a component and update the layout. Open "strength-bar.component.html" and update the following code.
<h1 class="text-primary text-center p-4 bg-light">
Example with Password Strength
</h1>
<div class="col-md-12">
<form [formGroup]="form2">
<div class="mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" formControlName="fullname" />
</div>
<div class="mb-3">
<label class="form-label">Email address</label>
<input type="email" class="form-control" formControlName="email" />
</div>
<div class="mb-3">
<label class="form-label">Password</label>
<input type="password" class="form-control" formControlName="password" />
<strength-checker
barLabel="Password Strength: "
[passwordToVerify]="form2.value.password"
(passwordStrength)="passwordValid($event)"
></strength-checker>
</div>
<button
type="submit"
class="btn btn-primary"
[disabled]="!passwordIsValid"
(click)="onSubmit()"
>
Submit
</button>
</form>
</div>

Open "strength-bar.component.ts" and update the following code.
import Component from '@angular/core';
import FormBuilder, Validators from '@angular/forms';

@Component(
selector: 'app-strength-bar',
templateUrl: './strength-bar.component.html',
styleUrls: ['./strength-bar.component.css'],
)
export class StrengthBarComponent
constructor(private fb: FormBuilder)
passwordIsValid = false;
form2 = this.fb.group(
fullname: [
null,
[
Validators.required,
Validators.pattern(/^[A-z0-9]*$/),
Validators.minLength(3),
],
],
email: [
null,
[
Validators.required,
Validators.pattern(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w2,3)+$/),
],
],
password: [null, [Validators.required]],
);

onSubmit()
if (this.form2.valid)
console.log('Form Submitted');
else
console.error('Form values are invalid.');



passwordValid(event)
this.passwordIsValid = event;


Create Child Component "Strength-checker"


Let's create a child component "strength-checker.component.ts".

The parent and child component interaction will be achieved by the Angular decorator such as "@Input" and "@Output". We are going to intercept the data using the "ngOnChanges" method. Our component looks like the following.
import 
Component,
Input,
OnChanges,
SimpleChange,
Output,
EventEmitter,
from '@angular/core';

@Component(
selector: 'strength-checker',
template: `<div class="strength">barLabel&nbsp;
<ul class="strengthBar">
<li class="point" [style.background-color]="bar0"></li>
<li class="point" [style.background-color]="bar1"></li>
<li class="point" [style.background-color]="bar2"></li>
<li class="point" [style.background-color]="bar3"></li>
</ul>
<br>
<p class="alert alert-info" *ngIf="msg">msg</p>
</div>`,
styles: [
`.strengthBar
display: inline;
list-style: none;
margin: 0;
padding: 0;
vertical-align: 2px;


.point:last-of-type
margin: 0 !important;


.point
background: #DDD;
border-radius: 2px;
display: inline-block;
height: 5px;
margin-right: 1px;
width: 62px;
`,
],
)
export class StrengthCheckerComponent implements OnChanges {
@Input() public passwordToVerify: string;
@Input() public barLabel: string;
@Output() passwordStrength = new EventEmitter<boolean>();
bar0: string;
bar1: string;
bar2: string;
bar3: string;

msg = '';

private colors = ['darkred', 'orangered', 'orange', 'yellowgreen'];

private static checkStrength(p)
let force = 0;
const regex = /[$-/:-?-~!"^_@`\[\]]/g;

const lowerLetters = /[a-z]+/.test(p);
const upperLetters = /[A-Z]+/.test(p);
const numbers = /[0-9]+/.test(p);
const symbols = regex.test(p);

const flags = [lowerLetters, upperLetters, numbers, symbols];

let passedMatches = 0;
for (const flag of flags)
passedMatches += flag === true ? 1 : 0;


force += 2 * p.length + (p.length >= 10 ? 1 : 0);
force += passedMatches * 10;

// short password
force = p.length <= 8 ? Math.min(force, 10) : force;

// poor variety of characters
force = passedMatches === 1 ? Math.min(force, 10) : force;
force = passedMatches === 2 ? Math.min(force, 20) : force;
force = passedMatches === 3 ? Math.min(force, 30) : force;
force = passedMatches === 4 ? Math.min(force, 40) : force;

return force;


ngOnChanges(changes: [propName: string]: SimpleChange ): void
const password = changes.passwordToVerify.currentValue;
this.setBarColors(4, '#DDD');
if (password)
const c = this.getColor(StrengthCheckerComponent.checkStrength(password));
this.setBarColors(c.idx, c.col);

const pwdStrength = StrengthCheckerComponent.checkStrength(password);
pwdStrength === 40
? this.passwordStrength.emit(true)
: this.passwordStrength.emit(false);

switch (c.idx)
case 1:
this.msg = 'Poor';
break;
case 2:
this.msg = 'Not Good';
break;
case 3:
this.msg = 'Average';
break;
case 4:
this.msg = 'Good';
break;

else
this.msg = '';



private getColor(s)
let idx = 0;
if (s <= 10)
idx = 0;
else if (s <= 20)
idx = 1;
else if (s <= 30)
idx = 2;
else if (s <= 40)
idx = 3;
else
idx = 4;

return
idx: idx + 1,
col: this.colors[idx],
;


private setBarColors(count, col)
for (let n = 0; n < count; n++)
this['bar' + n] = col;




The secure password strength bar looks like the following screenshot.

Password Strength Meter

Working Example


[embed_iframe link="https://stackblitz.com/edit/angular-ivy-bnupgd?embed=1&file=src/app/app.component.html" title="How to Manage Password Strength - Angular"]

Finally, everything’s ready now. Check out the working example, hope this article helped you to learn "How to manage password strength". Feel free to add your comment if any queries, also you can share your feedback.

Comments

Popular posts from this blog

Basic Use of Model Factories in Laravel

In this article, we will discuss the basic use of Model Factories in Laravel. Laravel comes with the feature called model factories that are offered to made fake models quickly. It’s used in the database testing and database seeding. Let’s start the discussion on this feature by... Read out the full post at here

How to Manage Elastic IP in AWS?

In this article, we will discuss "How to Manage Elastic IP in AWS?" . Here, you will learn the use of Elastic IP addresses and how to assign it to your EC2 Instance. If you are new with EC2 Instance then check out my previous article, "How to setup an EC2 Instance on AWS" . EC2 (Amazon Elastic Compute Cloud) provide us an ability to create, start, stop and terminate the instance at any time. This will creates a challenge with IP addresses, because restarting an instance or replacing a terminated instance with newly created instance, will result in a new IP address. Now the question is "How to reference a machine when the IP is constantly change?" . We can handle this situation with the use of Elastic IP address. We can associate a single Elastic IP address to different Ec2 Instances. You can immediately associate a new Ec2 Instance with the Elastic IP address if the EC2 instance is stopped or terminated. After the back-end EC2 instance changes, our exist...

How to use trackBy in Angular with Example

In this article, we will discuss "How to use trackBy in Angular" . Basically, " trackBy " is used to improve the performance of an angular application. Today, I will try to explain the use of trackBy with an example. Why do we need trackBy in Angular? By default, no need to use trackBy in Angular. But with large collections of data, angular ngFor directive may perform poorly. For example, a small change of data such as adding a new record, editing, or deleting a record from the collection. The angular framework will remove all the DOM elements that are associated with the data and will create them again in the DOM tree even if the same data is coming. Here, a lot of DOM manipulation will happen in the background if a large amount of data comes from the API then the application performance will suffer. Angular trackBy example Angular provides us function trackBy which helps us to track the items which have been added or deleted. The trackBy function takes two argum...