Backend-Only Authentication With Sapper & Firebase Admin

Marek van der Hoeven
The Startup
Published in
4 min readSep 21, 2020

--

In my last story, I described how to implement an authentication system with Sapper and Firebase Auth on the client-side. An alternative way is to use server-side sessions with the help of Firebase Admin and the Firebase REST API. Before I show you some code, a little background story about the idea behind this authentication flow.

0. Overview & explanation

Developing an authentication system with Firebase can be done in two ways: handling the session client-side or make it use your own session-based back-end. Some advantages of using Back-End only are:

  • No front-end bloat (saving precious KB's…)
  • Secure (when done right). The user won't have to interact with his Firebase-uid. Everything can be done via the shared store from Sapper.
  • This also circumvents the 1-hour session problem. Setting your own time-limit for your sessions (up to two weeks) via Firebase Admin.

This setup works nicely together with Sapper. I drew a beautiful picture of the overview of the architecture, with a step-by-step explanation below.

Imagine we have an application with a protected route, and the user logs in with their credentials.

  1. Our Sapper API-route will fetch the user from the Firebase REST-point and creates a session token with Firebase Admin. This token can be valid for up to two weeks.
  2. If successful, we populate our Sapper Session store via the middleware and save our user-info in it.
  3. Our store is shared with the client-side and the user will be able to perform authenticated actions.
  4. When a user returns to our application, the session token (saved as a cookie) will recognize our user and logs in automatically.

1. Setup a new project with protected routes

We start with a fresh Sapper-project named 'firebase-backend', install all the dependencies and then remove the entire blog-folder in /src/routes and the about.svelte page since we won't be needing those. Create two new blank pages named dashboard.svelte and a login.svelte.

npx degit "sveltejs/sapper-template#rollup" firebase-backend

Go to the Nav-component inside /src/components/ and add the new pages to it.

Nav component

2. Secure the dashboard page

If you run yarn dev and navigate to http://localhost:3000.You should be able to freely navigate between all the (empty) pages.

Let’s protect our dashboard.svelte for unauthorized access. Firstly, we use the sapper.middleware() to populate our Sapper store/session when a user connects to the server. This needs to be done in server.js. Add a user; its default value will be false. I use express btw, instead of polka.

Now we check in our dashboard.svelte if a user exists, otherwise we redirect to the login page.

dashboard.svelte is now protected

3. Log in as a user

Our dashboard page is now protected and will just redirect to the login page (since our user in our session is always false). We need to log in as a user and, as explained in chapter 0, we will do this in the back-end via API calls.

Firstly, we want to send an API-call with our credentials to the server via our login-page.

The API-call to /session does not exist yet. Before we create this API-route, we need some packages installed: Firebase Admin, node-fetch (to perform fetch actions on our back-end), body-parser, cookie-parser.

yarn add firebase-admin node-fetch body-parser cookie-parser

After installing these packages, create a file called firebaseAdmin.js in /src/-folder (which will have all your Firebase Admin config values). It should look something like this:

I use environment variables to not leak my credentials

Now we are set-up for our session-call. Create a new file called session.js inside /src/routes/-folder. This API-route checks the credentials sent from the client and tries to get an idToken via a call to the Firebase REST endpoint. Then it creates a session-cookie named fireCookie.

Before this works we need to adjust our server.js a bit

Our API-route is set, but if you try to make a call to it, an error shows that req.body is undefined. We need to adjust server.js by adding the cookieParser and use the body-parser to read JSON to our express server. Let's also adjust the Sapper middleware to set the user in our session when the fireCookie is found.

Now when a new user with a legit cookie connects, the session store of Sapper gets filled and the user can visit the dashboard page.

4. Loggin out

A user also needs to be able to logout. Simply create a logout-button in your dashboard.svelte, which calls a (soon to be created) API-route to sessionLogout.

Create a new API-route called sessionLogout.js inside your /routes/-folder and logout the session via the official Firebase Documentation methods.

Summary

So that's it. A simple way of managing user state, purely on the back-end and which shares its state via the Sapper Session Store. Since I wanted to keep this tutorial as simple as possible, I didn't focus too much on security. You might want to perform some extra's value-checks and implement a CSFR-token for sensitive-actions. Let me know what you think, or if things are missing!

--

--