From c5ae40278774d427d544830ae8859deae38f6d43 Mon Sep 17 00:00:00 2001 From: Joel Biddle Date: Tue, 22 Aug 2023 18:14:03 +1000 Subject: [PATCH] Added comments to explain breach passwords API --- .../checks/checkIsPasswordBreached.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/utilities/checks/checkIsPasswordBreached.ts b/frontend/src/components/utilities/checks/checkIsPasswordBreached.ts index 623b43413..e032ebd91 100644 --- a/frontend/src/components/utilities/checks/checkIsPasswordBreached.ts +++ b/frontend/src/components/utilities/checks/checkIsPasswordBreached.ts @@ -2,7 +2,15 @@ import axios from "axios"; import crypto from "crypto"; // added types from @types/node export const checkIsPasswordBreached = async (password: string) => { - const dataBreachCheckAPIBaseURL = "https://api.pwnedpasswords.com/range/"; + // see API details here: https://haveibeenpwned.com/API/v3#SearchingPwnedPasswordsByRange + // in short, the pending password is hashed (SHA-1), fist 5 chars are sliced and compared against a ranged hash table + // if there is a match, that password has been involved in a password breach and should not be accepted + + // the database consists of ~700 mln breached passwords and is continuously being updated including with data from the FBI & the UK's NCA + // https://www.troyhunt.com/open-source-pwned-passwords-with-fbi-feed-and-225m-new-nca-passwords-is-now-live/ + + const dataBreachCheckAPIBaseURL = "https://api.pwnedpasswords.com/range/"; // added to CSP + try { const textEncoder = new TextEncoder(); const encodedPwd = textEncoder.encode(password); @@ -13,24 +21,21 @@ export const checkIsPasswordBreached = async (password: string) => { .join("") .toUpperCase(); + // Ensure that ONLY the first five SHA-1 hash chars are sent over HTTPS const response = await axios.get(`${dataBreachCheckAPIBaseURL}${hashedPwd.slice(0, 5)}`); - console.log("response:", response); // delete later!!! - const responseData = response.data.toUpperCase(); - console.log("responseData:", responseData); // delete later!!! - const isBreachedPassword = responseData.includes(hashedPwd.slice(5, 40)); - console.log("isBreachedPassword:", isBreachedPassword); // delete later!!! - // Clear the hashed password from memory + // Clear the hashed password from memory (good practice) const zeroBuffer = new Uint8Array(encodedPwd.length); encodedPwd.set(zeroBuffer); - return isBreachedPassword; + return isBreachedPassword; // boolean } catch (err: any) { if (axios.isAxiosError(err) && err.response && err.response.status === 429) { console.error("Received a 429 response from the Pwnd Passwords API"); - // Handle the 429 error here + // Handle the 429 error here (not 100% sure what the rate limits are for the password API) + // an error here should not cause a fail of setting/resetting/changing the password } else { console.error(err); }