0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(core): encryptUserPassword (#135)

This commit is contained in:
Wang Sijie 2021-11-18 16:29:24 +08:00 committed by GitHub
parent 7d7b8112f6
commit 3480d05366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 23 deletions

View file

@ -1,6 +1,8 @@
import { PasswordEncryptionMethod } from '@logto/schemas';
import { hasUserWithId } from '@/queries/user';
import { generateUserId } from './user';
import { encryptUserPassword, generateUserId } from './user';
jest.mock('@/queries/user');
@ -48,3 +50,13 @@ describe('generateUserId()', () => {
expect(mockedHasUserWithId).toBeCalledTimes(11);
});
});
describe('encryptUserPassword()', () => {
it('generates salt, encrypted and method', () => {
const { passwordEncryptionMethod, passwordEncrypted, passwordEncryptionSalt } =
encryptUserPassword('user-id', 'password');
expect(passwordEncryptionMethod).toEqual(PasswordEncryptionMethod.SaltAndPepper);
expect(passwordEncrypted).toHaveLength(64);
expect(passwordEncryptionSalt).toHaveLength(21);
});
});

View file

@ -1,7 +1,10 @@
import { PasswordEncryptionMethod } from '@logto/schemas';
import { nanoid } from 'nanoid';
import pRetry from 'p-retry';
import { hasUserWithId } from '@/queries/user';
import { buildIdGenerator } from '@/utils/id';
import { encryptPassword } from '@/utils/password';
const userId = buildIdGenerator(12);
@ -18,3 +21,23 @@ export const generateUserId = async (retries = 500) =>
},
{ retries, factor: 0 } // No need for exponential backoff
);
export const encryptUserPassword = (
userId: string,
password: string
): {
passwordEncryptionSalt: string;
passwordEncrypted: string;
passwordEncryptionMethod: PasswordEncryptionMethod;
} => {
const passwordEncryptionSalt = nanoid();
const passwordEncryptionMethod = PasswordEncryptionMethod.SaltAndPepper;
const passwordEncrypted = encryptPassword(
userId,
password,
passwordEncryptionSalt,
passwordEncryptionMethod
);
return { passwordEncrypted, passwordEncryptionMethod, passwordEncryptionSalt };
};

View file

@ -1,11 +1,10 @@
import { PasswordEncryptionMethod, userInfoSelectFields } from '@logto/schemas';
import { userInfoSelectFields } from '@logto/schemas';
import pick from 'lodash.pick';
import { nanoid } from 'nanoid';
import { Provider } from 'oidc-provider';
import { object, string } from 'zod';
import RequestError from '@/errors/RequestError';
import { generateUserId } from '@/lib/user';
import { encryptUserPassword, generateUserId } from '@/lib/user';
import koaGuard from '@/middleware/koa-guard';
import {
deleteUserById,
@ -15,7 +14,6 @@ import {
insertUser,
updateUserById,
} from '@/queries/user';
import { encryptPassword } from '@/utils/password';
import { AnonymousRouter } from './types';
@ -36,14 +34,9 @@ export default function userRoutes<T extends AnonymousRouter>(router: T, provide
}
const id = await generateUserId();
const passwordEncryptionSalt = nanoid();
const passwordEncryptionMethod = PasswordEncryptionMethod.SaltAndPepper;
const passwordEncrypted = encryptPassword(
id,
password,
passwordEncryptionSalt,
passwordEncryptionMethod
);
const { passwordEncryptionSalt, passwordEncrypted, passwordEncryptionMethod } =
encryptUserPassword(id, password);
await insertUser({
id,
@ -102,14 +95,7 @@ export default function userRoutes<T extends AnonymousRouter>(router: T, provide
await findUserById(userId);
const passwordEncryptionSalt = nanoid();
const passwordEncryptionMethod = PasswordEncryptionMethod.SaltAndPepper;
const passwordEncrypted = encryptPassword(
userId,
password,
passwordEncryptionSalt,
passwordEncryptionMethod
);
const { passwordEncrypted, passwordEncryptionSalt } = encryptUserPassword(userId, password);
await updateUserById(userId, {
passwordEncryptionSalt,

View file

@ -2,16 +2,17 @@ import { createHash } from 'crypto';
import { PasswordEncryptionMethod } from '@logto/schemas';
import { assertEnv, repeat } from '@silverhand/essentials';
import { nanoid } from 'nanoid';
import { number, string } from 'zod';
import assertThat from '@/utils/assert-that';
const peppers = string()
.array()
.parse(JSON.parse(assertEnv('PASSWORD_PEPPERS')));
.parse(process.env.NODE_ENV === 'test' ? [nanoid()] : JSON.parse(assertEnv('PASSWORD_PEPPERS')));
const iterationCount = number()
.min(100)
.parse(Number(assertEnv('PASSWORD_INTERATION_COUNT')));
.parse(process.env.NODE_ENV === 'test' ? 1000 : Number(assertEnv('PASSWORD_INTERATION_COUNT')));
export const encryptPassword = (
id: string,