---
title: "Streamline SSR app development with FirebaseServerApp"
description: "The Firebase Web SDK has introduced FirebaseServerApp"
published: "2024-05-24"
last_updated: "2024-05-24"
authors:
  - "David Della Bitta (Software Engineer)"
categories:
  - "Web"
  - "JS SDK"
  - "Authentication"
  - "SSR"
  - "Next.js"
canonical_url: "https://firebase.blog/posts/2024/05/firebase-serverapp-ssr"
---

# Streamline SSR app development with FirebaseServerApp

*Published May 24, 2024 by David Della Bitta (Software Engineer)*

---
Working with Server-Side Rendering (SSR) frameworks and the traditional Firebase JavaScript SDK can present challenges in handling Firebase Auth user sessions in both CSR (Client-Side Rendering) and SSR code. Often implementations duplicate logic on the client and the server, which can increase code complexity, introduce race conditions, and significantly increase render time while waiting for redundant asynchronous operations to complete.

To address these challenges, the Firebase Web SDK has introduced `FirebaseServerApp`, a new type of `FirebaseApp` object that enables client-authenticated auth sessions created in the browser to be shared with SSR rendering phases in Node.js.

### FirebaseServerApp usage

The process of creating an instance of `FirebaseServerApp` is comparable to creating an instance of `FirebaseApp`. In fact, your application may use an instance of `FirebaseServerApp` wherever a `FirebaseApp` instance is used. However, there are a few additional pieces of information that can be configured in `FirebaseServerApp`, most importantly a Firebase Auth user ID token.

When an instance of `FirebaseServerApp` is initialized with an Auth ID token, it enables seamless bridging of authenticated user sessions between the client-side rendering (CSR) and server-side rendering (SSR) environments. Instances of the Firebase Auth SDK initialized with a `FirebaseServerApp` will attempt to log in the user on initialization without the need for the application to invoke any sign-in methods.

```javascript
import { initializeServerApp } from "firebase/app";
import { getAuth } from "firebase/auth";

// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
  // ...
};

const firebaseServerAppSettings = {
  authIdToken: idToken  // We'll explain how to get the
                        // idToken in the service worker
                        // example below.
}

const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);

// FirebaseServerApp and Auth will now attempt
// to sign in the current user based on provided
// authIdToken.
```

The use of `FirebaseServerApp` allows developers to leverage any of Auth’s many sign-in methods on the client, ensuring that the session seamlessly continues on the server-side, even for those sign-in methods that require user interaction. Additionally, it enables the offloading of heavy-lifting operations to the server, such as database queries, which should improve your app’s rendering performance.

Now that we have the baseline down, let’s go over some recommendations for your app’s use of `FirebaseServerApp`.

### Plumbing Auth ID Tokens into the SSR phase

[Our example Firebase Auth service worker](https://firebase.google.com/docs/auth/web/service-worker-sessions) facilitates the transmission of authenticated Auth ID tokens from the client to the SSR rendering phases. It works to intercept fetch requests that would trigger an SSR phase, and it appends the ID token in the request headers. In addition, it proactively attempts to refresh the token to minimize the possibility of invalid ID tokens reaching the SSR phase.

While you may write a custom solution using your chosen SSR framework to attach the User’s Auth ID token to the SSR request, we suggest at least reading over our service worker to note some of our  best practices for Auth ID token management.

### Await authStateReady to ensure user authentication

Standard Firebase Auth sign in operations return a promise that applications may await before continuing. This allows apps to wait for the authentication steps to resolve, and then to leverage the signed-in user for other Firebase operations (storage, database access, etc) later on in the application flow.

In contrast, the initialization of the `FirebaseServerApp` returns immediately. It will attempt to sign in the user behind the scenes, which is a nice streamlined experience, but alas, there’s nothing to await.

Therefore, to ensure that your app actually has a signed in user before attempting to access databases, storage, or other operations, it's recommended to await `FirebaseAuth.authStateReady()` or to use the `onAuthSateChanged` handler to detect user sign-in stemming from `FirebaseServerApp` initialization.

```javascript
const serverApp =
  initializeServerApp(firebaseConfig,
                      firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);

await serverAuth.authStateReady();
if (serverAuth.currentUser === null) {
  // authIdToken was missing or invalid.
}

// Proceed with any Firebase operations that
// require a signed-in user.
```

### Handling no current user after initialization

It's crucial to verify the existence of the `currentUser` in the Auth module after initialization is complete. If `currentUser` is null, it could indicate one of two things: either the `FirebaseServerAppSettings.authIdToken` was omitted during initialization, or the Auth service detected an invalid Auth ID token.

In these cases we recommend that your app redirects to a sign in page, as it’s probably a signal that the user either hasn’t signed in, or that their Auth session on the client has expired.

### FirebaseServerApp cleanup

In SSR applications, there might be many asynchronous operations running concurrently and independent of each other. It can be challenging to determine the precise end of the rendering pipeline, which raises the question: “when should I clean up the app's use of the `FirebaseServerApp` object?”

`FirebaseServerApp` uses reference counting. Creating a new `FirebaseServerApp` with identical parameters will return the same `FirebaseServerApp` and increment its reference count. This design allows us to reuse the `FirebaseServerApp` with the same authorization header to save resources.

Invoking `FirebaseServerApp.delete()` will decrement the reference count and mark the object for deletion if the reference count drops to zero. In modern SSR frameworks however, it can be hard to determine when to delete the app—there’s an option to automatically decrement the reference count when another object (say the request) is garbage collected, with the  `releaseOnDeref` field. Here’s an example in Next.js. Here, we assume that the Auth ID token was appended to the request headers by the example service worker mentioned above.

```javascript
// Example usage in Next.js.
import { headers } from 'next/headers'
import { redirect } from 'next/navigation'
import { FirebaseServerAppSettings, initializeServerApp } from "firebase/app";
import { getAuth } from 'firebase/auth';

const firebaseConfig = {
  // ...
};

export default async function Page() {
  const headersList = await headers();
  const authIdToken = headersList.get('authorization')?.split(' ')[1];
  const serverApp = initializeServerApp(firebaseConfig, { authIdToken });
  const auth = getAuth( serverApp );
  await auth.authStateReady();
  if( !auth.currentUser ) {
    return redirect("/unauthorized");
  }
  // ...
}
```

### What’s next

You can start using the `FirebaseServerApp` feature starting with the `10.10.0` release of the Firebase JavaScript SDK.

We’re working on new ideas to take FirebaseServerApp further and we’d like to hear your thoughts! Visit our [Firebase JavaScript SDK GitHub repository](https://github.com/firebase/firebase-js-sdk) if you encounter any technical issues, and reach out to us in our [Firebase UserVoice](https://firebase.uservoice.com/forums/948424-general) to let us know of any  feature requests. Thanks!
