@dloizides/auth-web 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.8.0 (2026-07-09)
4
+
5
+ Additive release for the Move 2b passkey in-app rebuild — the passkey ceremony
6
+ now runs **in-page** (`navigator.credentials.*` against the BFF's same-origin
7
+ `/bff/passkey/*` fetch endpoints) instead of a full-page redirect to Keycloak.
8
+ **Inert by default / no behaviour change until the BFF's WebAuthn RP is
9
+ configured:** when the RP is off the options endpoint returns 501 and the hook
10
+ transparently falls back to the legacy redirect. No breaking changes; every
11
+ 1.7.x export is unchanged and the legacy `startPasskeyLogin` /
12
+ `startPasskeyRegistration` navigation helpers stay exported (they ARE the
13
+ fallback).
14
+
15
+ ### Added
16
+
17
+ - **`usePasskeyCeremony({ mode, returnUrl, onSuccess })`** — the react-query-free
18
+ in-page ceremony hook: options fetch → `navigator.credentials.create/get` →
19
+ verify fetch. Returns `{ status, error, isSupported, start, reset }`. Falls
20
+ back to the legacy Keycloak redirect on a 501 (RP not configured), any non-2xx
21
+ options response, or an unsupported browser — so nothing regresses until the
22
+ owner flips `Bff:Passkey`. A cancelled/timed-out ceremony (`NotAllowedError` /
23
+ `AbortError`) surfaces as `'cancelled'`, anything else as `'failed'`.
24
+ - **`PasskeyCeremonyMode`** (`Login` / `Register`) and **`PasskeyCeremonyStatus`**
25
+ (`Idle` / `Running` / `Success` / `Error`) `const enum`s.
26
+
27
+ ### Changed
28
+
29
+ - **`<PasskeyLoginButton>`** and **`<PasskeySettingsCard>`** now drive
30
+ `usePasskeyCeremony` instead of `window.location.assign`. Same exported props,
31
+ same testIDs — a drop-in bump for consumers; the in-page path only activates
32
+ once the BFF RP is configured, otherwise they behave exactly as before.
33
+
3
34
  ## 1.7.0 (2026-07-07)
4
35
 
5
36
  Additive release for the Kefi multi-role overhaul — the shared machinery for a
package/dist/index.d.mts CHANGED
@@ -1022,16 +1022,18 @@ declare function DevicePinSettingsCard({ client, initialHasPin, theme: themeProp
1022
1022
  * The "Sign in with a passkey" button rendered on the unified login surface when
1023
1023
  * the BFF advertises the `passkey` method.
1024
1024
  *
1025
- * A passkey login is a full-page BROWSER NAVIGATION, not a fetch: tapping the
1026
- * button hands off to `/bff/passkey/login`, which drives the WebAuthn ceremony
1027
- * through Keycloak and returns the browser to `returnUrl` (default `'/'`, which
1028
- * routes an authenticated user to their dashboard) with a session cookie set. On
1029
- * a cancelled / failed ceremony the BFF bounces back to `?passkeyError=…`; we
1030
- * surface that as an inline error banner above the button.
1025
+ * The passkey login runs IN-PAGE via `usePasskeyCeremony`
1026
+ * (`navigator.credentials.get` against the same-origin `/bff/passkey/login/*`
1027
+ * fetch endpoints), landing the authenticated user on `returnUrl` (default `'/'`)
1028
+ * with a session cookie set. When the BFF's WebAuthn RP is not configured the
1029
+ * options endpoint returns 501 and the hook transparently falls back to the
1030
+ * legacy Keycloak redirect — so nothing regresses until the flag flips. A
1031
+ * cancelled / failed in-page ceremony surfaces as an inline error banner; a prior
1032
+ * redirect round-trip's `?passkeyError=…` is still honoured too.
1031
1033
  *
1032
- * react-query-free: it is pure `window.location` navigation (see
1033
- * `passkeyNavigation`), so it is safe to mount inside the login route group which
1034
- * has no QueryClient provider.
1034
+ * react-query-free: the hook uses plain `fetch` + `useState` (see
1035
+ * `usePasskeyCeremony`), so it is safe to mount inside the login route group
1036
+ * which has no QueryClient provider.
1035
1037
  */
1036
1038
 
1037
1039
  interface PasskeyLoginButtonProps {
@@ -1051,14 +1053,16 @@ declare function PasskeyLoginButton({ returnUrl, theme: themeProp, labels: label
1051
1053
  * The authenticated "Passkeys" settings card.
1052
1054
  *
1053
1055
  * Mount on an authenticated settings / account surface (alongside the device-PIN
1054
- * card). Adding a passkey is a full-page BROWSER NAVIGATION to
1055
- * `/bff/passkey/register`: Keycloak re-authenticates the user (password) then
1056
- * runs the WebAuthn credential-creation ceremony, returning the browser to the
1057
- * SAME settings page with `?passkey=registered` appended. On mount we read that
1058
- * param and, when present, show a success line.
1056
+ * card). Adding a passkey runs IN-PAGE via `usePasskeyCeremony`
1057
+ * (`navigator.credentials.create` against the same-origin
1058
+ * `/bff/passkey/register/*` fetch endpoints, session-cookie authenticated); on
1059
+ * success we show an inline success line — no navigation. When the BFF's WebAuthn
1060
+ * RP is not configured the options endpoint returns 501 and the hook falls back
1061
+ * to the legacy Keycloak redirect, which returns here with `?passkey=registered`;
1062
+ * that param is still honoured on mount, so nothing regresses until the flag flips.
1059
1063
  *
1060
- * react-query-free: the add action is pure `window.location` navigation (see
1061
- * `passkeyNavigation`); there is no fetch here. Mirrors `DevicePinSettingsCard`.
1064
+ * react-query-free: the hook uses plain `fetch` + `useState` (see
1065
+ * `usePasskeyCeremony`). Mirrors `DevicePinSettingsCard`.
1062
1066
  */
1063
1067
 
1064
1068
  interface PasskeySettingsCardProps {
@@ -1644,6 +1648,44 @@ declare const DEVICE_PIN_DEFAULT_DIGITS = 4;
1644
1648
  /** Guard: is `value` one of the BFF-accepted PIN lengths? */
1645
1649
  declare function isAllowedPinDigits(value: number): boolean;
1646
1650
 
1651
+ /**
1652
+ * Which WebAuthn ceremony {@link usePasskeyCeremony} drives.
1653
+ *
1654
+ * `Login` runs a usernameless/discoverable assertion
1655
+ * (`navigator.credentials.get`) from the login surface; `Register` runs an
1656
+ * attestation (`navigator.credentials.create`) from an authenticated settings
1657
+ * surface. The mode selects the `/bff/passkey/{login,register}/*` endpoint pair
1658
+ * and the matching redirect fallback.
1659
+ */
1660
+ declare const enum PasskeyCeremonyMode {
1661
+ /** Assertion ceremony — sign in with an existing passkey. */
1662
+ Login = "login",
1663
+ /** Attestation ceremony — add a passkey to the signed-in account. */
1664
+ Register = "register"
1665
+ }
1666
+
1667
+ /**
1668
+ * The lifecycle state of an in-page passkey ceremony.
1669
+ *
1670
+ * `Idle` before the user acts; `Running` while options are fetched, the
1671
+ * authenticator prompts, and the assertion/attestation is verified; `Success`
1672
+ * once the BFF confirms (a login has a session cookie set, a registration has a
1673
+ * stored credential); `Error` on a genuine in-page failure (see
1674
+ * {@link PasskeyErrorCode}). A redirect fallback (RP not configured / unsupported
1675
+ * browser) navigates the page away, so the hook never lands in a terminal state
1676
+ * for that path.
1677
+ */
1678
+ declare const enum PasskeyCeremonyStatus {
1679
+ /** No ceremony has started. */
1680
+ Idle = "idle",
1681
+ /** A ceremony is in flight (fetch → authenticator → verify). */
1682
+ Running = "running",
1683
+ /** The ceremony completed and the BFF confirmed it. */
1684
+ Success = "success",
1685
+ /** The ceremony failed in-page (cancelled or failed). */
1686
+ Error = "error"
1687
+ }
1688
+
1647
1689
  /**
1648
1690
  * Navigation helpers for the passkey (WebAuthn) BFF endpoints.
1649
1691
  *
@@ -1700,6 +1742,37 @@ declare function readPasskeyError(): PasskeyErrorCode | null;
1700
1742
  */
1701
1743
  declare function readPasskeyRegistered(): boolean;
1702
1744
 
1745
+ /** Options for {@link usePasskeyCeremony}. */
1746
+ interface UsePasskeyCeremonyOptions {
1747
+ /** Which ceremony to run — login (assertion) or register (attestation). */
1748
+ mode: PasskeyCeremonyMode;
1749
+ /**
1750
+ * Relative app path used two ways: the redirect fallback returns here, and (for
1751
+ * login) a successful in-page ceremony navigates here unless `onSuccess` is set.
1752
+ */
1753
+ returnUrl: string;
1754
+ /**
1755
+ * Called on a successful in-page ceremony. For login it receives the signed-in
1756
+ * `BffUser`; for register it receives `undefined`. When omitted, a login
1757
+ * navigates to `returnUrl` and a register just resolves to `Success`.
1758
+ */
1759
+ onSuccess?: (user: BffUser | undefined) => void;
1760
+ }
1761
+ /** The state + controls {@link usePasskeyCeremony} returns. */
1762
+ interface UsePasskeyCeremonyResult {
1763
+ /** Current lifecycle state. */
1764
+ status: PasskeyCeremonyStatus;
1765
+ /** The in-page error code, or `null`. */
1766
+ error: PasskeyErrorCode | null;
1767
+ /** `true` when the browser can run the in-page ceremony (else it redirects). */
1768
+ isSupported: boolean;
1769
+ /** Start the ceremony (or redirect-fallback when the RP is off / unsupported). */
1770
+ start: () => void;
1771
+ /** Clear a terminal state so the affordance can be retried. */
1772
+ reset: () => void;
1773
+ }
1774
+ declare function usePasskeyCeremony(optionsArg: UsePasskeyCeremonyOptions): UsePasskeyCeremonyResult;
1775
+
1703
1776
  /**
1704
1777
  * Device-local cache of the user's preferred login method (unified-login D5).
1705
1778
  *
@@ -1906,4 +1979,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
1906
1979
  /** `true` when the password satisfies every policy rule. */
1907
1980
  declare function isPasswordValid(password: string): boolean;
1908
1981
 
1909
- export { AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
1982
+ export { AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
package/dist/index.d.ts CHANGED
@@ -1022,16 +1022,18 @@ declare function DevicePinSettingsCard({ client, initialHasPin, theme: themeProp
1022
1022
  * The "Sign in with a passkey" button rendered on the unified login surface when
1023
1023
  * the BFF advertises the `passkey` method.
1024
1024
  *
1025
- * A passkey login is a full-page BROWSER NAVIGATION, not a fetch: tapping the
1026
- * button hands off to `/bff/passkey/login`, which drives the WebAuthn ceremony
1027
- * through Keycloak and returns the browser to `returnUrl` (default `'/'`, which
1028
- * routes an authenticated user to their dashboard) with a session cookie set. On
1029
- * a cancelled / failed ceremony the BFF bounces back to `?passkeyError=…`; we
1030
- * surface that as an inline error banner above the button.
1025
+ * The passkey login runs IN-PAGE via `usePasskeyCeremony`
1026
+ * (`navigator.credentials.get` against the same-origin `/bff/passkey/login/*`
1027
+ * fetch endpoints), landing the authenticated user on `returnUrl` (default `'/'`)
1028
+ * with a session cookie set. When the BFF's WebAuthn RP is not configured the
1029
+ * options endpoint returns 501 and the hook transparently falls back to the
1030
+ * legacy Keycloak redirect — so nothing regresses until the flag flips. A
1031
+ * cancelled / failed in-page ceremony surfaces as an inline error banner; a prior
1032
+ * redirect round-trip's `?passkeyError=…` is still honoured too.
1031
1033
  *
1032
- * react-query-free: it is pure `window.location` navigation (see
1033
- * `passkeyNavigation`), so it is safe to mount inside the login route group which
1034
- * has no QueryClient provider.
1034
+ * react-query-free: the hook uses plain `fetch` + `useState` (see
1035
+ * `usePasskeyCeremony`), so it is safe to mount inside the login route group
1036
+ * which has no QueryClient provider.
1035
1037
  */
1036
1038
 
1037
1039
  interface PasskeyLoginButtonProps {
@@ -1051,14 +1053,16 @@ declare function PasskeyLoginButton({ returnUrl, theme: themeProp, labels: label
1051
1053
  * The authenticated "Passkeys" settings card.
1052
1054
  *
1053
1055
  * Mount on an authenticated settings / account surface (alongside the device-PIN
1054
- * card). Adding a passkey is a full-page BROWSER NAVIGATION to
1055
- * `/bff/passkey/register`: Keycloak re-authenticates the user (password) then
1056
- * runs the WebAuthn credential-creation ceremony, returning the browser to the
1057
- * SAME settings page with `?passkey=registered` appended. On mount we read that
1058
- * param and, when present, show a success line.
1056
+ * card). Adding a passkey runs IN-PAGE via `usePasskeyCeremony`
1057
+ * (`navigator.credentials.create` against the same-origin
1058
+ * `/bff/passkey/register/*` fetch endpoints, session-cookie authenticated); on
1059
+ * success we show an inline success line — no navigation. When the BFF's WebAuthn
1060
+ * RP is not configured the options endpoint returns 501 and the hook falls back
1061
+ * to the legacy Keycloak redirect, which returns here with `?passkey=registered`;
1062
+ * that param is still honoured on mount, so nothing regresses until the flag flips.
1059
1063
  *
1060
- * react-query-free: the add action is pure `window.location` navigation (see
1061
- * `passkeyNavigation`); there is no fetch here. Mirrors `DevicePinSettingsCard`.
1064
+ * react-query-free: the hook uses plain `fetch` + `useState` (see
1065
+ * `usePasskeyCeremony`). Mirrors `DevicePinSettingsCard`.
1062
1066
  */
1063
1067
 
1064
1068
  interface PasskeySettingsCardProps {
@@ -1644,6 +1648,44 @@ declare const DEVICE_PIN_DEFAULT_DIGITS = 4;
1644
1648
  /** Guard: is `value` one of the BFF-accepted PIN lengths? */
1645
1649
  declare function isAllowedPinDigits(value: number): boolean;
1646
1650
 
1651
+ /**
1652
+ * Which WebAuthn ceremony {@link usePasskeyCeremony} drives.
1653
+ *
1654
+ * `Login` runs a usernameless/discoverable assertion
1655
+ * (`navigator.credentials.get`) from the login surface; `Register` runs an
1656
+ * attestation (`navigator.credentials.create`) from an authenticated settings
1657
+ * surface. The mode selects the `/bff/passkey/{login,register}/*` endpoint pair
1658
+ * and the matching redirect fallback.
1659
+ */
1660
+ declare const enum PasskeyCeremonyMode {
1661
+ /** Assertion ceremony — sign in with an existing passkey. */
1662
+ Login = "login",
1663
+ /** Attestation ceremony — add a passkey to the signed-in account. */
1664
+ Register = "register"
1665
+ }
1666
+
1667
+ /**
1668
+ * The lifecycle state of an in-page passkey ceremony.
1669
+ *
1670
+ * `Idle` before the user acts; `Running` while options are fetched, the
1671
+ * authenticator prompts, and the assertion/attestation is verified; `Success`
1672
+ * once the BFF confirms (a login has a session cookie set, a registration has a
1673
+ * stored credential); `Error` on a genuine in-page failure (see
1674
+ * {@link PasskeyErrorCode}). A redirect fallback (RP not configured / unsupported
1675
+ * browser) navigates the page away, so the hook never lands in a terminal state
1676
+ * for that path.
1677
+ */
1678
+ declare const enum PasskeyCeremonyStatus {
1679
+ /** No ceremony has started. */
1680
+ Idle = "idle",
1681
+ /** A ceremony is in flight (fetch → authenticator → verify). */
1682
+ Running = "running",
1683
+ /** The ceremony completed and the BFF confirmed it. */
1684
+ Success = "success",
1685
+ /** The ceremony failed in-page (cancelled or failed). */
1686
+ Error = "error"
1687
+ }
1688
+
1647
1689
  /**
1648
1690
  * Navigation helpers for the passkey (WebAuthn) BFF endpoints.
1649
1691
  *
@@ -1700,6 +1742,37 @@ declare function readPasskeyError(): PasskeyErrorCode | null;
1700
1742
  */
1701
1743
  declare function readPasskeyRegistered(): boolean;
1702
1744
 
1745
+ /** Options for {@link usePasskeyCeremony}. */
1746
+ interface UsePasskeyCeremonyOptions {
1747
+ /** Which ceremony to run — login (assertion) or register (attestation). */
1748
+ mode: PasskeyCeremonyMode;
1749
+ /**
1750
+ * Relative app path used two ways: the redirect fallback returns here, and (for
1751
+ * login) a successful in-page ceremony navigates here unless `onSuccess` is set.
1752
+ */
1753
+ returnUrl: string;
1754
+ /**
1755
+ * Called on a successful in-page ceremony. For login it receives the signed-in
1756
+ * `BffUser`; for register it receives `undefined`. When omitted, a login
1757
+ * navigates to `returnUrl` and a register just resolves to `Success`.
1758
+ */
1759
+ onSuccess?: (user: BffUser | undefined) => void;
1760
+ }
1761
+ /** The state + controls {@link usePasskeyCeremony} returns. */
1762
+ interface UsePasskeyCeremonyResult {
1763
+ /** Current lifecycle state. */
1764
+ status: PasskeyCeremonyStatus;
1765
+ /** The in-page error code, or `null`. */
1766
+ error: PasskeyErrorCode | null;
1767
+ /** `true` when the browser can run the in-page ceremony (else it redirects). */
1768
+ isSupported: boolean;
1769
+ /** Start the ceremony (or redirect-fallback when the RP is off / unsupported). */
1770
+ start: () => void;
1771
+ /** Clear a terminal state so the affordance can be retried. */
1772
+ reset: () => void;
1773
+ }
1774
+ declare function usePasskeyCeremony(optionsArg: UsePasskeyCeremonyOptions): UsePasskeyCeremonyResult;
1775
+
1703
1776
  /**
1704
1777
  * Device-local cache of the user's preferred login method (unified-login D5).
1705
1778
  *
@@ -1906,4 +1979,4 @@ declare function validatePasswordPolicy(password: string): PasswordPolicyError[]
1906
1979
  /** `true` when the password satisfies every policy rule. */
1907
1980
  declare function isPasswordValid(password: string): boolean;
1908
1981
 
1909
- export { AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
1982
+ export { AuthScreen, type AuthScreenProps, AuthTestIds, type AuthTheme, type AuthThemeColors, AuthThemeProvider, type AuthThemeProviderProps, type AuthThemeRadii, type AuthThemeSpacing, type AuthThemeTypography, BffAuthStatus, type BffDeviceState, type BffLoginConfig, type CreateBffAuthClientOptions, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, type DevicePinCapableClient, type DevicePinDisableCapableClient, type DevicePinEnrollCapableClient, DevicePinEnrollErrorKey, DevicePinEnrollForm, type DevicePinEnrollFormProps, type DevicePinEnrollLabels, type DevicePinEnrollResult, DevicePinErrorKey, DevicePinInput, type DevicePinInputProps, DevicePinLengthPicker, type DevicePinLengthPickerProps, DevicePinOffer, type DevicePinOfferProps, DevicePinSettingsCard, type DevicePinSettingsCardProps, type DevicePinSettingsLabels, type DevicePinUnlockCapableClient, type DevicePinUnlockLabels, type DevicePinUnlockResult, DevicePinUnlockScreen, type DevicePinUnlockScreenProps, type DevicePinUnlockedUser, ForgotPasswordFields, type ForgotPasswordFieldsLabels, type ForgotPasswordFieldsProps, ForgotPasswordForm, type ForgotPasswordFormLabels, type ForgotPasswordFormProps, type LoginConfigCapableClient, LoginForm, type LoginFormLabels, type LoginFormProps, OtpForm, type OtpFormLabels, type OtpFormProps, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyCeremonyMode, PasskeyCeremonyStatus, type PasskeyErrorCode, PasskeyLoginButton, type PasskeyLoginButtonProps, type PasskeyLoginLabels, PasskeySettingsCard, type PasskeySettingsCardProps, type PasskeySettingsLabels, PasswordPolicyError, PinForm, type PinFormLabels, type PinFormProps, type PreferencesClientOptions, type PreferredMethodClient, PreferredMethodHint, type PreferredMethodHintLabels, type PreferredMethodHintProps, PreferredMethodSettingsCard, type PreferredMethodSettingsCardProps, type PreferredMethodSettingsLabels, ResetPasswordError, ResetPasswordForm, type ResetPasswordFormLabels, type ResetPasswordFormProps, type RoleRoute, type RoleRouteTable, type UseBffAuthOptions, type UseBffAuthResult, type UseBffForgotPasswordOptions, type UseBffLoginConfigResult, type UseBffResetPasswordOptions, type UseDevicePinDisableArgs, type UseDevicePinDisableResult, type UseDevicePinEnrollArgs, type UseDevicePinEnrollResult, type UseDevicePinUnlockArgs, type UseDevicePinUnlockResult, type UseForgotPasswordSubmitArgs, type UseForgotPasswordSubmitResult, type UseOtpLoginOptions, type UseOtpLoginResult, type UsePasskeyCeremonyOptions, type UsePasskeyCeremonyResult, type UsePinLoginOptions, type UsePinLoginResult, type UsePreferredMethodSettingArgs, type UsePreferredMethodSettingResult, type UseResetPasswordFormArgs, type UseResetPasswordFormResult, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };