diff --git a/docs/authentication-and-access-control/password-management.md b/docs/authentication-and-access-control/password-management.md index f45e3aa851..a9cbe32cf8 100644 --- a/docs/authentication-and-access-control/password-management.md +++ b/docs/authentication-and-access-control/password-management.md @@ -13,7 +13,6 @@ The `hashPassword` utility uses the [PBKDF2](https://en.wikipedia.org/wiki/PBKDF | Name | Type | Default value | | --- | --- | --- | | plainTextPassword | string | | -| options | `{ legacy?: boolean }` | `{}` | **Return type** @@ -25,8 +24,7 @@ Promise The `verifyPassword` takes three arguments: - the password to check in plain text, -- the password hash (usually fetched from the database), -- and an optional `options` object (see below). +- and the password hash (usually fetched from the database). **Parameters** @@ -34,12 +32,9 @@ The `verifyPassword` takes three arguments: | --- | --- | --- | | plainTextPassword | string | | | passwordHash | string | | -| options | `{ legacy?: boolean }` | `{}` | **Return type** ```typescript Promise ``` - -> If you used the `parsePassword` function in previous versions of Foal (<0.7.0), you must pass the `legacy: true` option to `verifyPassword` and `hashPassword`. diff --git a/packages/core/src/common/utils/hash-password.util.spec.ts b/packages/core/src/common/utils/hash-password.util.spec.ts index 293c79aa56..c62cfe2ebd 100644 --- a/packages/core/src/common/utils/hash-password.util.spec.ts +++ b/packages/core/src/common/utils/hash-password.util.spec.ts @@ -25,22 +25,4 @@ describe('hashPassword', () => { strictEqual(derivedKey, expectedBuffer.toString('base64')); }); - it('should be able to salt and hash the plain password using the legacy way (old parsePassword util).', async () => { - const plainPassword = 'hello world'; - const actual = await hashPassword(plainPassword, { legacy: true }); - - strictEqual(typeof actual, 'string'); - const [ algorithm, iterations, salt, derivedKey] = actual.split('$'); - - strictEqual(algorithm, 'pbkdf2_sha256'); - strictEqual(parseInt(iterations, 10), 100000); - strictEqual(salt.length, 32); // 16 * 2 - strictEqual(derivedKey.length, 128); // 64 * 2 - - const expectedBuffer = await promisify(pbkdf2)( - plainPassword, salt, parseInt(iterations, 10), 64, 'sha256' - ); - strictEqual(expectedBuffer.toString('hex'), derivedKey); - }); - }); diff --git a/packages/core/src/common/utils/hash-password.util.ts b/packages/core/src/common/utils/hash-password.util.ts index f0948fc244..3eca22385d 100644 --- a/packages/core/src/common/utils/hash-password.util.ts +++ b/packages/core/src/common/utils/hash-password.util.ts @@ -1,24 +1,11 @@ import { pbkdf2, randomBytes } from 'crypto'; import { promisify } from 'util'; -/** - * Legacy function to hash passwords. Only kept for backward compatibility. - * @param password - */ -async function parsePassword(password: string): Promise { - const salt = (await promisify(randomBytes)(16)).toString('hex'); - const iterations = 100000; - const keylen = 64; - const digest = 'sha256'; - const derivedKey = await promisify(pbkdf2)(password, salt, iterations, keylen, digest); - return `pbkdf2_${digest}$${iterations}$${salt}$${derivedKey.toString('hex')}`; -} - /** * Hash a password using the PBKDF2 algorithm. * * Configured to use PBKDF2 + HMAC + SHA256. - * The result is a 64 byte binary string (or hex if the legacy option is true). + * The result is a 64 byte binary string. * * The random salt is 16 bytes long. * The number of iterations is 150000. @@ -26,14 +13,9 @@ async function parsePassword(password: string): Promise { * * @export * @param {string} plainTextPassword - The password to hash. - * @param {{ legacy?: boolean }} [options={}] * @returns {Promise} The derived key with the algorithm name, the number of iterations and the salt. */ -export async function hashPassword(plainTextPassword: string, - options: { legacy?: boolean } = {}): Promise { - if (options.legacy) { - return parsePassword(plainTextPassword); - } +export async function hashPassword(plainTextPassword: string): Promise { const saltBuffer = await promisify(randomBytes)(16); const iterations = 150000; const keylen = 32; diff --git a/packages/core/src/common/utils/verify-password.util.spec.ts b/packages/core/src/common/utils/verify-password.util.spec.ts index be00047666..de893dc0b2 100644 --- a/packages/core/src/common/utils/verify-password.util.spec.ts +++ b/packages/core/src/common/utils/verify-password.util.spec.ts @@ -51,13 +51,4 @@ describe('verifyPassword', () => { strictEqual(await verifyPassword('wrong password', passwordHash), false); }); - it('should verify password hashes created from hashPassword with the legacy' - + ' option (old parsePassword).', async () => { - const plainPassword = 'hello world'; - const passwordHash = await hashPassword(plainPassword, { legacy: true }); - - ok(await verifyPassword(plainPassword, passwordHash, { legacy: true })); - strictEqual(await verifyPassword('wrong password', passwordHash, { legacy: true }), false); - }); - }); diff --git a/packages/core/src/common/utils/verify-password.util.ts b/packages/core/src/common/utils/verify-password.util.ts index c1a9c1d951..06a68f156f 100644 --- a/packages/core/src/common/utils/verify-password.util.ts +++ b/packages/core/src/common/utils/verify-password.util.ts @@ -8,12 +8,9 @@ import { promisify } from 'util'; * @export * @param {string} plainTextPassword - The password in clear text. * @param {string} passwordHash - The password hash generated by the `hashPassword` function. - * @param {{ legacy?: boolean }} [options={}] * @returns {Promise} True if the hash and the password match. False otherwise. */ -export async function verifyPassword(plainTextPassword: string, passwordHash: string, - options: { legacy?: boolean } = {}): Promise { - const legacy = options.legacy || false; +export async function verifyPassword(plainTextPassword: string, passwordHash: string): Promise { const [ algorithm, iterations, salt, derivedKey ] = passwordHash.split('$'); strictEqual(algorithm, 'pbkdf2_sha256', 'Invalid algorithm.'); @@ -23,12 +20,12 @@ export async function verifyPassword(plainTextPassword: string, passwordHash: st strictEqual(typeof derivedKey, 'string', 'Invalid password format.'); strictEqual(isNaN(parseInt(iterations, 10)), false, 'Invalid password format.'); - const saltBuffer = Buffer.from(salt, legacy ? 'hex' : 'base64'); - const derivedKeyBuffer = Buffer.from(derivedKey, legacy ? 'hex' : 'base64'); + const saltBuffer = Buffer.from(salt, 'base64'); + const derivedKeyBuffer = Buffer.from(derivedKey, 'base64'); const digest = 'sha256'; // TODO: depends on the algorthim var const password = await promisify(pbkdf2)( plainTextPassword, - legacy ? saltBuffer.toString('hex') : saltBuffer, + saltBuffer, parseInt(iterations, 10), derivedKeyBuffer.length, digest