diff --git a/apps/e2e/tests/authentication/auth.po.ts b/apps/e2e/tests/authentication/auth.po.ts
index 21c3a6176..6d1f98430 100644
--- a/apps/e2e/tests/authentication/auth.po.ts
+++ b/apps/e2e/tests/authentication/auth.po.ts
@@ -80,4 +80,10 @@ export class AuthPageObject {
await this.visitConfirmEmailLink(email);
}
+
+ async updatePassword(password: string) {
+ await this.page.fill('[name="password"]', password);
+ await this.page.fill('[name="repeatPassword"]', password);
+ await this.page.click('[type="submit"]');
+ }
}
diff --git a/apps/e2e/tests/authentication/password-reset.spec.ts b/apps/e2e/tests/authentication/password-reset.spec.ts
new file mode 100644
index 000000000..037f4c581
--- /dev/null
+++ b/apps/e2e/tests/authentication/password-reset.spec.ts
@@ -0,0 +1,48 @@
+import { expect, test } from '@playwright/test';
+
+import { AuthPageObject } from './auth.po';
+
+const email = 'owner@makerkit.dev';
+const newPassword = (Math.random() * 10000).toString();
+
+test.describe('Password Reset Flow', () => {
+ test.describe.configure({ mode: 'serial' });
+
+ test('will reset the password and sign in with new one', async ({ page }) => {
+ const auth = new AuthPageObject(page);
+
+ await page.goto('/auth/password-reset');
+
+ await page.fill('[name="email"]', email);
+ await page.click('[type="submit"]');
+
+ await auth.visitConfirmEmailLink(email);
+
+ await page.waitForURL('/update-password');
+
+ await auth.updatePassword(newPassword);
+
+ await page
+ .locator('a', {
+ hasText: 'Back to Home Page',
+ })
+ .click();
+
+ await page.waitForURL('/home');
+
+ await auth.signOut();
+
+ await page
+ .locator('a', {
+ hasText: 'Sign in',
+ })
+ .click();
+
+ await auth.signIn({
+ email,
+ password: newPassword,
+ });
+
+ await page.waitForURL('/home');
+ });
+});
diff --git a/apps/web/app/update-password/page.tsx b/apps/web/app/update-password/page.tsx
index fea8e33d5..a06007608 100644
--- a/apps/web/app/update-password/page.tsx
+++ b/apps/web/app/update-password/page.tsx
@@ -15,11 +15,13 @@ export const generateMetadata = async () => {
};
};
+const Logo = () => ;
+
async function UpdatePasswordPage() {
await requireUserInServerComponent();
return (
-
+
);
diff --git a/packages/features/auth/src/components/password-reset-request-container.tsx b/packages/features/auth/src/components/password-reset-request-container.tsx
index f3adb6e40..23a5ec47e 100644
--- a/packages/features/auth/src/components/password-reset-request-container.tsx
+++ b/packages/features/auth/src/components/password-reset-request-container.tsx
@@ -20,6 +20,7 @@ import { If } from '@kit/ui/if';
import { Input } from '@kit/ui/input';
import { Trans } from '@kit/ui/trans';
+import { useCaptchaToken } from '../captcha/client';
import { AuthErrorAlert } from './auth-error-alert';
const PasswordResetSchema = z.object({
@@ -31,6 +32,8 @@ export function PasswordResetRequestContainer(params: {
}) {
const { t } = useTranslation('auth');
const resetPasswordMutation = useRequestResetPassword();
+ const { captchaToken, resetCaptchaToken } = useCaptchaToken();
+
const error = resetPasswordMutation.error;
const success = resetPasswordMutation.data;
@@ -55,11 +58,20 @@ export function PasswordResetRequestContainer(params: {