# Accessibility (WCAG 2.1 AA)

HelixIAM's sign-in pages and account console target **WCAG 2.1 level A and AA**, the level EN 301 549 (clause 9,
web content) requires and that Dutch government websites, login pages included, must meet. The work landed in
1.0.0-rc.13; the full report, criterion by criterion, is available to licensed customers from KubeDNA B.V. ([contact@helixiam.com](mailto:contact@helixiam.com)) on request.

!!! warning "A self-assessment, not an audit"
    The status below is the HelixIAM maintainers' own assessment. No accredited or independent party has evaluated
    HelixIAM, and it has not been tested with screen readers or with users with disabilities. An organisation that
    needs a formal conformance claim (for example in a Dutch *toegankelijkheidsverklaring*) needs its own WCAG-EM
    audit of its own deployment, with its own theme and texts. A draft Dutch statement to start from is available
    to licensed customers on request.

## Scope

| Surface | Assessed |
| --- | --- |
| Sign-in pages: login (password, magic link, IdP/eID buttons, EU wallet), registration, password reset, e-mail verification, every MFA step, consent, device activation, sign-out, error pages | Fully, every template |
| Account console (server-rendered) | Fully |
| Default theme, and the contrast checks on admin-set theme colours | Default theme fully |
| Admin console | Spot check of five screens |
| Older React account app | Not separately audited; shares the fixed console components |

Out of scope: third-party pages a sign-in passes through (DigiD, eHerkenning, eIDAS nodes, wallets, upstream
identity providers, CAPTCHA widgets), e-mails, and an organisation's own custom CSS, logo and texts.

## How it is tested

- **axe-core** runs in a browser test on every server page (62 page states), in English and Dutch, at 1440 and
  390 px, in the light and dark colour scheme. It is part of the build and **fails it on any serious or critical
  violation**.
- The same test checks, beyond axe: `<html lang>` matches the language served, every page has a title, the skip link
  is the first focusable element, every visible control shows a focus indicator, and nothing scrolls sideways at
  320 CSS px, also with the WCAG 1.4.12 text-spacing override applied.
- Every template and script was reviewed by hand against the success criteria: keyboard operation and focus order,
  landmarks and headings, labels and `autocomplete`, error messages, status messages, time limits, QR alternatives,
  reflow and text spacing.

## What this means for your deployment

- Every page has a *Skip to main content* link, one `h1`, and its `lang` set to the language served (English or
  Dutch).
- QR codes have a text alternative (the setup key, or a same-device link); push, QR and wallet status changes are
  announced to screen readers; errors are shown in text and linked to their field.
- The EU wallet request warns a minute before it expires and offers *Try again*; expired push and QR requests end in
  a focused *Try again*.
- **Theme colours are checked.** Saving a realm theme (`PUT …/theme`) is refused when text, links, error and success
  text, or the focus ring fall below the WCAG contrast minimums (4.5:1 for text, 3:1 for the focus ring). The
  console's *Branding* tab warns while you type a colour. See [Login theming](../operations/theming.md).

## Known gaps

- No independent audit and no assistive-technology testing (above).
- **CAPTCHA** is off by default. When a realm enables one, it is a third-party widget HelixIAM cannot fix or verify,
  and there is no CAPTCHA-free alternative path. Leaving it off and relying on the rate limits and lockout avoids the
  problem.
- **Push and QR sign-in** cannot warn before the request expires (the page does not know its lifetime); it offers
  *Try again* afterwards.
- **Custom CSS, logos and admin-entered texts are not checked.** If you add custom CSS, test it.
- **E-mails** were not assessed.
- **Admin console:** only five screens were checked; the flow editor's canvas mode is pointer-oriented, and its
  *Simple* (stepper) mode is the keyboard path.
- **Markup change:** the login brand headline is now `<p class="brand-headline">` instead of an `h1`; custom CSS that
  targeted `.helix-brand h1` must target `.brand-headline`.

## See also

- [Login theming](../operations/theming.md)
- [Compliance program](compliance-program.md)
