Skip to content

Commit 7b35c09

Browse files
committed
feat: add handlePasswordValidation + tests
1 parent fd492d3 commit 7b35c09

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

src/node/util.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,66 @@ export function getPasswordMethod(hashedPassword: string | undefined): PasswordM
189189
return "SHA256"
190190
}
191191

192+
type PasswordValidation = {
193+
isPasswordValid: boolean
194+
hashedPassword: string
195+
}
196+
197+
type HandlePasswordValidationArgs = {
198+
/** The PasswordMethod */
199+
passwordMethod: PasswordMethod
200+
/** The password provided by the user */
201+
passwordFromRequestBody: string
202+
/** The password set in PASSWORD or config */
203+
passwordFromArgs: string | undefined
204+
/** The hashed-password set in HASHED_PASSWORD or config */
205+
hashedPasswordFromArgs: string | undefined
206+
}
207+
208+
/**
209+
* Checks if a password is valid and also returns the hash
210+
* using the PasswordMethod
211+
*/
212+
export async function handlePasswordValidation(
213+
passwordValidationArgs: HandlePasswordValidationArgs,
214+
): Promise<PasswordValidation> {
215+
const { passwordMethod, passwordFromArgs, passwordFromRequestBody, hashedPasswordFromArgs } = passwordValidationArgs
216+
// TODO implement
217+
const passwordValidation = <PasswordValidation>{
218+
isPasswordValid: false,
219+
hashedPassword: "",
220+
}
221+
222+
switch (passwordMethod) {
223+
case "PLAIN_TEXT": {
224+
const isValid = passwordFromArgs ? safeCompare(passwordFromRequestBody, passwordFromArgs) : false
225+
passwordValidation.isPasswordValid = isValid
226+
227+
const hashedPassword = await hash(passwordFromRequestBody)
228+
passwordValidation.hashedPassword = hashedPassword
229+
break
230+
}
231+
case "SHA256": {
232+
const isValid = isHashLegacyMatch(passwordFromRequestBody, hashedPasswordFromArgs || "")
233+
passwordValidation.isPasswordValid = isValid
234+
235+
passwordValidation.hashedPassword = hashedPasswordFromArgs || (await hashLegacy(passwordFromRequestBody))
236+
break
237+
}
238+
case "ARGON2": {
239+
const isValid = await isHashMatch(passwordFromRequestBody, hashedPasswordFromArgs || "")
240+
passwordValidation.isPasswordValid = isValid
241+
242+
passwordValidation.hashedPassword = hashedPasswordFromArgs || ""
243+
break
244+
}
245+
default:
246+
break
247+
}
248+
249+
return passwordValidation
250+
}
251+
192252
const mimeTypes: { [key: string]: string } = {
193253
".aac": "audio/x-aac",
194254
".avi": "video/x-msvideo",

test/unit/node/util.test.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
hash,
33
isHashMatch,
4+
handlePasswordValidation,
45
PasswordMethod,
56
getPasswordMethod,
67
hashLegacy,
@@ -232,3 +233,92 @@ describe("getPasswordMethod", () => {
232233
expect(passwordMethod).toEqual(expected)
233234
})
234235
})
236+
237+
describe.only("handlePasswordValidation", () => {
238+
it("should return true with a hashedPassword for a PLAIN_TEXT password", async () => {
239+
const p = "password"
240+
const passwordValidation = await handlePasswordValidation({
241+
passwordMethod: "PLAIN_TEXT",
242+
passwordFromRequestBody: p,
243+
passwordFromArgs: p,
244+
hashedPasswordFromArgs: undefined,
245+
})
246+
247+
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
248+
249+
expect(passwordValidation.isPasswordValid).toBe(true)
250+
expect(matchesHash).toBe(true)
251+
})
252+
it("should return false when PLAIN_TEXT password doesn't match args", async () => {
253+
const p = "password"
254+
const passwordValidation = await handlePasswordValidation({
255+
passwordMethod: "PLAIN_TEXT",
256+
passwordFromRequestBody: "password1",
257+
passwordFromArgs: p,
258+
hashedPasswordFromArgs: undefined,
259+
})
260+
261+
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
262+
263+
expect(passwordValidation.isPasswordValid).toBe(false)
264+
expect(matchesHash).toBe(false)
265+
})
266+
it("should return true with a hashedPassword for a SHA256 password", async () => {
267+
const p = "helloworld"
268+
const passwordValidation = await handlePasswordValidation({
269+
passwordMethod: "SHA256",
270+
passwordFromRequestBody: p,
271+
passwordFromArgs: undefined,
272+
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
273+
})
274+
275+
const matchesHash = isHashLegacyMatch(p, passwordValidation.hashedPassword)
276+
277+
expect(passwordValidation.isPasswordValid).toBe(true)
278+
expect(matchesHash).toBe(true)
279+
})
280+
it("should return false when SHA256 password doesn't match hash", async () => {
281+
const p = "helloworld1"
282+
const passwordValidation = await handlePasswordValidation({
283+
passwordMethod: "SHA256",
284+
passwordFromRequestBody: p,
285+
passwordFromArgs: undefined,
286+
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
287+
})
288+
289+
const matchesHash = isHashLegacyMatch(p, passwordValidation.hashedPassword)
290+
291+
expect(passwordValidation.isPasswordValid).toBe(false)
292+
expect(matchesHash).toBe(false)
293+
})
294+
it("should return true with a hashedPassword for a ARGON2 password", async () => {
295+
const p = "password"
296+
const passwordValidation = await handlePasswordValidation({
297+
passwordMethod: "ARGON2",
298+
passwordFromRequestBody: p,
299+
passwordFromArgs: undefined,
300+
hashedPasswordFromArgs:
301+
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
302+
})
303+
304+
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
305+
306+
expect(passwordValidation.isPasswordValid).toBe(true)
307+
expect(matchesHash).toBe(true)
308+
})
309+
it("should return false when ARGON2 password doesn't match hash", async () => {
310+
const p = "password1"
311+
const passwordValidation = await handlePasswordValidation({
312+
passwordMethod: "ARGON2",
313+
passwordFromRequestBody: p,
314+
passwordFromArgs: undefined,
315+
hashedPasswordFromArgs:
316+
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
317+
})
318+
319+
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
320+
321+
expect(passwordValidation.isPasswordValid).toBe(false)
322+
expect(matchesHash).toBe(false)
323+
})
324+
})

0 commit comments

Comments
 (0)