Password Strength Checker
Dependencies:
- Python 3
In today's interconnected digital landscape, data security stands as an unyielding fortress guarding our most sensitive information. At its core lies the crucial factor of password strength, the first line of defense against unauthorized access and breaches. In this blog post, we embark on an enlightening journey into the realm of cybersecurity, exploring a potent alliance of two cutting-edge technologies: FastAPI and GraphQL, fueled by the Strawberry library. This dynamic combination promises not only to evaluate password robustness but also to deliver a developer's dream - a seamless and agile development experience.
Our exploration commences with the establishment of stringent password rules. These rules, including checks for minimum length, uppercase and lowercase character requirements, mandatory digits, essential special characters, and the prevention of sequential letter repetition, serve as the bedrock of password fortification.
We'll delve into the details of this powerful combination and show you how it can elevate the security of your applications to a whole new level.
Install requirements:
CMD / Terminal
pip3 install fastapi==0.87.0 uvicorn==0.31.1 graphene==3.1.1 strawberry-graphql==0.246.2
1. Let's start by creating some rules for passwords.
• min_size: This rule verifies the minimum password length.
• min_upper_case: It ensures the presence of a minimum number of uppercase letters.
• min_lower_case: This rule checks for the inclusion of a minimum number of lowercase letters.
• min_digit: It verifies if the password contains the required minimum digits.
• min_special_chars: This rule confirms the presence of the minimum required special characters.
• no_repeted: Lastly, it checks for the absence of repeated sequential letters in the password.
rules_password.py
import re
def min_size(string, value) -> bool:
return len(string) >= value
def count_matches(string, condition) -> int:
return sum(1 for c in string if condition(c))
def min_upper_case(string, value) -> bool:
return count_matches(string, str.isupper) >= value
def min_lower_case(string, value) -> bool:
return count_matches(string, str.islower) >= value
def min_digit(string, value) -> bool:
return count_matches(string, str.isdigit) >= value
def min_special_chars(string, value) -> bool:
special_chars = r'[!@#$%^&*()\-+\\\/{}\[\]]'
return len(re.findall(special_chars, string)) >= value
def no_repeted(string) -> bool:
# https://stackoverflow.com/a/28007115
return not re.search(r'(.)\1', string)
to_do
main.py
import inspect
import strawberry
from typing import List, Optional
from fastapi import FastAPI
from strawberry.asgi import GraphQL
from rules_password import *
@strawberry.type
class PasswordResponse:
isValid: bool
failedRules: List[str]
@strawberry.input
class Rules:
rule: str
value: Optional[int] = None
@strawberry.type
class Query:
@strawberry.field
def validatePassword(self, password, rules) -> PasswordResponse:
dictFunctions = {
"minSize": min_size,
"minUpperCase": min_upper_case,
"minLowerCase": min_lower_case,
"minDigit": min_digit,
"minSpecialChars": min_special_chars,
"noRepeted": no_repeted,
}
dictResponse = {}
for ruleInput in rules:
function = dictFunctions.get(ruleInput.rule)
if function:
num_params = len(inspect.signature(function).parameters)
if num_params == 1:
dictResponse[ruleInput.rule] = function(password)
elif num_params == 2:
dictResponse[ruleInput.rule] = function(password, ruleInput.value)
else:
dictResponse[ruleInput.rule] = False
if all(dictResponse.values()):
return PasswordResponse(isValid=True, failedRules=[])
else:
failed_checks = [rule for rule, passed in dictResponse.items() if not passed]
return PasswordResponse(isValid=False, failedRules=failed_checks)
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 {
validatePassword(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"},
]) {
isValid
failedRules
}
}
Output
response: {
"data": {
"validatePassword": {
"isValid": false,
"failedRules": [
"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 {
validatePassword(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"},
]) {
isValid
failedRules
}
}
"""
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": {
# "validatePassword": {
# "isValid": false,
# "failedRules": [
# "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