Skip to content

Bug: amplify-authenticator broken with Angular zoneless change detection (provideZonelessChangeDetection) #6964

Description

@gage22171

Bug Report

Related issue: #4899 (OnPush change detection support)

Summary

<amplify-authenticator> does not work correctly with Angular's zoneless change detection (provideZonelessChangeDetection()) when MFA is enabled. Zoneless is a stable, supported feature in Angular 18–21 — this is a compatibility bug, not a feature gap.

With zoneless enabled and Zone.js removed from polyfills, the Authenticator renders but does not update the UI after the MFA challenge step. After entering a password and clicking "Sign in", the UI appears frozen on the MFA prompt until an unrelated user interaction (e.g., a mouse move) happens to trigger change detection.

This is a stricter superset of #4899. With zoneless, Zone.js is entirely absent, so AuthenticatorComponent's async state updates never schedule a change detection pass at all.

Environment

  • @aws-amplify/ui-angular: 5.3.3
  • Angular: 21
  • provideZonelessChangeDetection() enabled, Zone.js removed from polyfills
  • Cognito User Pool with MFA enabled

Steps to Reproduce

  1. Create an Angular 18–21 project with provideZonelessChangeDetection() in app.config.ts
  2. Remove zone.js from polyfills in angular.json
  3. Configure Cognito with MFA enabled
  4. Add <amplify-authenticator> to the root component
  5. Load the app and attempt to sign in — enter credentials and submit
  6. Observe that the UI does not transition to the MFA challenge step (or from MFA to authenticated) until an unrelated mouse event fires

Expected Behavior

The Authenticator component works correctly with zoneless change detection. All state transitions (sign in, MFA challenge, authenticated) update the UI immediately — consistent with how any Angular 18–21 component is expected to behave.

Why This Is a Bug

Zoneless change detection has been stable and supported since Angular 18 and is the recommended default in Angular 19+. Angular 21 applications using provideZonelessChangeDetection() are using a first-class, documented Angular API. A library component that breaks under it has a compatibility bug, not a missing feature.

Note on Fix Approach

markForCheck() alone is not sufficient for the zoneless case — it marks the component dirty but relies on Zone.js to actually trigger a change detection run. With Zone.js absent, the dirty flag is never processed.

For full zoneless compatibility, the fix needs to either:

  • Call ChangeDetectorRef.detectChanges() after async auth state updates (runs CD synchronously, no Zone.js needed), or
  • Migrate internal auth state to Angular signals (signal writes automatically schedule a CD pass in the signal graph)

markForCheck() is the correct fix for the OnPush case in #4899, but zoneless requires one of the above approaches.

The stalled community PR #4997 uses markForCheck() + RxJS — that would fix #4899 but would still leave zoneless broken. A complete fix needs detectChanges() or signals.

Workaround

None known that doesn't require re-adding Zone.js or wrapping the entire Authenticator in a custom component with manual ApplicationRef.tick() calls.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions