Image for post
Image for post
Photo by Dlanor S on Unsplash

Auth Using FirebaseUI, Firebase Functions & Session Cookies

Luis Gomes
Apr 5, 2019 · 6 min read

But…why session cookies?

Heard about Firebase Auth and it’s cool features that handle all the dirty Auth flow for you? Awesome, right?

Well, yes and no. Firebase Auth has been mainly used on the client side. Convenience but at the cost of performance. The client has to make numerous calls to the server, exchanging tokens and what not for every page that needs a user to be signed in. Back in the day when I didn’t know React, my endeavours to hack up a vanilla JS app led to a conclusion that this was not a good fit. We can do better.

Behold session cookies. Embedded in requests, these little guys are sent to the server and user information can be extracted from them by our server machine — yeah, no shortage of brutal computing power there.

Effectively, it’s one request with a cookie, checked on server and content rendered accordingly. No unnecessary back and forth. Sweet!

Having said that, implementing Firebase session cookies can be a pain due Firebase’s rather underwhelming documentation. This guide seeks to help you speed up that process filling the blanks where needed.

Installing Node.js and Firebase CLI

Node.js ships with npm and is needed to install Firebase CLI and a few packages later on. Firebase CLI is used for initialising projects, deployment etc.

  • Install Node.js
$ sudo npm install -g firebase-tools

Creating a Firebase Project and Initialisation

  • In the Firebase console, create a new project giving it an appropriate name.
$ firebase login
  • Navigate to a new directory on your machine and initialize the project. Select the project you created and select Functions and Hosting(using space bar) when prompted. Select JavaScript as the language for functions. Use the default yes / no for other prompts using the enter key.
$ firebase init

A project structure as follows will be created after the above command. The public folder is used for static assets like CSS, JS etc.

Image for post
Image for post
Project Structure

Setting up Handlebars, Express & cookie-parser

Handlebars is a templating engine used to render dynamic pages. Although the use of dynamic content in this guide is limited, we use it to render sample static pages to the client. Yes, public assests can be used to access static pages from a server, but the aim here is to check if a user is signed in and render accordingly which is not possible if we serve a page statically. Having said that, we will still use static assets like JS, CSS etc., which are publicly accessible, in pages rendered using handlebars.

  • In the terminal, navigate to the functions directory and run the following to install handlebars.
$ npm install --save express-handlebars
  • Create a directory named views in the functions directory. This will contain the .hbs files that will contain our sample pages.

Express will be used to define behaviour of routes, check for signed-in, and render pages accordingly.

  • Install Express in the same functions directory.
$ npm install --save express

We will be using cookies, hence the cookie-parser module can help handing the dirty work of extracting cookies from requests. Install it in the same directory as well.

$ npm install --save cookie-parser

Enabling Google Sign-in

We will only be using Google sign-in in this guide.

  • From the Firebase console, go to your project

That’s it for the setup, let’s get to the real stuff.

Setting Up the cloud function to use Express

  • Modify the /functions/index.js file so that it looks like this.
index.js

The above is a starter code that creates five routes and also initializes cookie-parser, Firebase-admin and the handlebar templating engine. The following functionality needs to be implemented on the routes.

  • / … this is the root route i.e when you do not enter any route in the hosted URL

Line 50 in the above code sets our Firebase Function name to app and instructs it to use the express app for all requests made to the function.

  • Modify the firebase.json file in the root directory. This rewrites all requests from from any source path to our app Firebase Function.
firebase.json

/signin route

  • Create signin.hbs in /function/views
signin.hbs

This is the view that will be rendered to the user. It uses FirebaseUI components to generate a sign in flow. As can be seen in Line 14, it uses a static script. This script initializes the FirebaseUI components and defines behaviour on user sign in. Create signin.js in /public/scripts

signin.js

Line 2–9: Enter your Firebase project credentials here

  • Open your project fromFirebase console

Line 16 defines a uiConfig object that configures the FirebaseUI that is rendered to the user. We only use Google sign-in in our sign-in options. We also define a signInSuccess callback that allows us to extract the idToken of the signed-in user and send it to the cloud function to generate a session cookie.

We use session cookies to keep track of whether a user is signed-in. Firebase does also offer client side alternatives for session tracking but session cookies are generally much faster.

Line 33 makes a call to the /sessionLogin route with idToken as a query parameter of the GET request. We will define this route shortly. This route generates and saves a cookie in the response.

  • Finally, define the /signin route in index.js

/sessionLogin route

As described earlier, this route handles generation of session cookies. We will define a function setCookie() that takes an idToken and response object as parameters.

  • Add the following function in index.js

When the above function redirects to /newPage the cookies are set on the request and can be used to extract user information. More on this in the next section.

/newPage route

This route only loads if a user is signed-in i.e only when valid cookies are set in the request. The page rendered displays the UID of the current user. Here is what it looks like

Image for post
Image for post

Achieving this is a two step process.

  • Check if cookie is valid and add an object containing the UID to the incoming request object that is to be processed by the route. This is done using a middleware function.

Line 8 adds a decodedClaims object(which contains the UID) to the request object and next() invokes the callback defined on the /newPage route.

  • Now let’s define the /newPage route in index.js

This adds the middleware function in the route and also extracts the UID from the decodedClaims object that was added on the request object in the previous step. Line 4 renders newPage.hbs passing to it the UID.

  • Create /public/newPage.hbs as follows
newPage.hbs

Line 10 uses the uid passed from the previous step.

/ route (root route)

This is a the home route that offers options to sign-in, sign-out and a link to /newPage to test cookie based session tracking. Here is what it looks like

Image for post
Image for post
  • define the route in index.js
  • add home.hbs in /public
home.hbs

/signout route

This routes clears the set cookies hence effectively signing out the user and redirects to the root route.

  • Define the route as follows

Deploying

That’s it! You can now deploy and test this using the following command in your project folder. A URL to the hosted app will be presented when the command finishes execution. Use it to play around with what you just created.

$ firebase deploy

Gotchas

  • Firebase only supports setting of one cookie and with a specific name __session

References and Resources

Nova Semita

We invest in ambitious people who deserve better and help…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store