-
Notifications
You must be signed in to change notification settings - Fork 460
prevent use of common password using the haveibeenpwned password api #958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
c54b3fd
963b990
203592d
8c7723d
ccbb669
cc0348e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import crypto from 'node:crypto' | ||
| import { type Connection, type Password, type User } from '@prisma/client' | ||
| import bcrypt from 'bcryptjs' | ||
| import { redirect } from 'react-router' | ||
|
|
@@ -255,3 +256,33 @@ export async function verifyUserPassword( | |
|
|
||
| return { id: userWithPassword.id } | ||
| } | ||
|
|
||
| export async function checkCommonPassword(password: string) { | ||
| const hash = crypto | ||
| .createHash('sha1') | ||
| .update(password, 'utf8') | ||
| .digest('hex') | ||
| .toUpperCase() | ||
|
|
||
| const [prefix, suffix] = [hash.slice(0, 5), hash.slice(5)] | ||
|
|
||
| const controller = new AbortController() | ||
|
|
||
| try { | ||
| const timeoutId = setTimeout(() => controller.abort(), 1000) | ||
|
|
||
| const res = await fetch(`https://api.pwnedpasswords.com/range/${prefix}`) | ||
|
|
||
| clearTimeout(timeoutId) | ||
|
|
||
| if (!res.ok) false | ||
|
|
||
| const data = await res.text() | ||
| return data.split('/\r?\n/').some((line) => line.includes(suffix)) | ||
| } catch (error) { | ||
| if (error instanceof DOMException && error.name === 'AbortError') { | ||
| console.warn('Password check timed out') | ||
| } | ||
| return false | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be a good idea to add a warning if any other kind of error is thrown so we at least have some visibility into whether things are working. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah completely forgot about it |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { http, HttpResponse } from 'msw' | ||
AdityaKirad marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| export const pwnedPasswordApiHandler = http.get( | ||
| 'https://api.pwnedpasswords.com/range/:prefix', | ||
| () => { | ||
| return new HttpResponse('', { status: 200 }) | ||
| }, | ||
| ) | ||
Uh oh!
There was an error while loading. Please reload this page.