1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00

feat: changing password will expire reset password tokens (#3451)

This commit is contained in:
Jaanus Sellin 2023-04-05 12:39:52 +03:00 committed by GitHub
parent 0491c08d5e
commit 80bea14d42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 5 deletions

View File

@ -61,6 +61,10 @@ export default class ResetTokenService {
} }
} }
expireExistingTokensForUser = async (userId: number): Promise<void> => {
return this.store.expireExistingTokensForUser(userId);
};
async isValid(token: string): Promise<IResetToken> { async isValid(token: string): Promise<IResetToken> {
let t; let t;
try { try {
@ -109,7 +113,7 @@ export default class ResetTokenService {
): Promise<IResetToken> { ): Promise<IResetToken> {
const token = await this.generateToken(); const token = await this.generateToken();
const expiry = new Date(Date.now() + expiryDelta); const expiry = new Date(Date.now() + expiryDelta);
await this.store.expireExistingTokensForUser(tokenUser); await this.expireExistingTokensForUser(tokenUser);
return this.store.insert({ return this.store.insert({
reset_token: token, reset_token: token,
user_id: tokenUser, user_id: tokenUser,

View File

@ -351,6 +351,7 @@ class UserService {
const passwordHash = await bcrypt.hash(password, saltRounds); const passwordHash = await bcrypt.hash(password, saltRounds);
await this.store.setPasswordHash(userId, passwordHash); await this.store.setPasswordHash(userId, passwordHash);
await this.sessionService.deleteSessionsForUser(userId); await this.sessionService.deleteSessionsForUser(userId);
await this.resetTokenService.expireExistingTokensForUser(userId);
} }
async getUserForToken(token: string): Promise<TokenUserSchema> { async getUserForToken(token: string): Promise<TokenUserSchema> {
@ -388,7 +389,6 @@ class UserService {
}); });
if (allowed) { if (allowed) {
await this.changePassword(user.id, password); await this.changePassword(user.id, password);
await this.sessionService.deleteSessionsForUser(user.id);
} else { } else {
throw new InvalidTokenError(); throw new InvalidTokenError();
} }

View File

@ -33,5 +33,5 @@ export interface IResetTokenStore extends Store<IResetToken, string> {
useToken(token: IResetQuery): Promise<boolean>; useToken(token: IResetQuery): Promise<boolean>;
deleteFromQuery(query: IResetTokenQuery): Promise<void>; deleteFromQuery(query: IResetTokenQuery): Promise<void>;
deleteExpired(): Promise<void>; deleteExpired(): Promise<void>;
expireExistingTokensForUser(user_id: number): Promise<void>; expireExistingTokensForUser(userId: number): Promise<void>;
} }

View File

@ -168,7 +168,7 @@ test('Trying to reset password with same token twice does not work', async () =>
token, token,
password, password,
}) })
.expect(403) .expect(401)
.expect((res) => { .expect((res) => {
expect(res.body.details[0].message).toBeTruthy(); expect(res.body.details[0].message).toBeTruthy();
}); });
@ -191,7 +191,7 @@ test('Calling validate endpoint with already existing session should destroy ses
await request.get('/api/admin/features').expect(200); await request.get('/api/admin/features').expect(200);
const url = await resetTokenService.createResetPasswordUrl( const url = await resetTokenService.createResetPasswordUrl(
user.id, user.id,
adminUser.username, adminUser.username!,
); );
const relative = getBackendResetUrl(url); const relative = getBackendResetUrl(url);
@ -267,3 +267,31 @@ test('Trying to change password to undefined should yield 400 without crashing t
}) })
.expect(400); .expect(400);
}); });
test('changing password should expire all active tokens', async () => {
const url = await resetTokenService.createResetPasswordUrl(
user.id,
adminUser.username,
);
const relative = getBackendResetUrl(url);
const {
body: { token },
} = await app.request
.get(relative)
.expect(200)
.expect('Content-Type', /json/);
await app.request
.post(`/api/admin/user-admin/${user.id}/change-password`)
.send({ password: 'simple123-_ASsad' })
.expect(200);
await app.request
.post('/auth/reset/password')
.send({
token,
password,
})
.expect(401);
});