Insecure OTP Implementation: OTP Generated on the Client-Side

What is this Vulnerability?

Modern applications frequently use One-Time Passwords (OTPs) to confirm user identity when logging in, registering, changing passwords, or confirming transactions. They are created safely on the server, transmitted through a reliable channel (such as email or SMS), and are intended to be private, time-limited, and unpredictable.

However, the OTP is generated client-side in this insecure implementation, usually with JavaScript. Even worse, an attacker can easily intercept or alter the OTP because it is disclosed in the request or response (for example, in network logs, browser developer tools, or API responses).

Example:
browser_developer_tool_example
Or even worse, the OTP is returned in an API response like:
otp_returned_in_api_response_example
This defeats the core security assumption behind OTPs — that the user must access a secure, separate channel to retrieve it.

Insecure OTP Implementation OTP Generated on the Client-Side-img

Impact of the Vulnerability

This flaw has serious ramifications for account security and authentication:

  • Bypassing OTP Verification: Without requiring access to the victim's device, attackers can obtain or create the OTP directly.

  • Account Takeover: Attackers can compromise accounts with OTP-protected workflows if they combine this vulnerability with other weaknesses (like predictable usernames).

  • 2FA Defeat: The second factor is rendered ineffective if the OTP is a component of a two-factor authentication system.

  • Loss of Confidentiality: Although users may believe the OTP was sent in confidence, anyone with even rudimentary technical skills could easily obtain it.

  • Compliance Violation: Violates security best practices and may violate data protection or compliance regulations (e.g., GDPR, PCI DSS).

Solution to fix the Vulnerability

To secure OTP workflows, applications must shift all OTP logic to the server-side and ensure secure delivery. Here's how:

  • Server-Side OTP Generation
    • Generate OTPs on the backend using a cryptographically secure method and store them temporarily in a secure database or cache (e.g., Redis) along with a timestamp and user reference. Example:

    • server_side_otp_generation

  • Transmission of Secure OTP
    • Use secure channels to send the OTP -
    • SMS through reliable APIs such as Nexmo, Twilio, etc.
    • Use secure mail services when sending emails.
    • The OTP value should never be returned in an API response.

  • Verification on the server side
    • Verify the OTP on the server after the user submits it
    • Verify the OTP value.
    • Verify that it hasn't expired (set TTL, for example, 5 minutes).
    • Limiting the number of verification attempts is an optional way to stop brute force attacks.

  • Prevent OTP Leaks in Responses or Logs:
    • OTPs should never be included in URL query strings, logs, or server responses.
    • Strip sensitive data from logs using logging filters or masking techniques.

  • Implement Rate Limiting
    • Apply rate limiting on OTP requests and verification attempts.