Article Banner

Better Passwords With Angular and Django

Even though I describe myself as a Pythonista today I have realized that I have always been writing only for the front-end. I like Angular and the world of front-end development but when it comes to python it is different for me.

So I decided to show something related to backend and I ended up writing this piece which has to do with both front and back. (Looks like there is a hidden love for the front-end too)

In this piece, I am going to show you how you can ask your users to choose more secure passwords with a good user experience. Let’s take a look at what the product of this article will be. Below GIF is taken from the library npm site.

We will be using the excellent library password-strength from material-extensions. Thanks to Antony Nahas and all the contributors.

I have the front and back repo here if you are a show me the code type.

I am skipping the project creation stuff, docs already explain it better than me. I have those two project structures:

  • Front (Angular)

  • Back (Django and Django REST)

Begin with Backend

As always let me begin with the backend❤️ Let’s install the requirements:

I will be skipping the configuration, they are out of the scope of this article. Please ask me if you struggle with anything. I highly suggest checking the Djoser lib in detail, it is a really good one built by the sunscrapers.


Django's requirements

Now thanks to Djoser lib I have a working endpoint which I can create a user. Let’s run the server and hit it. http://127.0.0.1:8000/auth/users/

So I have made a try to create a user but the password(test) is not filling out the requirements so I got those error messages. Let’s look at what type of requirements does Django has by default. A section from settings.py below.

{% gist https://gist.github.com/klement97/0c6b48e853225219c7185e7360ca914e %}

  • User Attribute Similarity — Ensures the password is not similar to user attributes like email, username and first and last names

  • Minimum Length Validator — Ensures the password is at least 8 chars. This can be changed by adding an option below like so

'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 8,
        }
    },
  • Common Password Validator — Ensures the password is not inside a 20.000 of passwords length of a list. Comparing is case-insensitive.

  • Numeric Password Validator — Ensures the password is not entirely numeric

The above validators are the default ones and can be extended which is exactly what we are going to do. We are going to write some more validators ourselves.

  • Number Validator

  • Upper Case Validator

  • Lower Case Validator

  • Symbol Validator

{% gist https://gist.github.com/klement97/fe3c1201836201024d89f23a25578750 %}

Above you see the validators.py file, it is as simple as it gets. We check for our condition and raise a Validation Error if it is not met.

Add new validators to settings.py:

{% gist https://gist.github.com/klement97/a4642de33510bf031bfa36f4590bdb97 %}

Let’s check out what does the signup form looks like now.

OK, now the backend is done and we are sure it is not going to accept weak passwords even if the frontend sends them. Let’s move to the front-end side.

Front-end

So let’s begin with the front-end side of the work. We are going to create a signup form and then integrate the password-strength component from material-extensions inside it.

Install the library, you can check out the versions to install the required one for your angular version. The latest is v.6.0.0 which is Angular v9 supported.

Make sure you have angular material installed and configured the right way and you have BrowserAnimationsModule inside the imports of app.module

ng add @angular/material  // if material is not already installed

ng add @angular-material-extensions/password-strength

The above command will automatically add MatPasswordStrengthModule inside the imports array of app.module.ts but I have a lazy-loaded auth module for the sign-up components so let's move the module inside auth.module.ts

Build Sign up form

So we have the following sign up form.

I have linked server errors to an ordered list just below the password field. If we try to sign up without a valid password we can see the server errors like so:

Now we have the server errors displayed to the user but come on, who wants to show errors like this? Let’s integrate the material design password strength component.

After we have imported MatPasswordStrengthModule inside our module now we can use the following strength meter and strength info. Let’s give an identifier to our password input.

<mat-form-field appearance="outline" class="full-width">
  <mat-label>Password</mat-label>
  <input **#password** type="password" matInput formControlName="password" />
</mat-form-field>

Below the password field add password strength meter and info.

...
formControlName="password" />
</mat-form-field>

<div style="margin-top: 10px; margin-bottom: 10px; width: 100%;">
  <mat-password-strength
          #strength
          [password]="password.value"
          [enableLengthRule]="true"
          [enableDigitRule]="true"
          [enableLowerCaseLetterRule]="true"
          [enableUpperCaseLetterRule]="true"
          [enableSpecialCharRule]="true"
  >
  </mat-password-strength>
  <mat-password-strength-info [passwordComponent]="strength">
  </mat-password-strength-info>
</div>

As you can see you can enable or disable rules as you wish. Now the form looks like this:

We have finished the basic integration. There are lots of customizations that can be done. Please visit here to see all of them. I am going to show one of them which is how to change messages displayed to the user.

Inside mat-strength-info we can do something like this:

<mat-password-strength-info
        [passwordComponent]="strength"
        [digitsCriteriaMsg]="'The password must contain at least 1 digit'"
        [minCharsCriteriaMsg]="'The password must contains at least 8 chars'"
        [specialCharsCriteriaMsg]="'The password must contain 1 special char like (!£$%^&*()@~?,/.)'"
>
</mat-password-strength-info>

By doing so you can give any message you like to the strength info component.

Conclusion

We wanted to increase the security level of passwords. We have begun with the backend validation and used only this validation at first by showing to the user whatever error message backend sent. After that to give our users a better experience we have used the mat-password-strength library and integrated it into our sign up form. Of course, it was easier to show the error messages of the backend and just leave it like so. But we want the user experience to be the best it can be, especially on a signup form everything must be easier and password validation is not an exception. If you want your users to do something you want then you need to ask them the correct way.

Thanks for reading.

Latest Article