Skip to main content

Lack of data validation - OTP

Need

To prevent unauthorized actions by ensuring the OTP used is valid and used only once.

Context

  • Usage of Elixir (1.12.0 and above) for building scalable and fault-tolerant applications
  • Usage of Phoenix Framework for building web applications

Description

Non compliant code

defmodule MyAppWeb.AuthController do
use MyAppWeb, :controller

def verify_otp(conn, %{"otp" => otp}) do
if MyApp.Auth.verify_otp(otp) do
render(conn, "success.html")
else
render(conn, "error.html")
end
end
end

In this example, the OTP is verified, but not invalidated after use. This means that the same OTP can be used multiple times, allowing for potential unauthorized access.

Steps

  • Add an additional step to invalidate the OTP after it has been used.
  • Update the verify_otp function in the Auth context to handle invalidating the OTP.
  • Update the controller to handle cases where the OTP is already invalidated.

Compliant code

defmodule MyAppWeb.AuthController do
use MyAppWeb, :controller

def verify_otp(conn, %{"otp" => otp}) do
case MyApp.Auth.verify_and_invalidate_otp(otp) do
:ok ->
render(conn, "success.html")
_ ->
render(conn, "error.html")
end
end
end

defmodule MyApp.Auth do
def verify_and_invalidate_otp(otp) do
if is_valid_and_not_invalidated(otp) do
invalidate_otp(otp)
:ok
else
:error
end
end
end

In this secure code, after the OTP is used, it is invalidated by the verify_and_invalidate_otp function in the Auth context. If an invalidated OTP is used again, it is treated as an invalid OTP.

References