0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

fix(api): fix password validation for /reset_password route (#3858)

Previously, the password validation logic for the `/reset_password`
route was reversed: An error was returned when the password was valid
and the operation would succeed when the password was invalid.

This commit fixes the logic to return an error when the validation fails
and proceed with resetting the password when the password is valid.
This commit is contained in:
George Kalpakas 2023-06-11 11:33:37 +03:00 committed by GitHub
parent 87acf824ed
commit 702d5c4971
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 34 deletions

View file

@ -0,0 +1,6 @@
---
'@verdaccio/server-fastify': patch
'@verdaccio/web': patch
---
Fix the password validation logic for the `/reset_password` route to ensure that the password is only reset if it is valid.

View file

@ -83,30 +83,31 @@ async function loginRoute(fastify: FastifyInstance) {
fastify.configInstance?.server?.passwordValidationRegex
) === false
) {
fastify.auth.changePassword(
name as string,
password.old,
password.new,
(err, isUpdated): void => {
if (_.isNil(err) && isUpdated) {
reply.code(fastify.statusCode.OK);
} else {
reply.send(
fastify.errorUtils.getInternalError(
fastify.errorUtils.API_ERROR.INTERNAL_SERVER_ERROR
)
);
}
}
);
} else {
reply.send(
fastify.errorUtils.getCode(
fastify.statusCode.BAD_REQUEST,
fastify.errorUtils.APP_ERROR.PASSWORD_VALIDATION
)
);
return;
}
fastify.auth.changePassword(
name as string,
password.old,
password.new,
(err, isUpdated): void => {
if (_.isNil(err) && isUpdated) {
reply.code(fastify.statusCode.OK);
} else {
reply.send(
fastify.errorUtils.getInternalError(
fastify.errorUtils.API_ERROR.INTERNAL_SERVER_ERROR
)
);
}
}
);
}
);
// });

View file

@ -71,23 +71,18 @@ function addUserAuthApi(auth: Auth, config: Config): Router {
config?.serverSettings?.passwordValidationRegex
) === false
) {
auth.changePassword(
name as string,
password.old,
password.new,
(err, isUpdated): void => {
if (_.isNil(err) && isUpdated) {
next({
ok: true,
});
} else {
return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
}
}
);
} else {
return next(errorUtils.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));
}
auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {
if (_.isNil(err) && isUpdated) {
next({
ok: true,
});
} else {
return next(errorUtils.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
}
});
}
);
}

View file

@ -79,6 +79,122 @@ describe('test web server', () => {
.expect(HTTP_STATUS.CANNOT_HANDLE, JSON.stringify({ error: 'cannot handle this' }));
});
test('should change password', async () => {
const oldPass = 'test';
const newPass = 'new-pass';
const api = supertest(await initializeServer('default-test.yaml'));
// Login with the old password.
const loginRes = await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: oldPass,
})
)
.expect(HTTP_STATUS.OK);
// Change the password.
await api
.put('/-/verdaccio/sec/reset_password')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.set(HEADER_TYPE.AUTHORIZATION, `Bearer ${loginRes.body.token}`)
.send(
JSON.stringify({
password: {
old: oldPass,
new: newPass,
},
})
)
.expect(HTTP_STATUS.OK);
// Verify that you cannot login with the old password.
await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: oldPass,
})
)
.expect(HTTP_STATUS.UNAUTHORIZED);
// Verify that you can login with the new password.
await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: newPass,
})
)
.expect(HTTP_STATUS.OK);
});
test('should not change to invalid password', async () => {
const oldPass = 'test';
const newPass = '12'; // Invalid password: Too short.
const api = supertest(await initializeServer('default-test.yaml'));
// Login with the old password.
const loginRes = await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: oldPass,
})
)
.expect(HTTP_STATUS.OK);
// Try changing to an invalid password.
await api
.put('/-/verdaccio/sec/reset_password')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.set(HEADER_TYPE.AUTHORIZATION, `Bearer ${loginRes.body.token}`)
.send(
JSON.stringify({
password: {
old: oldPass,
new: newPass,
},
})
)
.expect(HTTP_STATUS.BAD_REQUEST);
// Verify that you cannot login with the new (invalid) password.
await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: newPass,
})
)
.expect(HTTP_STATUS.UNAUTHORIZED);
// Verify that you can still login with the old password.
await api
.post('/-/verdaccio/sec/login')
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
.send(
JSON.stringify({
username: 'test',
password: oldPass,
})
)
.expect(HTTP_STATUS.OK);
});
test('should not change password if flag is disabled', async () => {
const oldPass = 'test';
const newPass = 'new-pass';
@ -136,6 +252,4 @@ describe('test web server', () => {
)
.expect(HTTP_STATUS.OK);
});
test.todo('should change password');
});