Skip to main content

Forgot Password

Ever Teams provides a complete forgot / reset password flow, powered by the Ever Gauzy API's password reset endpoints. This page documents the full flow, API integration, and implementation details.

User Flow

Step 1: Request Password Reset

Page: /auth/forgot-password

The user enters their email address and clicks "Send Reset Link". The app calls the Gauzy API:

POST /auth/request-password
Content-Type: application/json

{
"email": "[email protected]"
}

Response: Always returns true (even if the email doesn't exist) to prevent user enumeration attacks.

Server behavior:

  • Looks up all users with the given email (may be in multiple tenants)
  • Generates a short-lived JWT token (10-minute expiry) for each user
  • Invalidates any existing password reset records for that email
  • Sends a password reset email with a link containing the token
  • If the user exists in multiple tenants, sends a multi-tenant reset email with links for each tenant
Rate limiting

This endpoint is rate-limited to 3 requests per 60 seconds to prevent abuse.

Key Files

FilePurpose
app/[locale]/auth/forgot-password/page.tsxRoute entry point
core/components/pages/auth/forgot-password/forgot-password-form.tsxForm component with email input and success state
core/services/client/api/auth/auth.service.tsrequestPassword() method

Step 2: Reset Password

Page: /auth/reset-password

The user arrives via the email link, which includes a token query parameter. They enter a new password and confirmation:

POST /auth/reset-password
Content-Type: application/json

{
"token": "eyJhbGciOiJI...",
"password": "newSecurePassword123",
"confirmPassword": "newSecurePassword123"
}

Response: Returns true on success.

Server behavior:

  • Verifies the JWT token (checks signature, expiry, and purpose)
  • Looks up the password reset record in the database
  • Validates that the passwords match
  • Hashes the new password with bcrypt
  • Updates the user's password
  • Deletes the password reset record (one-time use)

Error cases:

  • Expired token (10-minute window)
  • Invalid or already-used token
  • Passwords don't match
  • Password doesn't meet requirements
Rate limiting

This endpoint is also rate-limited to 3 requests per 60 seconds.

Client-Side Validation

Before calling the API, the reset form validates:

  • Password must be at least 6 characters
  • Password and confirmation must match
  • Token must be present in the URL

Key Files

FilePurpose
app/[locale]/auth/reset-password/page.tsxRoute entry point
core/components/pages/auth/reset-password/reset-password-form.tsxForm with password inputs, validation, show/hide toggle
core/services/client/api/auth/auth.service.tsresetPassword() method

Login Page Integration

A "Forgot Password?" link is displayed on the password login page (/auth/password), in the LoginFormActions component. It appears between the "Don't have an account?" / "Register" row and the "Continue" button.

Translation Keys

All UI strings are internationalized. The keys are in locales/en.json:

KeyValue
pages.auth.FORGOT_PASSWORD"Forgot Password?"
pages.authForgotPassword.HEADING_TITLE"Forgot Password"
pages.authForgotPassword.FORM_DESCRIPTION"Enter the email address..."
pages.authForgotPassword.SEND_RESET_LINK"Send Reset Link"
pages.authForgotPassword.SUCCESS_TITLE"Check Your Email"
pages.authForgotPassword.SUCCESS_MESSAGE"Password reset instructions..."
pages.authForgotPassword.BACK_TO_LOGIN"Back to Login"
pages.authResetPassword.HEADING_TITLE"Reset Password"
pages.authResetPassword.NEW_PASSWORD"New Password"
pages.authResetPassword.CONFIRM_PASSWORD"Confirm Password"
pages.authResetPassword.RESET_PASSWORD"Reset Password"
pages.authResetPassword.SUCCESS_TITLE"Password Updated"
pages.authResetPassword.PASSWORDS_DONT_MATCH"Passwords don't match"
pages.authResetPassword.TOKEN_EXPIRED"This reset link is invalid or has expired..."

API Service Methods

The AuthService class in core/services/client/api/auth/auth.service.ts provides:

// Request a password reset email
requestPassword(email: string): Promise<boolean>

// Reset password with a valid token
resetPassword(token: string, password: string, confirmPassword: string): Promise<boolean>

Both methods call the Gauzy API directly. No Next.js API proxy routes are needed since these are public endpoints.

Security Considerations

AspectImplementation
User enumerationPOST /auth/request-password always returns true regardless of whether the email exists
Token expiryReset tokens expire after 10 minutes
One-time useEach token can only be used once; previous tokens are invalidated when a new one is generated
Rate limitingBoth endpoints limited to 3 requests per minute
Password hashingNew passwords are hashed with bcrypt before storage
Input validationServer-side validation via DTOs with class-validator