Skip to content

docs(auth): rewrite the server-side rendering section - #3740

Open
armando-navarro wants to merge 1 commit into
angular:mainfrom
armando-navarro:docs-auth-ssr
Open

docs(auth): rewrite the server-side rendering section#3740
armando-navarro wants to merge 1 commit into
angular:mainfrom
armando-navarro:docs-auth-ssr

Conversation

@armando-navarro

Copy link
Copy Markdown
Collaborator

Checklist

  • Issue number for this PR: Documentation issue in Authentication with SSR #3585
  • Docs included?: yes (documentation-only change)
  • Test units included?: no (documentation-only change)
  • In a clean directory, yarn install, yarn test run successfully?: not applicable, no source changed

Description

Rewrites the Server-side Rendering section of docs/auth.md, which documented a setup that does not work.

Defects in the old section:

  • It read the ID token through inject(REQUEST) and request.headers.authorization, but REQUEST is a standard Request, so headers come from headers.get(...).
  • initializeServeApp in the import list is a typo.
  • provideAuth is missing its closing paren.
  • REQUEST and FirebaseApp are used without being imported. Documentation issue in Authentication with SSR #3585 is a reader hitting this one.
  • A bare ... placeholder inside the providers array does not parse.

The new section documents the path that works, as four steps, each with the reason it is needed:

  • RenderMode.Server on any route that has to render as the signed-in user. ng new --ssr scaffolds every route as RenderMode.Prerender, and Angular supplies REQUEST and REQUEST_CONTEXT only on server-rendered routes.
  • A __session cookie kept in sync with the ID token, with secure and sameSite set, and why that cookie name matters behind Firebase Hosting.
  • Replacing the generated handler in server.ts rather than adding a second one.
  • Passing inject(FirebaseApp) to every provider, not only provideAuth, because ng add writes them with no argument.

Leaving out any one of the four still renders the page, signed out, with no error anywhere. That silence is what made the old section expensive to debug, so each step states what breaks without it.

The section was written against a new ng new --ssr Angular 21 app set up with ng add @angular/fire@next, where a signed-in user's first request to a freshly started server returns signed-in HTML.

One import is deliberately inconsistent, and the section explains it:

  • beforeAuthStateChanged comes from firebase/auth, not @angular/fire/auth.
  • Our wrapper keeps the app marked busy until that callback first runs, and it only runs on a sign-in or sign-out.
  • So importing it from AngularFire makes ng build hang during route extraction and fail with a timeout.
  • I am filing that bug separately.

Also corrects the emulator example further down the same file, which used the no-argument getAuth that the new section warns against.

Documentation only, no source or API changes.

Fixes #3585

The old section documented a setup that no longer works. It described
reading the ID token from an Authorization header via REQUEST, whose
headers it accessed with Node property syntax even though REQUEST is a
standard Request, and its snippet had a typo in an import, a missing
paren, two identifiers used without importing them, and a bare
placeholder that does not parse.

The new section documents the path that works today, verified end to end
against a brand new Angular 21 SSR app that added AngularFire with
ng add. A signed-in user now provably gets a signed-in server render.

Four things the old section omitted, each of which silently produced a
signed-out page with no error to debug against:

- The CLI scaffolds every route as RenderMode.Prerender, and Angular
  supplies REQUEST and REQUEST_CONTEXT only on RenderMode.Server routes,
  so the token never reaches the render.
- The generated server.ts already has a handler that renders the app.
  Adding a second one rather than replacing it means the original wins
  and the token is never passed in.
- ng add writes provideAuth and provideFirestore with no argument, which
  resolves the default app. On a signed-in request the factory builds a
  server app instead, so those providers fail on a freshly started
  server.
- Registering more than one Firebase app makes AngularFire fall back to
  the default app, which discards the server app entirely.

beforeAuthStateChanged is imported from firebase/auth rather than
@angular/fire/auth, and the section says why. The AngularFire wrapper
marks the app busy until the callback first runs, and that callback only
runs on a sign-in or sign-out, so importing it from AngularFire makes
ng build hang during route extraction and fail with a timeout.

Also corrects the emulator example further down the file, which used the
no-argument getAuth that the new section warns against.
@armando-navarro armando-navarro added comp: auth Authentication (src/auth). comp: docs Documentation. comp: ssr Server-side rendering, hydration, @angular/ssr interop. type: chore Maintenance with no user-facing behavior change. labels Aug 11, 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: docs Documentation. comp: ssr Server-side rendering, hydration, @angular/ssr interop. type: chore Maintenance with no user-facing behavior change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Documentation issue in Authentication with SSR

1 participant