Skip to content

Commit 1fbd99a

Browse files
gappleatinux
andauthored
feat: Add utility for checking outdated password hashes during login flow (#471)
Co-authored-by: Sébastien Chopin <seb@nuxt.com> Co-authored-by: Sébastien Chopin <atinux@gmail.com>
1 parent cc97f7d commit 1fbd99a

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,17 @@ if (await verifyPassword(hashedPassword, 'user_password')) {
299299
}
300300
```
301301

302+
It also provides a `passwordNeedsRehash` function to check if a password needs to be rehashed. This is useful when the hash settings are changed, such as as increasing the scrypt cost parameters.
303+
304+
```ts
305+
const needsRehash = await passwordNeedsRehash(hashedPassword)
306+
307+
if (needsRehash) {
308+
// Password needs to be rehashed
309+
hashedPassword = await hashPassword('user_password')
310+
}
311+
```
312+
302313
You can configure the scrypt options in your `nuxt.config.ts`:
303314

304315
```ts

playground/server/api/login.post.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export default defineEventHandler(async (event) => {
3030
throw invalidCredentialsError
3131
}
3232

33+
if (passwordNeedsReHash(password)) {
34+
await db.sql`UPDATE users SET password = ${hashPassword(password)} WHERE id = ${user.id}`
35+
}
36+
3337
await setUserSession(event, {
3438
user: {
3539
email,

src/runtime/server/utils/password.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,23 @@ export async function hashPassword(password: string) {
4242
export async function verifyPassword(hashedPassword: string, plainPassword: string) {
4343
return await getHash().verify(hashedPassword, plainPassword)
4444
}
45+
46+
/**
47+
* Check if the hash value needs a rehash or not. The rehash is required if
48+
* configuration settings have changed.
49+
* @param hashedPassword - The hashed password to check
50+
* @returns `true` if a rehash is needed, `false` otherwise
51+
* @example
52+
* ```ts
53+
* const isValid = await verifyPassword(hashedPassword, plainText)
54+
*
55+
* // Plain password is valid, and hash needs a rehash
56+
* if (isValid && passwordNeedsReHash(hashedPassword)) {
57+
* const newHash = await hashPassword(plainText)
58+
* }
59+
* ```
60+
* @more you can configure the scrypt options in `auth.hash.scrypt`
61+
*/
62+
export function passwordNeedsReHash(hashedPassword: string) {
63+
return getHash().needsReHash(hashedPassword)
64+
}

0 commit comments

Comments
 (0)