The login page is the most-probed door your organization has
Every public login page starts being scanned by automated tools shortly after going live. Attackers try previously leaked usernames and passwords, hammer a single account with password guesses, or use bots to abuse the login form.
These attacks do not look the same. Sometimes many attempts come from a single IP address. Sometimes the same username is retried from many different sources. Sometimes leaked passwords are applied to thousands of different accounts at low speed, in a distributed pattern.
This is why static defenses fall short. Locking only by IP misses distributed attacks and can wrongly block real users coming through shared networks. Locking only by account hands attackers another advantage — they can lock out many accounts and cause a denial of service. Forcing CAPTCHA on every single login ruins the real user experience.
The bigger mistake is leaving the bot and risk evaluation at login time entirely to a third-party cloud service. That model creates external dependency, per-user or per-evaluation cost, data visibility issues, and an extra break point in the authentication path.
Login protection should not be a uniform wall. It should be a local security layer that raises friction as risk rises, responds based on the source and target of the attack, and does not punish real users unnecessarily.
Because protecting the login page is not only about stopping the attacker — it is also about keeping the real user able to safely continue their work.
How we approach it
Graduated friction, multi-scope policy, and a self-hosted challenge — all on the platform you already own.
Three tiers of friction, not one hard wall
Every policy runs three thresholds: a warning that surfaces in the audit log, a CAPTCHA challenge that filters automation without blocking humans, and a lockout that closes the door entirely. Legitimate users rarely see the second tier and almost never the third; attackers escalate quickly.
Three scopes — match the defense to the attack
Each policy applies at one of three scopes: by source IP, by username, or by both together. A brute-force attack on one account from one IP gets caught by IP scope; credential stuffing across many usernames from rotating IPs gets caught by username scope; the combined scope handles targeted attacks that mix both.
Self-hosted CAPTCHA — no external bot-detection cloud
The CAPTCHA challenge is generated server-side as an image, with five difficulty levels, a charset that skips confusing characters (I, L, O, 0, 1), and configurable colors, dimensions, and noise. There is no Google reCAPTCHA, no Cloudflare Turnstile, no per-evaluation fee — and the most sensitive moment of authentication never leaves your perimeter.
Coordinated with MFA and the rest of the auth path
Lockout counters coordinate with the same attempt tracking used by every MFA channel. A user cannot brute-force one factor while another factor sits at a parallel attempt, and a captcha tripped at the password step propagates to the rest of the flow that protects the same identity.
Capabilities
Multi-scope policies — IP, username, or combined
Each policy is bound to one of three scopes. The IP scope catches a single attacker hammering many accounts from one network. The username scope catches credential stuffing where each attempt rotates the source IP. The combined scope catches the targeted case where a known attacker focuses on a specific account from a specific network.
Graduated thresholds — warning, CAPTCHA, lockout
Every policy runs three thresholds that escalate in order. The warning threshold flags suspicious activity in the audit log without affecting the user. The CAPTCHA threshold puts a self-hosted image challenge in front of the next attempt. The lockout threshold closes the door for a configurable duration — and the order, values, and decay window are all per-policy.
Self-hosted image CAPTCHA with five difficulty levels
CAPTCHAs are generated locally as images — five difficulty levels from light readability cues to heavy distortion, configurable colors and dimensions to match the brand, and a charset that intentionally omits visually-similar characters (I, L, O, 0, 1) to keep the legitimate user's experience clean.
No third-party CAPTCHA or bot-detection cloud in the auth path
Login protection is generated, served, validated, and audited entirely on the platform. There is no per-evaluation fee, no outside dependency, no privacy implication of sending every login attempt to a vendor, and no opaque scoring service sitting between your users and your authentication.
Coordinated attempt tracking across the auth flow
Failed password attempts, failed MFA challenges, and failed CAPTCHA responses feed coordinated counters per policy scope. An attacker cannot brute-force one factor while a parallel attempt waits at another, and a lockout triggered at one step propagates to every channel that protects the same identity.
Per-attempt decay window — old failures forget themselves
Each policy defines a decay window. Failed attempts older than the window stop counting toward the current thresholds, so a legitimate user who typo'd their password three times last week does not start today already at the CAPTCHA tier. The window, the decay shape, and the thresholds are all tunable per policy.
Per-attempt audit trail with masked recipient context
Every login attempt — success, warning crossed, CAPTCHA triggered, lockout fired — writes a structured audit entry with timestamp, source IP, user agent, scope, and policy outcome. Recipient information (email, phone) is masked in the audit stream by default so the audit trail does not become a secondary leak path.
Operational depth
The mechanics that make graduated defense feel invisible to good users and clear to attackers.
CAPTCHA appearance is customizable per brand
Background colour, text colour, width, height, font size, character spacing, noise lines, and noise dots are all configurable. The challenge can match the visual identity of the login portal it protects without leaking that an external service is involved — because nothing external is involved.
Charset deliberately excludes confusing characters
The default charset skips I, L, O, 0, and 1 — characters that are easy to mistake for each other in distorted form. Legitimate users solve CAPTCHAs faster and with fewer retries; the defensive value against automated solvers is preserved at every difficulty level.
Per-policy thresholds, decay, and lockout duration
Warning threshold, CAPTCHA threshold, lockout threshold, decay window, and lockout duration are all configurable per policy. A user-management interface has different tolerances than a public help-desk login or an admin console; the same engine serves them with different numbers.
Stateless coordination through Redis
Counters and lockout state live in Redis, so any gateway pod can see the current attempt count for any scope. Horizontally scaled deployments see consistent state without coordination overhead, and a lockout decision made on one pod is immediately visible to every other pod.
Recovery flow — administrator unlock and time-based release
A locked-out user either waits for the lockout to expire on its own clock or is unlocked by an administrator through the gateway admin interface. The recovery action is itself audited; an emergency unlock during an incident is a traceable event rather than an invisible workaround.
Where teams use it
Credential stuffing across many accounts
An attacker with a leaked username/password list rotates IPs and tries each pair against the login page. Username-scope policies catch this pattern — counters rise per account, the CAPTCHA tier filters automation, and the lockout closes the door for repeated targets.
Brute force against a known account
A single attacker, a single source IP, a single target account, many guesses. IP-scope policies catch this within seconds — the warning surfaces in audit, the CAPTCHA tier filters scripted attempts, and the lockout duration multiplies fast enough to make the attack uneconomic.
Bot-driven spam logins
Automated agents try to log in to scrape, spam, or wait for an unlocked account. The CAPTCHA tier is exactly where these are caught — generated locally, validated locally, and entirely outside the reach of automated CAPTCHA-solver services that target external SaaS challenges.
Compliance evidence on login monitoring
PCI-DSS, HIPAA, and ISO 27001 require evidence that failed-login monitoring is in place, with thresholds and audit trails. The per-attempt audit stream gives the auditor a single timeline to review, with thresholds expressed as configuration rather than written prose.
Common questions
Which attack patterns are covered?
Does the CAPTCHA tier use Google reCAPTCHA or Cloudflare Turnstile?
When should I use IP scope versus username scope versus combined?
How does a user recover from a lockout?
When does the failed-attempt counter reset?
Defend the login page without locking out real users
Three-tier graduated friction, three-scope policy coverage, and self-hosted CAPTCHA — all on the platform you already own. We'll walk through a live deployment on your applications.