Skip to content

Commit

Permalink
feat(core,schemas): add support for argon2d and argon2id (#6404)
Browse files Browse the repository at this point in the history
  • Loading branch information
wangsijie authored Aug 6, 2024
1 parent 43d5bd2 commit d56bc2f
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 3 deletions.
10 changes: 10 additions & 0 deletions .changeset/thirty-cups-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@logto/schemas": minor
"@logto/core": minor
---

add support for new password digest algorithm argon2d and argon2id

In `POST /users`, the `passwordAlgorithm` field now accepts `Argon2d` and `Argon2id`.

Users with those algorithms will be migrated to `Argon2i` upon succussful sign in.
39 changes: 38 additions & 1 deletion packages/core/src/libraries/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ describe('encryptUserPassword()', () => {
describe('verifyUserPassword()', () => {
const { verifyUserPassword } = createUserLibrary(queries);

describe('Argon2', () => {
describe('Argon2i', () => {
it('resolves when password is correct', async () => {
await expect(verifyUserPassword(mockUser, 'password')).resolves.not.toThrowError();
});
Expand All @@ -111,6 +111,43 @@ describe('verifyUserPassword()', () => {
});
});

describe('Argon2d', () => {
const user = {
...mockUser,
passwordEncrypted: '$argon2d$v=19$m=16,t=2,p=1$VW1JcEJrMjN1Vnp3Tm5JUA$Ddl/I6Zem7vbZ4r5jPCb/g',
passwordEncryptionMethod: UsersPasswordEncryptionMethod.Argon2d,
};

it('resolves when password is correct', async () => {
await expect(verifyUserPassword(user, 'password')).resolves.not.toThrowError();
});

it('rejects when password is incorrect', async () => {
await expect(verifyUserPassword(user, 'wrong')).rejects.toThrowError(
new RequestError({ code: 'session.invalid_credentials', status: 422 })
);
});
});

describe('Argon2id', () => {
const user = {
...mockUser,
passwordEncrypted:
'$argon2id$v=19$m=16,t=2,p=1$VW1JcEJrMjN1Vnp3Tm5JUA$0uzNwxbjs/f/1e5r4uX7JQ',
passwordEncryptionMethod: UsersPasswordEncryptionMethod.Argon2id,
};

it('resolves when password is correct', async () => {
await expect(verifyUserPassword(user, 'password')).resolves.not.toThrowError();
});

it('rejects when password is incorrect', async () => {
await expect(verifyUserPassword(user, 'wrong')).rejects.toThrowError(
new RequestError({ code: 'session.invalid_credentials', status: 422 })
);
});
});

describe('MD5', () => {
const user = {
...mockUser,
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/libraries/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ export const createUserLibrary = (queries: Queries) => {
);

switch (passwordEncryptionMethod) {
case UsersPasswordEncryptionMethod.Argon2i: {
// Argon2i, Argon2id, Argon2d shares the same verify function
case UsersPasswordEncryptionMethod.Argon2i:
case UsersPasswordEncryptionMethod.Argon2id:
case UsersPasswordEncryptionMethod.Argon2d: {
const result = await argon2Verify({ password, hash: passwordEncrypted });
assertThat(result, new RequestError({ code: 'session.invalid_credentials', status: 422 }));
break;
Expand Down
35 changes: 35 additions & 0 deletions packages/schemas/alterations/next-1722926389-argon2d-argon2id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { sql } from '@silverhand/slonik';

import type { AlterationScript } from '../lib/types/alteration.js';

const alteration: AlterationScript = {
up: async (pool) => {
await pool.query(sql`
alter type users_password_encryption_method add value 'Argon2id';
alter type users_password_encryption_method add value 'Argon2d';
`);
},
down: async (pool) => {
const { rows } = await pool.query(sql`
select id from users
where password_encryption_method = ${'Argon2id'}
or password_encryption_method = ${'Argon2d'}
`);
if (rows.length > 0) {
throw new Error('There are users with password encryption methods Argon2id or Argon2d.');
}

await pool.query(sql`
create type users_password_encryption_method_revised as enum ('Argon2i', 'SHA1', 'SHA256', 'MD5', 'Bcrypt');
alter table users
alter column password_encryption_method type users_password_encryption_method_revised
using password_encryption_method::text::users_password_encryption_method_revised;
drop type users_password_encryption_method;
alter type users_password_encryption_method_revised rename to users_password_encryption_method;
`);
},
};

export default alteration;
2 changes: 1 addition & 1 deletion packages/schemas/tables/users.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* init_order = 1 */

create type users_password_encryption_method as enum ('Argon2i', 'SHA1', 'SHA256', 'MD5', 'Bcrypt');
create type users_password_encryption_method as enum ('Argon2i', 'Argon2id', 'Argon2d', 'SHA1', 'SHA256', 'MD5', 'Bcrypt');

create table users (
tenant_id varchar(21) not null
Expand Down

0 comments on commit d56bc2f

Please sign in to comment.