mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Password breach check
This commit is contained in:
@@ -46,6 +46,7 @@ type Errors = {
|
||||
number?: string,
|
||||
specialChar?: string,
|
||||
repeatedChar?: string,
|
||||
breachedPassword?: string
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ export default function UserInfoStep({
|
||||
setOrganizationNameError(false);
|
||||
}
|
||||
|
||||
errorCheck = checkPassword({
|
||||
errorCheck = await checkPassword({
|
||||
password,
|
||||
commonPasswords,
|
||||
setErrors
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import axios from "axios";
|
||||
import crypto from "crypto";
|
||||
|
||||
///// REMINDER: ensure all logs are deleted!!! /////
|
||||
|
||||
export const checkIsPasswordBreached = async (password: string) => {
|
||||
const dataBreachCheckAPIBaseURL = "https://api.pwnedpasswords.com/range/";
|
||||
try {
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
const encodedPwd = textEncoder.encode(password);
|
||||
console.log("encodedPwd:", encodedPwd); // delete later!!!
|
||||
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-1", encodedPwd);
|
||||
console.log("hashBuffer:", hashBuffer); // delete later!!!
|
||||
|
||||
const hashedPwd = Array.from(new Uint8Array(hashBuffer))
|
||||
.map((byte) => byte.toString(16).padStart(2, "0"))
|
||||
.join("")
|
||||
.toUpperCase();
|
||||
|
||||
console.log("hashedPwd:", hashedPwd); // delete later!!!
|
||||
|
||||
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
|
||||
crypto.subtle.digest("SHA-1", encodedPwd);
|
||||
|
||||
return isBreachedPassword;
|
||||
} 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
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
import { checkIsPasswordBreached } from "./checkIsPasswordBreached";
|
||||
|
||||
type Errors = {
|
||||
tooShort?: string,
|
||||
tooLong?: string,
|
||||
@@ -6,7 +8,8 @@ type Errors = {
|
||||
number?: string,
|
||||
specialChar?: string,
|
||||
repeatedChar?: string,
|
||||
commonPassword?: string
|
||||
commonPassword?: string,
|
||||
breachedPassword?: string
|
||||
};
|
||||
|
||||
interface CheckPasswordParams {
|
||||
@@ -32,13 +35,15 @@ interface CheckPasswordParams {
|
||||
* @param {String} obj.password - the password to check
|
||||
* @param {Function} obj.setErrors - set state function to set error object
|
||||
*/
|
||||
const checkPassword = ({
|
||||
const checkPassword = async ({
|
||||
password,
|
||||
commonPasswords,
|
||||
setErrors
|
||||
}: CheckPasswordParams): boolean => {
|
||||
}: CheckPasswordParams): Promise<boolean> => {
|
||||
const errors: Errors = {};
|
||||
|
||||
|
||||
const isBreachedPassword = await checkIsPasswordBreached(password)
|
||||
|
||||
if (password.length < 14) {
|
||||
errors.tooShort = "at least 14 characters";
|
||||
}
|
||||
@@ -70,6 +75,10 @@ const checkPassword = ({
|
||||
if (commonPasswords.includes(password)) {
|
||||
errors.commonPassword = "No common passwords";
|
||||
}
|
||||
|
||||
if (isBreachedPassword) {
|
||||
errors.breachedPassword = "The password you provided is in a list of passwords commonly used on other websites. Please try again with a stronger password.";
|
||||
}
|
||||
|
||||
setErrors(errors);
|
||||
return Object.keys(errors).length > 0;
|
||||
|
||||
@@ -41,6 +41,7 @@ type Errors = {
|
||||
number?: string,
|
||||
specialChar?: string,
|
||||
repeatedChar?: string,
|
||||
breachedPassword?: string
|
||||
};
|
||||
|
||||
export default function SignupInvite() {
|
||||
@@ -80,7 +81,7 @@ export default function SignupInvite() {
|
||||
setLastNameError(false);
|
||||
}
|
||||
|
||||
errorCheck = checkPassword({
|
||||
errorCheck = await checkPassword({
|
||||
password,
|
||||
commonPasswords,
|
||||
setErrors
|
||||
|
||||
@@ -25,6 +25,7 @@ type Errors = {
|
||||
number?: string,
|
||||
specialChar?: string,
|
||||
repeatedChar?: string,
|
||||
breachedPassword?: string
|
||||
};
|
||||
|
||||
const schema = yup.object({
|
||||
@@ -53,8 +54,8 @@ export const ChangePasswordSection = () => {
|
||||
try {
|
||||
if (!user?.email) return;
|
||||
if (!commonPasswords) return;
|
||||
|
||||
const errorCheck = checkPassword({
|
||||
|
||||
const errorCheck = await checkPassword({
|
||||
password: newPassword,
|
||||
commonPasswords,
|
||||
setErrors
|
||||
|
||||
@@ -42,6 +42,7 @@ type Errors = {
|
||||
number?: string,
|
||||
specialChar?: string,
|
||||
repeatedChar?: string,
|
||||
breachedPassword?: string
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -99,7 +100,7 @@ export const UserInfoSSOStep = ({
|
||||
setOrganizationNameError(false);
|
||||
}
|
||||
|
||||
errorCheck = checkPassword({
|
||||
errorCheck = await checkPassword({
|
||||
password,
|
||||
commonPasswords,
|
||||
setErrors
|
||||
|
||||
Reference in New Issue
Block a user