Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation issue in Authentication with SSR #3585

Open
perissf1 opened this issue Dec 6, 2024 · 3 comments
Open

Documentation issue in Authentication with SSR #3585

perissf1 opened this issue Dec 6, 2024 · 3 comments

Comments

@perissf1
Copy link

perissf1 commented Dec 6, 2024

Angularfire Authentication guide shows how to support Auth context in server-side rendering. In the code sample, this line doesn't compile:

  const request = inject(REQUEST, { optional: true });

Because the compiler Cannot find name 'REQUEST'.

What's the correct import to add?

@google-oss-bot
Copy link

This issue does not seem to follow the issue template. Make sure you provide all the required information.

@jamesdaniels
Copy link
Member

Angular no longer includes that injection token by default, you need to add it to your server.ts manually. I'll work on documentation here

@jamesdaniels
Copy link
Member

jamesdaniels commented Dec 14, 2024

Still need to document, so I'll keep this issue open but I've added SSR authentication in the new ng19 based sample application in the root of this repo.

  1. Persist the user's idToken in a Cookie while on the browser—to combat race conditions use both onIdTokenChanged and beforeAuthStateChanged. We're working to make a better API here in the future.
    this.unsubscribeFromOnIdTokenChanged = onIdTokenChanged(this.auth, async (user) => {
    if (user) {
    const idToken = await user.getIdToken();
    cookies.set("__session", idToken);
    } else {
    cookies.remove("__session");
    }
    });
    let priorCookieValue: string|undefined;
    this.unsubscribeFromBeforeAuthStateChanged = beforeAuthStateChanged(this.auth, async (user) => {
    priorCookieValue = cookies.get("__session");
    const idToken = await user?.getIdToken();
    if (idToken) {
    cookies.set("__session", idToken);
    } else {
    cookies.remove("__session");
    }
    }, async () => {
    // If another beforeAuthStateChanged rejects, revert the cookie (best-effort)
    if (priorCookieValue) {
    cookies.set("__session", priorCookieValue);
    } else {
    cookies.remove("__session");
    }
    });
  2. Now that the idToken is stored in a cookie, we should parse it out in Express. REQUEST is back but is appears to be blank, so let's pass it into our application's render via request context
    .handle(req, { authIdToken: req.cookies?.__session })
  3. Inject the request context into the FirebaseApp provider on the server, pass the idToken to initializeServerApp
    provideFirebaseApp(() => {
    // TODO migrate to REQUEST once that's working
    const requestContext = inject(REQUEST_CONTEXT, { optional: true }) as {
    authIdToken: string,
    } | undefined;
    const authIdToken = requestContext?.authIdToken;
    return initializeServerApp(environment.firebase, { authIdToken });
    }),
  4. Make sure to pass FirebaseServerApp to your SDK instance providers, as FirebaseServerApp is not picked up by default
    const auth = getAuth(inject(FirebaseApp));
  5. Auth.currentUser will now be immutably locked to that user on a server render pass

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

No branches or pull requests

3 participants