Ngxs and Firebase Authentication

How to store the Firebase auth state in Ngxs

I am working on a very small Angular application. I did not want to make a custom solution for authentication so I decided to use an existing one. It is also important that only my colleagues from Exponea can sign in to the application. Perfect excuse to give Firebase a shot!

Adding Ngxs State

I started by adding Ngxs to my application.

yarn add @ngxs/{store,router-plugin,devtools-plugin}

This command installs the base package, as well as adding support for Redux dev tools and the router. Then I added the required modules to my main module.

User State

I want to store my authentication state in a user state. So I created a new file called user.state.ts and added a new class for the state. In Ngxs, you create Typescript classes and use decorators to define the state and its actions. Cool, eh?

The file contains the definition of the data model of the state as well as the actions it reacts to. The UserStateModel interface contains a User (or null if not signed in) and loaded boolean which indicated whether the user was already loaded.

The UserState class defines the state itself. You can see that it is decorated with the@State decorator. The state will react to 3 actions — logging in, logging out, and setting the user (this one will be used to set the loaded user from Firebase later).

When the user presses a login button, the LoginAction is dispatched to the store. Similarly, when the user visits the /logout page, the LogoutAction is dispatched to the store. Ngxs allows you to wait for the action to complete so it allows me to do this in the page view component:

I can wait for the logout action to complete and then redirect to the login page. Easy.

Adding Firebase

In order to implement the authentication, it was time to add Firebase to the application.

yarn add firebase @angular/fire

Just like before, I started by adding the Firebase module to my main module.

You probably noticed that there is a reference to environment.firebaseConfig. This is in the environment.ts file and it is different for development and for production. I had to create 2 Firebase projects in the Firebase console and copied each configuration to the environment files.

Logging In and Out

Now I came back to the user state which I created earlier. I could now implement the login and logout actions using Firebase.

There are a few important points in this implementation. First, I injected the AngularFireAuth service to interact with Firebase. Then I created an authentication provider — in this case, I wanted to use Google authentication — and set a custom parameter hd to our Exponea domain. This tells Google to only allow people who have an Exponea email to log in. It also shows it in the UI. Finally, in the action handler functions, I used signInWithRedirect and signOut. You can also use signInWithPopup instead if you want. Note that there is no extra step required to make the redirect work, Firebase takes care of that for you.

Also, note that both functions are async and I used await in the function bodies. Ngxs actions can be asynchronous and that allows you to wait for them to complete.

To finish off, I needed to get the user from Firebase and place it in the Ngxs store to use it further in my application. Thankfully, this is very easy because Firebase exposes an observable of the user.

As you can see, all I did was to subscribe to the observable provided by Firebase and dispatch Ngxs action to update the state. There’s one catch — you cannot store the whole user in the Ngxs state because the provided object contains also a few methods and internal properties. So instead I made a private function to extract the important user properties and only store those in the Ngxs state.

That’s it!

Thank you for reading this article! If you like it, well, you know what to do. 👏👏👏 + ❤️❤️❤️ + Follow me for more great content. Have a wonderful day!