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:
parent
0491c08d5e
commit
80bea14d42
@ -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,
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user