DEV Community

Prajwal Gaonkar
Prajwal Gaonkar

Posted on

Making a Public Form Secure: Tokens, Idempotency & Real-World Backend Design

I thought building a form was easy… until I tried making it secure.

While designing a recruitment form for a college club, I realized that the real challenge is not collecting data — it is making sure the system behaves correctly under real-world conditions.

Let’s walk through how I approached this problem step by step.


Understanding the Problem

The form was public. Users could submit it using:

  • Mobile data
  • College Wi-Fi

A common beginner approach is to block users based on IP address after submission.

At first glance, this seems reasonable.

But in real-world networks, especially Wi-Fi, multiple users share the same public IP due to NAT.

100 users → 1 IP

If we block that IP, we end up blocking everyone connected to that network.

Clearly, this approach fails.


Solution 1 — IP-Based Blocking

The idea

  • Track submissions by IP
  • Block further requests from the same IP

Why it seems useful

  • Simple to implement
  • Works in small, isolated environments

Drawbacks

  • Breaks in shared networks (Wi-Fi, offices, colleges)
  • Blocks legitimate users
  • Not reliable in real-world systems

Solution 2 — One-Time Form Tokens

The idea

  • When a user loads the form, the server generates a unique token
  • The token is sent to the client
  • On submission, the server validates and marks the token as used

Why it works

  • Prevents duplicate submissions
  • Stops accidental double clicks
  • Prevents replaying the same request

Drawbacks

  • Users can reload the page and get a new token
  • Bots can repeatedly request new tokens
  • Does not prevent automated spam

Solution 3 — Idempotency Keys

The idea

  • Each logical request is assigned a unique idempotency key
  • The server stores the key along with the response
  • If the same key is used again, the server returns the stored response instead of processing the request again

Example

POST /submit
Idempotency-Key: abc123

Why it works

  • Prevents duplicate processing
  • Handles retries safely
  • Ensures operations execute only once

Drawbacks

  • Requires additional storage (Redis/DB)
  • Needs careful handling of request validation
  • Does not stop bots generating new requests with new keys

Solution 4 — Honeypot Fields

The idea

  • Add a hidden input field that users cannot see
  • Bots often fill all fields automatically
  • If this field is filled, reject the request

Why it works

  • Very simple to implement
  • Effectively blocks basic bots

Drawbacks

  • Advanced bots can bypass it
  • Not sufficient as a standalone solution

Solution 5 — CAPTCHA

The idea

  • Verify that the user is human before accepting submission

Examples

  • “I am not a robot”
  • Google reCAPTCHA
  • Cloudflare Turnstile

Why it works

  • Blocks most automated scripts
  • Adds a strong verification layer

Drawbacks

  • Slight friction for users
  • Can impact user experience if overused

Final Thoughts

What started as a simple form turned into a lesson in backend system design.

The biggest takeaway is:

There is no single solution.

Real systems use layered protection:

  • IP awareness (but not reliance)
  • Tokens for request validation
  • Idempotency for safe retries
  • Honeypots for bot detection
  • CAPTCHA for human verification

Each layer solves a different problem.

Even a simple public form can reveal how real-world systems are designed to handle scale, failures, and abuse.


Top comments (0)