Accessible Authentication: the WCAG 2.2 criterion your login page probably fails
SC 3.3.8 bans cognitive function tests in login flows. Here is what that means for password fields, OTP inputs, CAPTCHAs, and security questions — with the code.
Find the password field on your login page and try to paste into it. Not type — paste, from a password manager, the way roughly everyone with a 40-character generated password does it. If nothing lands in the field, or the field silently strips the value, you have a WCAG 2.2 failure sitting on the single page every one of your users has to get through before they can do anything at all.
That failure is success criterion 3.3.8, Accessible Authentication (Minimum), Level AA, and it is the most consequential of the nine criteria WCAG 2.2 added. Not because it is hard to satisfy — most fixes are one attribute or one deleted event handler — but because the failure is total. A broken contrast ratio makes a page harder to read. A broken login makes your product impossible to enter.
What 3.3.8 actually says
The criterion: a cognitive function test must not be required for any step in an authentication process, unless that step provides at least one of four escape hatches.
A cognitive function test is anything that asks the user to remember, transcribe, calculate, or solve. Remembering a password. Remembering a username. Retyping a six-digit code from an email into a form. Transcribing warped characters from a CAPTCHA. Answering "what was your first pet's name." Solving a puzzle. All of it counts.
The four exceptions:
- Alternative. Another authentication method is available that does not rely on a cognitive function test.
- Mechanism. A mechanism is available to assist the user in completing the cognitive function test.
- Object Recognition. The test is to recognize objects — the "select all images with a bicycle" pattern.
- Personal Content. The test is to identify non-text content the user themselves provided.
The second exception is the one that saves passwords. Passwords are, undeniably, a memory test. They remain legal under 3.3.8 because password managers exist and browsers implement autofill — that is the assisting mechanism. Which means the moment your code interferes with the password manager, the exception evaporates and the criterion fails.
This is the part teams miss. 3.3.8 is not really asking you to redesign authentication. It is asking you to stop breaking the tools that already make authentication accessible.
The four ways teams break it
Blocking paste
Somewhere in the last fifteen years, "disable paste on the password field" got filed under security hygiene. It is not. It never was. Blocking paste pushes users toward passwords short enough to type from memory, which is the opposite of what you want, and it is now an explicit accessibility failure.
The offending code is usually one of these:
// All of these fail 3.3.8
<input type="password" onPaste={(e) => e.preventDefault()} />
<input type="password" onDrop={(e) => e.preventDefault()} />
<input type="password" onCopy={(e) => e.preventDefault()} />
Delete them. There is no compliant version of this pattern, and no security argument that survives contact with the threat model — an attacker with clipboard access has already won more than your login form.
Suppressing autofill
The second failure is quieter, because nothing visibly breaks. The field just never gets offered to the password manager.
// Fails: autocomplete off means no manager assistance
<input type="password" autoComplete="off" name="pw" />
// Passes: the manager knows exactly what this field is
<input
type="password"
autoComplete="current-password"
name="password"
id="password"
/>
Use current-password on sign-in, new-password on registration and password-change forms, and username on the identifier field above it. Password managers rely on those tokens to decide what to fill and what to save. autocomplete="off" on a credential field is a direct instruction to your users' assistive tooling to stand down.
A subtler variant: custom components that render a div with contenteditable instead of an input, or that intercept keystrokes to mask characters manually. Password managers cannot see those fields at all. If your design system has a "fancy" password input, this is worth an hour of your time.
Split one-time-code inputs
The six-box OTP input is everywhere, and in its usual implementation it is a transcription test with no assisting mechanism. The user has a code in another app or an email, and your UI requires them to read it, hold it in working memory, and type one character into each of six separate fields — while any paste attempt drops all six characters into box one.
Two things fix it:
// Single field — simplest compliant option
<input
type="text"
inputMode="numeric"
autoComplete="one-time-code"
name="otp"
/>
autocomplete="one-time-code" lets the operating system surface the code from SMS or the keychain directly above the keyboard. If you keep the six-box design for visual reasons, you must handle a paste of the full code and distribute it across the inputs yourself:
function handlePaste(e) {
const digits = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6)
if (!digits) return
e.preventDefault()
setCode(digits.split(""))
inputRefs[Math.min(digits.length, 5)].current?.focus()
}
Also check your CSS. user-select: none applied to the element that displays a code — a recovery code panel, a backup key — makes the code impossible to copy, which turns the next step into a transcription test.
CAPTCHA
This one is more nuanced than the internet suggests. Under 3.3.8, an image-based "select all the crosswalks" challenge passes, because Object Recognition is an explicit exception. A distorted-text CAPTCHA requiring you to transcribe characters fails. A math problem or logic puzzle fails.
But passing 3.3.8 is a low bar to clear here, and clearing it is not the same as being usable. Object-recognition challenges are still miserable for people with low vision, and they fail SC 3.3.9, Accessible Authentication (Enhanced), which is Level AAA and drops both the object-recognition and personal-content exceptions. If you are going to keep a CAPTCHA, the durable answer is a non-interactive challenge — risk-scored or cryptographic attestation — with a genuine alternative path for anyone it blocks. "Contact support" is not an alternative path if support only answers on weekdays.
Security questions
Straightforward recall test, no exception applies, fails outright. If you use knowledge-based questions anywhere in account recovery, that step needs an alternative route: an email link, an SMS code you can paste, or a support-verified path.
The compliance timing question
Here is where I will be more careful than most posts on this topic. 3.3.8 is new in WCAG 2.2. The major legal instruments still point at older versions of the standard.
The DOJ's ADA Title II rule adopts WCAG 2.1 Level AA. Ontario's AODA Integrated Accessibility Standards Regulation references WCAG 2.0 Level AA. In Europe, conformance with the European Accessibility Act runs through the harmonized standard EN 301 549, and the version in force as I write this references WCAG 2.1 — an update aligning it to 2.2 has been in progress, so check the current published version before you rely on this paragraph.
Strictly, then, 3.3.8 is not yet mandated by any of those three regimes. Two reasons that should not change what you do.
First, standards references get updated, and they get updated on a schedule set by regulators rather than by your roadmap. Teams that built to WCAG 2.1 and stopped will find themselves re-auditing on someone else's timeline. WCAG 2.2 is the current W3C Recommendation, and it is what procurement questionnaires increasingly ask about — I have written before about how procurement teams evaluate accessibility vendors, and version currency is one of the first filters buyers apply.
Second, and more to the point: the underlying failure is not a technicality. Blocking paste on a password field breaks the product for people with memory impairments, for dyslexic users, for people whose motor conditions make precise typing expensive, and for anyone using a screen reader who now has to verify forty characters one at a time. That was broken before WCAG named it, and it stays broken until you fix it.
What a scanner can and cannot see
Automated tooling is genuinely good at part of this and blind to the rest. Worth knowing which is which before you buy anything.
Detectable in code: paste, copy, and drop handlers on credential fields; autocomplete="off" or missing autocomplete tokens on password and OTP inputs; user-select: none on elements containing codes; password inputs that are not input elements at all. These are static patterns in the markup and the stylesheet. inklu scans HTML, CSS, JSX (including TSX), and SCSS, which is where all of them live, and the fixes are small enough that the pull request we open is usually a one-line diff — delete the handler, add the token.
Not detectable automatically: whether your security questions have a real alternative route, whether the fallback path for a blocked CAPTCHA actually works, whether your custom password component is exposed to managers in practice. Those need a person with a password manager and ten minutes. Any vendor telling you 3.3.8 is fully automatable is overselling. If you are comparing tools, look at how each one describes its manual-testing gap — and check their site for current details rather than taking anyone's summary of a competitor, including mine. Our comparison pages lay out where we think the lines fall.
The ten-minute audit
Open your own login flow and check:
- Paste a password from your manager. Does it land?
- Does the manager offer to fill it, without you clicking into the field first?
- Paste a six-digit code into the OTP input. All six digits, first try?
- Can you select and copy your own recovery codes?
- Is there a CAPTCHA, and if it defeats you, is there a path forward that does not involve a business-hours email?
- Does account recovery depend on remembering something you were never told to write down?
Every "no" on that list is a fix measured in minutes, on the page with more traffic than any other page you own.
If you want the code-level ones found and opened as pull requests against your repo rather than listed in a PDF, book a demo at inklu.io — we will run a scan against your actual login flow on the call. Pricing is token-based and starts at $29 a month; the breakdown is on the pricing page. Anything else, email hello@inklu.io.