You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Multi-Step Signup With Firebase Email Auth and Angular Reactive Forms
Episode 68 written by Jeff DelaneyFirebase password auth can be configured with a few lines of code, but what happens if you need additional custom user data before authorizing activity in your app? In this lesson, my goal is to show you several important concepts.
- Email/Password Auth
- Reactive Forms in Angular
- Security with custom Firebase user data
What are we Building?
This lesson is based off of the Firstarter PWA starter app, which is organized into NgModules. It is not needed to follow this lesson, but it does have a notification service for showing errors to the end user.
We are going to build a custom user authentication flow backed by Firebase email-password auth. When users first sign-up, they must fill out a custom form with a catchphrase before they are fully authorized to use the app. The catchphrase can be anything, for example “I love Angular!” - it’s just a placeholder for any type of custom data you can imagine.
Initial Setup
Full source code for multi-step signup.
I’m only going to provide the relevant pieces of code here. If you want to duplicate the styling and structure of this demo, clone the demo project above.
To use reactive forms in Angular, make sure to import the ReactiveFormsModule
in the NgModule that contains the signup form.
import { ReactiveFormsModule } from '@angular/forms'; |
Auth Service
Don’t forget have email password auth enabled in the Firebase console.
I covered much this code in the past with the Firestore OAuth Lesson, but we need to add an extra methods to it for email-password auth.
To signup a user, we need to send Firebase an email address and password string. Firebase will determine if this data is valid and return a promise with the newly created user. Once we have that user, we create a custom document in Firestore with an ID that matches the user’s UID.
import { Injectable } from '@angular/core'; |
Login Form Component
Now we’re ready to jump into Angular’s reactive forms module. The first step is to include the reactive forms module in the corresponding NgModule.
I am going to write all of the logic in a single component, but you might break this down into multiple components if the form is large and complex. Here’s an overview of what’s happening.
- Validate the user has a valid email/password.
- Once authenticated, the user is shown a secondary form. Unlike the initial form, it will update custom information on the user’s document in Firestore.
A great way to keep your reactive forms concise is to use typescript getters. For example, adding the code get email() { return this.signupForm.get('email') }
eliminates the need to call the parent form repetitively when accessing its validation state or value.
import { Component, OnInit } from '@angular/core'; |
Multi-Step Login Form HTML
What the hell is this (auth.user | async) || {} as user
line of code? In plain English, it’s like saying if we don’t have a user, give me an empty object, then set that as a template variable called user. The idea is to set a template variable, while preventing ngIf from hiding the html when the user is null.
For each form input, we can connect it to the reactive form with formControlName
attribute. This will tell the form to validate the input, which you can use to conditionally display error templates or CSS classes.
<ng-container *ngIf="(auth.user | async) || {} as user"> |
Router Guard
At this point, the user could skip the secondary step and navigate directly to data they’re not supposed to see. I am going to provide a router guard to prevent unauthorized navigation. The important line here is !!(user && user.catchPhrase)
, which converts the user’s catchPhrase
property to a boolean. In other words, if their Firestore user document does not have a catchPhrase, we block access the route.
import { Injectable } from '@angular/core'; |
Backend Firestore Rules
To fully secure the app, we should also set backend rules in Firestore to prevent an unauthorized user from seeing private data. There are thousands of potential rule configurations, so check out the docs if you need a more specialized configuration. The code below checks if the user’s document exists or it can check a custom property on the user document equals a specific value.
match /some-document { |
The End
That’s it for multi-step signup with Angular 5 and Firebase password auth. Hopefully this gives you a good starting point to build large complex forms in your app.