From feda54b4fbc8bf48b6fd8bd53ff01f2508cf1baa Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Wed, 13 May 2026 22:55:07 -0400 Subject: [PATCH] test(core): Update post-password-change token test for tokensValidAfter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Master used to reject stale password-reset tokens via `createJWTHash`, which embedded the user's password hash in the JWT. This branch replaced that mechanism with `tokensValidAfter` — a per-user timestamp the server bumps on any sensitive account change. The corresponding test now mocks the new mechanism (bumping `tokensValidAfter` past the token's `iat`) rather than the old one (signing a token against a fake user with a different password). --- .../cli/test/integration/password-reset.api.test.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/cli/test/integration/password-reset.api.test.ts b/packages/cli/test/integration/password-reset.api.test.ts index 8237d6dbe36..d8e1d7ac6a9 100644 --- a/packages/cli/test/integration/password-reset.api.test.ts +++ b/packages/cli/test/integration/password-reset.api.test.ts @@ -10,7 +10,6 @@ import type { User } from '@n8n/db'; import { GLOBAL_MEMBER_ROLE, GLOBAL_OWNER_ROLE, UserRepository } from '@n8n/db'; import { Container } from '@n8n/di'; import { compare } from 'bcryptjs'; -import { mock } from 'jest-mock-extended'; import { randomString } from 'n8n-workflow'; import { v4 as uuid } from 'uuid'; @@ -169,8 +168,14 @@ describe('GET /resolve-password-token', () => { }); test('should fail after password has changed', async () => { - const updatedUser = mock({ ...owner, password: 'another-password' }); - const resetPasswordToken = authService.generatePasswordResetToken(updatedUser); + // Issue a reset token, then simulate a password change by bumping the + // user's `tokensValidAfter` to a moment strictly after the token's + // `iat` (whole-second floor in `isTokenStale` means same-second bumps + // don't count). The reset token must now be rejected as stale. + const resetPasswordToken = authService.generatePasswordResetToken(owner); + await Container.get(UserRepository).update(owner.id, { + tokensValidAfter: new Date(Date.now() + 2000), + }); const response = await testServer.authlessAgent .get('/resolve-password-token')