From 297830ed35bc57d566e1ba80b951bf1fdabeb2ff Mon Sep 17 00:00:00 2001 From: Alexandre Brandizzi Date: Fri, 25 Sep 2026 12:22:55 -0300 Subject: [PATCH] fix(auth): send reset email and code in the request body The verify call now carries the email the code was issued to, which the API requires, and neither call puts the email or code in the URL. --- src/domain/auth/api/auth-api.ts | 8 ++-- src/test/domain/auth/api/auth-api.test.ts | 45 +++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/test/domain/auth/api/auth-api.test.ts diff --git a/src/domain/auth/api/auth-api.ts b/src/domain/auth/api/auth-api.ts index 279baaa7..c8f4f681 100644 --- a/src/domain/auth/api/auth-api.ts +++ b/src/domain/auth/api/auth-api.ts @@ -40,12 +40,14 @@ export async function changePassword(data: ChangePasswordPayload): Promise { - return apiPost(`${API_PATHS.authentication.forgetPassword}?Email=${encodeURIComponent(email)}`); + return apiPost(API_PATHS.authentication.forgetPassword, { email }); } -export async function verifyResetCode(code: string): Promise { - return apiPost(`${API_PATHS.authentication.verificationCode}?code=${encodeURIComponent(code)}`); +// The server checks a code only against the email it was issued to. +export async function verifyResetCode(email: string, code: string): Promise { + return apiPost(API_PATHS.authentication.verificationCode, { email, code }); } export async function resetPassword(data: ResetPasswordPayload): Promise { diff --git a/src/test/domain/auth/api/auth-api.test.ts b/src/test/domain/auth/api/auth-api.test.ts new file mode 100644 index 00000000..498d28be --- /dev/null +++ b/src/test/domain/auth/api/auth-api.test.ts @@ -0,0 +1,45 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const apiPost = vi.fn(); + +vi.mock("@/api/api", () => ({ + apiPost: (...args: unknown[]) => apiPost(...args), +})); + +import { forgotPassword, resetPassword, verifyResetCode } from "@/domain/auth/api/auth-api"; + +describe("password reset API", () => { + beforeEach(() => { + apiPost.mockReset(); + apiPost.mockResolvedValue({ status: "Success ", message: "ok" }); + }); + + it("sends the email in the request body, never in the URL", async () => { + await forgotPassword("alice@example.com"); + + expect(apiPost).toHaveBeenCalledWith("Authentication/ForgetPassword", { + email: "alice@example.com", + }); + expect(String(apiPost.mock.calls[0][0])).not.toContain("?"); + }); + + it("verifies a code together with the email it was issued to", async () => { + await verifyResetCode("alice@example.com", "123456"); + + expect(apiPost).toHaveBeenCalledWith("Authentication/VerificationCode", { + email: "alice@example.com", + code: "123456", + }); + expect(String(apiPost.mock.calls[0][0])).not.toContain("123456"); + }); + + it("resets with email, code and the new password in the body", async () => { + await resetPassword({ Email: "alice@example.com", Code: "123456", Password: "New@67890" }); + + expect(apiPost).toHaveBeenCalledWith("Authentication/ResetPassword", { + Email: "alice@example.com", + Code: "123456", + Password: "New@67890", + }); + }); +});