Skip to content

fix(auth): stop beforeAuthStateChanged from holding the app unstable - #3770

Merged
armando-navarro merged 3 commits into
angular:mainfrom
armando-navarro:a30-before-auth-state-changed
Sep 27, 2026
Merged

armando-navarro merged 3 commits into
angular:mainfrom
armando-navarro:a30-before-auth-state-changed

Conversation

@armando-navarro

Copy link
Copy Markdown
Collaborator

Fixes #3748

Restores beforeAuthStateChanged: { blockUntilFirst: false }, which #3590 added and #3613 dropped without comment.

Changes

  • @angular/fire/auth wraps beforeAuthStateChanged with blockUntilFirst set to true, so registering the hook adds a pending task that clears only when the callback first runs. Firebase runs this callback only on a sign-in or sign-out, so for a visitor who does neither, the app never becomes stable.
    • In the browser, ApplicationRef.whenStable() never resolves.
    • When the hook is also registered on the server, ng build fails during route extraction, and a server that renders per request never responds.
  • With the override, the callback still runs inside Angular's zone and injection context, and its returned promise still reaches Firebase, so a rejection still cancels the sign-in.
    • One other difference: a call outside an injection context now logs its per-call warning only at the verbose log level, as onMessage does.
  • Adding more injector safety #3590 added the override with the note "beforeAuthStateChanged should not block". zone log verbosity #3613 removed it at the spot where it added log-level overrides, and none of the issues zone log verbosity #3613 fixed involve this function, so the removal looks accidental.
  • docs/auth.md and the sample keep importing beforeAuthStateChanged from firebase/auth until a release carries this fix.

Verification

On an Angular 21.2 server-rendered app, comparing 21.0.0-rc.1 with a build of this branch:

  • Hook registered on the server: ng build on rc.1 fails after 34 seconds with Routes extraction was aborted. TimeoutError. With this branch it succeeds.
  • Hook registered on the server only while answering a request, with every route rendered per request: each request to rc.1 got no response within 60 seconds. With this branch, each returned a server-rendered page in under 30 milliseconds.
  • The cookie sync from docs/auth.md, which registers the hook only in the browser: on rc.1 the app did not become stable within 10 seconds. With this branch it became stable after 25 milliseconds.
  • npm run test:node: 331 specs, 0 failures. npm run test:chrome-headless: 107 passed, 48 skipped.

AngularFire wrapped beforeAuthStateChanged so that registering the
hook added a pending task, cleared only when the callback first runs.
Firebase runs that callback only on a sign-in or sign-out, so for a
visitor who does neither the app never became stable. Registered on
the server, it failed ng build during route extraction and left
server-rendered requests without a response.

This restores the blockUntilFirst: false override from angular#3590, which
angular#3613 dropped without comment while adding log-level overrides next
to it. The callback still runs inside Angular's zone and injection
context, and its returned promise still reaches Firebase, so a
rejection still cancels the sign-in. A call outside an injection
context now logs its per-call warning only at the verbose level, as
onMessage does.

Fixes angular#3748
@armando-navarro armando-navarro added bump: patch Retired 2026-09-27, use target: comp: auth Authentication (src/auth). comp: build/pipeline Build, bundling, packaging, release pipeline. comp: ssr Server-side rendering, hydration, @angular/ssr interop. comp: zones Change detection / zone.js / zoneless. type: bug Defect: expected behavior doesn't happen. labels Sep 25, 2026

@tyler-reitz tyler-reitz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving.

Rebuilt from the generator and confirmed src/auth/firebase.ts matches its output, with a control run flipping the override to prove that check can fail. The #3590 / #3613 history is exactly as you describe.

Two follow-ups, neither blocking:

The beforeAuthStateChanged from firebase/auth section of docs/auth.md describes the blocking behavior in the present tense and points at #3748 as open. Merging this closes #3748, so that section wants a version qualifier like the one in #3769's docs, or a follow-up issue to point at.

This override has now been added, dropped and re-added with no test. A spec in src/auth/auth.spec.ts asserting the app becomes stable after registering the hook would have gone red on #3613.

Merging this change closes angular#3748, so the section's present-tense note
would point at a closed issue. Also removed the false claim that the
@angular/fire/auth import makes ng build hang: the guide registers the
hook only in the browser, so its own build succeeds.
@armando-navarro

Copy link
Copy Markdown
Collaborator Author

Thanks Tyler.

  • docs/auth.md: done in the latest commit.
    • The section now says the blocking behavior applies to AngularFire 21.0.0-rc.1 and earlier, with beforeAuthStateChanged imported from @angular/fire/auth makes ng build fail during route extraction #3748 as the reference.
    • The code sample keeps its firebase/auth import, since that works on every release, and moving it to @angular/fire/auth waits for a release that carries this fix.
    • I also dropped the line saying the @angular/fire/auth import makes ng build hang. The guide's code registers the hook only in the browser, so its own build succeeds, and the build failure needs the hook registered on the server as well.

@armando-navarro
armando-navarro merged commit f182972 into angular:main Sep 27, 2026
24 checks passed
@armando-navarro armando-navarro added this to the 21.0.0 milestone Sep 28, 2026
@armando-navarro armando-navarro added target: patch This PR is targeted for the next patch release, and can be backported to older release lines and removed bump: patch Retired 2026-09-27, use target: labels Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: auth Authentication (src/auth). comp: build/pipeline Build, bundling, packaging, release pipeline. comp: ssr Server-side rendering, hydration, @angular/ssr interop. comp: zones Change detection / zone.js / zoneless. target: patch This PR is targeted for the next patch release, and can be backported to older release lines type: bug Defect: expected behavior doesn't happen.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

beforeAuthStateChanged imported from @angular/fire/auth makes ng build fail during route extraction

2 participants