feat(auth): password change requires old password

By checking the "old" password of the user prior to a password change, the
password change function is more secured against abuse.

Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2021-12-28 01:46:40 +01:00 committed by David Mehren
parent 20b0ded223
commit 277e2fb1ca
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
4 changed files with 37 additions and 2 deletions

View file

@ -9,10 +9,10 @@ import {
ConflictException,
Controller,
Delete,
NotFoundException,
Post,
Put,
Req,
UnauthorizedException,
UseGuards,
} from '@nestjs/common';
import { Session } from 'express-session';
@ -70,6 +70,10 @@ export class AuthController {
@Body() changePasswordDto: UpdatePasswordDto,
): Promise<void> {
try {
await this.identityService.loginWithLocalIdentity(
user,
changePasswordDto.currentPassword,
);
await this.identityService.updateLocalPassword(
user,
changePasswordDto.newPassword,
@ -77,7 +81,9 @@ export class AuthController {
return;
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
throw new UnauthorizedException(
'Verifying your identity with the current password did not work.',
);
}
throw e;
}

View file

@ -6,6 +6,8 @@
import { IsString } from 'class-validator';
export class UpdatePasswordDto {
@IsString()
currentPassword: string;
@IsString()
newPassword: string;
}

View file

@ -112,6 +112,7 @@ describe('Auth', () => {
it('works', async () => {
// Change password
const changePasswordDto: UpdatePasswordDto = {
currentPassword: password,
newPassword: newPassword,
};
await request(testSetup.app.getHttpServer())
@ -133,6 +134,7 @@ describe('Auth', () => {
cookie = response.get('Set-Cookie')[0];
// Reset password
const changePasswordBackDto: UpdatePasswordDto = {
currentPassword: newPassword,
newPassword: password,
};
await request(testSetup.app.getHttpServer())
@ -146,6 +148,7 @@ describe('Auth', () => {
testSetup.configService.get('authConfig').local.enableLogin = false;
// Try to change password
const changePasswordDto: UpdatePasswordDto = {
currentPassword: password,
newPassword: newPassword,
};
await request(testSetup.app.getHttpServer())
@ -177,6 +180,29 @@ describe('Auth', () => {
.send(JSON.stringify(loginOldPasswordDto))
.expect(201);
});
it('fails, when old password is wrong', async () => {
// Try to change password
const changePasswordDto: UpdatePasswordDto = {
currentPassword: 'wrong',
newPassword: newPassword,
};
await request(testSetup.app.getHttpServer())
.put('/api/private/auth/local')
.set('Content-Type', 'application/json')
.set('Cookie', cookie)
.send(JSON.stringify(changePasswordDto))
.expect(401);
// old password still does work for login
const loginOldPasswordDto: LoginDto = {
password: password,
username: username,
};
await request(testSetup.app.getHttpServer())
.post('/api/private/auth/local/login')
.set('Content-Type', 'application/json')
.send(JSON.stringify(loginOldPasswordDto))
.expect(201);
});
});
describe('POST /auth/local/login', () => {

View file

@ -114,6 +114,7 @@ describe('Register and Login', () => {
.set('Content-Type', 'application/json')
.send(
JSON.stringify({
currentPassword: PASSWORD,
newPassword: 'newPassword',
}),
)