Building A Serverless Password Strength Validator
Uriel Bitton
AWS Cloud Consultant | The DynamoDB guy | AWS Certified | I help you supercharge your DynamoDB database ????
?? Hello there! Welcome to The Serverless Spotlight!
In this week's Serverless Challenge Edition, we’ll be building a password strength validator.
Verifying a user’s chosen password is a feature that every application needs no matter how simple or complex.
As such, verifying the user’s password must be performed on the server side and highly discouraged to be done on the client side.
Today, I’ll be guiding you through the steps of designing and implementing a serverless password strength checker microservice — so you can easily grab the design and code and use it for all of your custom authentication needs.
Let’s start designing!
Design & Tech Stack
Design Plan
The plan is to allow the user to submit a password (for an account creation use case). The password string will be sent to the server using a serverless function. The serverless function will define the acceptable parameters for a “strong” password and will return those to the client side.
Tech Stack
Implementation
AWS Lambda
In your AWS account, create a new Lambda function.
Choose Author from scratch and give it a name. I’ll call mine “password-checker”.
Choose the Node JS 20.x version and then click the create function button to create your function.
Once your function is created, you can now add the necessary code to verify a given password’s strength.
In the code section of the Lambda function that we just created, let’s add the following code:
exports.handler = async (event) => {
const { password } = JSON.parse(event.body);
// Password strength criteria
const lengthCriteria = password.length >= 8;
const upperCaseCriteria = /[A-Z]/.test(password);
const lowerCaseCriteria = /[a-z]/.test(password);
const numberCriteria = /[0-9]/.test(password);
const specialCharCriteria = /[^A-Za-z0-9]/.test(password);
const isStrongPassword = lengthCriteria && upperCaseCriteria && lowerCaseCriteria && numberCriteria && specialCharCriteria;
const response = {
statusCode: 200,
body: JSON.stringify({
passwordStrength: isStrongPassword ? 'Strong' : 'Weak',
criteria: {
lengthCriteria,
upperCaseCriteria,
lowerCaseCriteria,
numberCriteria,
specialCharCriteria
}
}),
};
return response;
};
The code above accepts a password string as a parameter from a fetch request from the frontend.
It then performs the following checks to determine if the password is strong or weak:
We then send back a response with two parameters.
If the provided password is strong we return the value “Strong” for passwordStrength otherwise we return “Weak”.
We also send back a criteria object listing which checks passed or failed for deeper details on the password’s strengths and weaknesses.
This is what your Lambda function should look like.
Before you deploy, make sure to rename the file index.mjs to index.js in the sidebar to the left as seen on the screenshot above. Since we are using Node JS version 20, the file name extension must use .js instead of the default .mjs.
AWS Lambda Function URL
Now that we’ve written our function code, we need to create a function URL to expose an endpoint for our client side to invoke.
You can follow this article if you’re not familiar with the process; it takes less than two minutes.
With the function URL copied on your device’s clipboard, we can now move on to built out the frontend client.
React JS App
Let’s create a new React JS app.
In your IDE’s terminal run the commands to create a new React App:
npx create-react-app password-strength-checker
cd into the directory now:
领英推荐
cd password-strength-checker
Going into the file App.js, we can now write our frontend code:
// src/PasswordChecker.js
import React, { useState } from "react";
const App = () => {
const [password, setPassword] = useState("");
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const handleCheckPassword = async () => {
setLoading(true);
try {
const response = await fetch("YOUR_LAMBDA_FUNCTION_ENDPOINT_URL", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
password,
}),
});
const data = await response.json();
setResult(data);
} catch (error) {
console.error("Error checking password:", error);
setResult(null);
} finally {
setLoading(false);
}
};
return (
<div>
<h2> Password Strength Checker </h2>
<input
type="password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={handleCheckPassword} disabled={loading}>
{loading ? "Checking..." : "Check Password"}
</button>
{result && (
<div>
<h3> Result: </h3>
<p> Password strength: {result.passwordStrength} </p>
<ul>
<li>
Length criteria:
{result.criteria.lengthCriteria ? "Met" : "Not met"}
</li>
<li>
Upper case criteria:
{result.criteria.upperCaseCriteria ? "Met" : "Not met"}
</li>
<li>
Lower case criteria:
{result.criteria.lowerCaseCriteria ? "Met" : "Not met"}
</li>
<li>
Number criteria:
{result.criteria.numberCriteria ? "Met" : "Not met"}
</li>
<li>
Special character criteria:
{result.criteria.specialCharCriteria ? "Met" : "Not met"}
</li>
</ul>
</div>
)}
</div>
);
};
export default App;
Let’s explain the code above.
We start by declaring three state variables:
1. “password” to capture the input password from the user.
2. “result” to hold the result object which is filled by the data returning from the server side lambda function.
3. “loading” that acts as a loading flag to show the user that the data is being fetched on the server side.
We then make a POST request to our Lambda function and await the result.
Once the data is returned by our serverless function, we set the result state variable with the data returned and catch any errors.
In the UI portion of the code above, we display an input for the user to enter a password string. Then with the condition that the data is returned from the serverless function, we display in the UI the results of the password strength and the criteria of checks it passed or failed.
Let’s try to run our code and view the results.
I have inputted my first name as the password string and i receive the results:
As expected, the password strength is weak. I can also see which criteria elements my password has met or not met.
Congratulations! You have just created a fully serverless password strength checker in only a few minutes.
AWS CloudWatch
In many cases your serverless functions will fail or run into some issues. To understand the causes and origins of these issues, it is often useful to view the logs of the functions.
These logs will produce fine-grained details on why and when a Lambda function failed or passed.
The best part is that you have nothing to configure, Lambda is automatically integrated with AWS CloudWatch which provides for you constant logging and monitoring of your AWS Lambda functions.
To view the logs for a particular function head over to your Lambda function page and find the Monitor menu link and click on View CloudWatch logs.
On the new tab you are redirected to, your AWS CloudWatch console, you will see some log groups at the bottom of the page:
Click on any of them to view logs for a particular Lambda function invocation.
As you can see below, I triggered an error on an earlier invocation to show you the details of the error.
I can see the line on which the error occured, the file name and the time as well.
CloudWatch provides me with details on why the error occurred and helps me better understand it and resolve it.
CloudWatch is a must-use for any Lambda usage and will also show all console log messages you add in your Lambda functions for easy debugging.
?? My name is Uriel Bitton and I hope you learned something of value in this edition of The Serverless Spotlight.
?? Please consider sharing it with your network to help others learn as well.
?? You can also explore my social media links here:
?? *my blog website is coming soon, so stay tuned for that.
?? I hope to see you in the next week's edition!
Uriel