Skip to content

IS-11327 LWA: WebAuthn ceremony errors as HAAPI step AppErrors#194

Draft
aleixsuau wants to merge 5 commits into
feature/IS-11302/webauthn-single-option-auto-startfrom
feature/IS-11327/webauthn-error-handling
Draft

IS-11327 LWA: WebAuthn ceremony errors as HAAPI step AppErrors#194
aleixsuau wants to merge 5 commits into
feature/IS-11302/webauthn-single-option-auto-startfrom
feature/IS-11327/webauthn-error-handling

Conversation

@aleixsuau
Copy link
Copy Markdown
Contributor

@aleixsuau aleixsuau commented May 20, 2026

Jira: https://curity.atlassian.net/browse/IS-11327

Summary

Follow-up to IS-11252. Catches WebAuthn ceremony exceptions (cancel / timeout / parse error / unsupported API / null credential), classifies them via a two-bucket discriminator (cancelOrTimeout / failed), and surfaces them as client-synthesised AppError-class problems through useHaapiStepper().error.app. Copy comes from step.metadata.messages.error.clientOperation.webauthn.{cancelOrTimeout | registration | authentication}. Since the BE is not providing the error copies yet, it currently shows the default error message ('An error occurred').

Test plan

Setup:

Test cases:

  • Trigger a WebAuthn registration and click the cancel button → assert error message renders via the consumer's error.app subscription.
  • Trigger a WebAuthn registration generic failure (by applying webauthnerrors.patch) → assert the registration-failed copy
  • Same for authentication (cancel + generic failure)
  • Confirm the WebAuthn step renderer stays mounted after each failure and the button is clickable for retry

aleixsuau and others added 5 commits May 20, 2026 14:46
Catch every WebAuthn ceremony failure in the runners and surface it as a
synthesised HaapiUnexpectedProblemStep via the existing error.app pipeline
(rather than escalating to the React error boundary as a programming bug).
Two-bucket discriminator (cancelOrTimeout / failed) matching Velocity
parity. Copy comes from step.metadata.messages.error.clientOperation.webauthn
with empty-string fallback while the BE keys land.

* Runner-level synthesis: runWebAuthn{Registration,Authentication} catch the
  full error catalog (parse DOMException, create/get DOMException, TypeError,
  null credential, unsupported API) and throw a synthesised HaapiStepperError
  built via formatErrorStepData(HaapiUnexpectedProblemStep).
* Dispatcher wrapping: performClientOperation wraps each WebAuthn runner in a
  .then/.catch chain returning ClientOperationResult discriminated union. The
  catch discriminates HaapiStepperError vs raw rejections via a type guard;
  raw errors propagate to the React boundary as programming bugs.
* Type hierarchy: HaapiWebAuthnRegistrationClientOperationAction is now a
  proper discriminated union (passkeys | any-device) so consumers narrow via
  positive + negative type guards without casts. HaapiWebAuthnAnyDeviceArgs
  is also a discriminated union (platform-required | crossPlatform-required)
  expressing the "at least one of two" HAAPI spec invariant.
* Metadata surface: HaapiMetadata.messages.error.clientOperation.webauthn
  carries the per-ceremony copy (cancelOrTimeout shared, registration,
  authentication).
* Auto-start parity: manageWebAuthnAutoStart stays fire-and-forget via
  nextStep(); ceremony failures surface the same way as manual click
  (matching Velocity's .catch(handleError) pattern).
* Tests: 23 runner-level tests in webauthn.spec.ts cover the full catalog
  per ceremony; HaapiStepper.spec.tsx wiring tests consolidated under one
  WebAuthn suite (Auto-Start gating + Registration/Authentication
  success+error routing), dropping the duplicate auto-start error-surfacing
  cases since manual click + auto-start share the dispatcher plumbing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…apiStepperError

* Rename `HaapiMetadata.messages` → `HaapiMetadata.viewData` (and the dependent
  type aliases) so the metadata branch reads as view-customisation data emitted
  by the server rather than HAAPI step messages. Path becomes
  `step.metadata.viewData.error.clientOperation.webauthn.<key>`.
* Extract `getHaapiStepperError` from `webauthn.ts` to `client-operations.ts`
  as a shared helper that takes a resolved message string and synthesises a
  `HaapiStepperError` from a `HaapiUnexpectedProblemStep`. WebAuthn-specific
  message resolution stays in `webauthn.ts` (`getWebAuthnErrorMessage`); other
  client operations (BankID, EBF) can reuse the helper when their per-runtime
  error handling lands.
* Test fixtures + path-access assertions in `webauthn.spec.ts` updated to
  use the new `viewData` key.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClientOperationResult is no longer WebAuthn-specific — the EBF and BankID
runners will need it next. Extract it into a new sibling typings.ts file
alongside the operation runners; keep the WebAuthn-specific enums where
they are.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant