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 (2)

Collapse
 
acytryn profile image
Andre Cytryn

the idempotency key point is underrated in most "secure your form" guides. one thing worth noting: if the key is generated server-side per page load, you get the replay protection, but browser back-button navigation can reuse a cached page with an already-spent token, causing confusing failures for legitimate users. generating the key client-side (e.g. UUID on form render) and letting the server deduplicate avoids that. also, pairing idempotency with a short TTL (like 10 minutes) keeps your storage from growing unbounded.

Collapse
 
opprajwal profile image
Prajwal Gaonkar

Exactly 💯