Password Strength Checker

Password Strength Checker

Dependencies:

- Python 3

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Install requirements:

CMD / Terminal
pip3 install fastapi==0.87.0 uvicorn==0.20.0 graphene==3.1.1 strawberry-graphql==0.142.2

1. Let's start by creating some rules for passwords.

min_size: Checks the minimum password length
min_upper_case: Checks if it has the minimum upper case letters
min_lower_case: Checks if it has the minimum lower case letters
min_digit: Checks if the password has the minimum required digits
min_special_chars: Checks if the password has the minimum special characters
no_repeted: Checks if the password has repeated sequential letters

rules_password.py
import re

def min_size(string, value) -> bool:
    if len(string) < value:
        return False
    return True

def min_upper_case(string, value) -> bool:
    countUpperCaseChars = sum(1 for c in string if c.isupper())
    
    if countUpperCaseChars < value:
        return False
    return True

def min_lower_case(string, value) -> bool:
    countLowerCaseChars = sum(1 for c in string if c.islower())
    
    if countLowerCaseChars < value:
        return False
    return True

def min_digit(string, value) -> bool:
    countDigits = sum(1 for c in string if c.isdigit())
    
    if countDigits < value:
        return False
    return True

def min_special_chars(string, value) -> bool:
    specialChars = r'!@#$%^&*()-+\/{}[]'    
    countSpecialChars = sum(string.count(c) for c in list(specialChars))
    
    if countSpecialChars < value:
        return False
    return True

def no_repeted(string, value) -> bool:
    # https://stackoverflow.com/a/28007115    
    if re.search(r'(.)\1', string):
        return False
    return True

to_do

main.py
import strawberry
from typing import List
from fastapi import FastAPI
from strawberry.asgi import GraphQL
# Local import
from rules_password import *

@strawberry.type
class Response:
    verify: bool
    noMatch: List[str]

@strawberry.input
class Rules:
    rule: str
    value: int

@strawberry.type
class Query:
    @strawberry.field
    def verify(self, password,  rules) -> Response:
        
        # Relates the rules available in GraphQL with the name of the functions in rules_password.py
        dictFunctions = {
            "minSize": min_size,
            "minUppercase": min_upper_case,
            "minLowercase": min_lower_case,
            "minDigit": min_digit,
            "minSpecialChars": min_special_chars,
            "noRepeted": no_repeted,
        }
        
        # For each rule input in GraphQL, call the function and relate the name of the rule with the return to its function
        dictResponse = {}
        for ruleInput in rules:
            dictResponse[ruleInput.rule] = dictFunctions[ruleInput.rule](password, ruleInput.value)
            # Example: dictResponse["minSize"] = False (False it's return of min_size(string, value))
        
        if all(list(dictResponse.values())):
            # Returns empty "noMatch" attribute if all values in dictResponse are True
            return Response(verify=True, noMatch=[""])
        else:
            # Return the rules that did not pass in the "noMatch" attribute
            wrongChecks = [response for response in dictResponse if dictResponse[response] == False]
            return Response(verify=False, noMatch=wrongChecks)

schema = strawberry.Schema(query=Query)
graphql_app = GraphQL(schema)

app = FastAPI()
app.add_route("/graphql", graphql_app)
app.add_websocket_route("/graphql", graphql_app)

This is all required code.


Example of use:

Go go http://localhost:8000/graphql and you can insert queries like this:

Query Input
query {
    verify(password: "TestStrengthPassword!123&", rules: [
          {rule: "minSize", value: 10},
          {rule: "minUppercase", value: 5},
          {rule: "minLowercase", value: 3},
          {rule: "minDigit", value: 2}
          {rule: "minSpecialChars", value: 2}
          {rule: "noRepeted", value: 0}
    ]) {
        verify
        noMatch
    }
}
Output
{
    "data": {
        "verify": {
        "verify": false,
        "noMatch": [
            "minUppercase",
            "minDigit",
            "noRepeted"
        ]
        }
    }
}

For use like a API, make a POST to http://localhost:8000/graphql

example_use.py
import json
import requests

url = "http://localhost:8000/graphql"
    
body = """
query {
    verify(password: "TestStrengthPassword!12&", rules: [
        {rule: "minSize", value: 10},
        {rule: "minUppercase", value: 5},
        {rule: "minLowercase", value: 3},
        {rule: "minDigit", value: 3},
        {rule: "minSpecialChars", value: 2},
        {rule: "noRepeted", value: 0},
    ]) {
        verify
        noMatch
    }
}
"""

print(body)
response = requests.post(url=url, json={"query": body})
print("response status code: ", response.status_code)
if response.status_code == 200:
    parsed = json.loads(response.content)
    print("response : ", json.dumps(parsed, indent=4))

# response status code:  200
# response :  {
#     "data": {
#         "verify": {
#             "verify": false,
#             "noMatch": [
#                 "minUppercase",
#                 "minDigit",
#                 "noRepeted"
#             ]
#         }
#     }
# }

and its done!


All the code is available here too: Github - Password-Strength-Checker

CMD / Terminal
git clone https://github.com/AlfredoFilho/Password-Strength-Checker.git