Bob at Genuitec Virtual evangelist at large. The face of Genuitec often appearing in graphics. Pen-name for our more shy writers of content.

In this tutorial, we are going to build an Angular 5 authentication system using Google’s Cloud Firestore. Most of the applications we build require some kind of authentication, and the simplest and fastest way to get started with that is by using the Firestore – a flexible, scalable database for mobile, web and server development. You will learn to develop a fully functioning Angular 5 authentication system using Firestore.

We will be using the official tool for Angular and Firebase integration – AngularFire that allows you to work with Cloud Firestore, the new flagship database for mobile app development. It improves on the successes of Realtime Database with a new, more intuitive data model. Cloud Firestore also features richer, faster queries and scales better than Realtime Database. We will also be using Angular IDE through this tutorial, though you can use Webclipse or MyEclipse too, following exactly the same steps. Ensure that the latest version of Angular CLI is installed on your computer. You also need a Google account to be able to sign in to Firebase Console, where you will be creating the app that we will work with, in this tutorial.

Create an Angular Project and a Firebase App

Before beginning, do ensure you are in the Angular Perspective (Window > Perspective > Open Perspective > Other > Angular) for an optimum workspace layout and development experience.

Open Angular IDE, and from the top menu select File , then New , then Angular Project . In the New Angular Project wizard, enter AngularAuth as the project name, 1.6.5 as the Angular CLI version, and you can choose whatever Node and NPM versions you wish, or stick with the defaults. Click Next, then click Finish.

Once the project is created, the next thing to do is to create an app in Firebase, so navigate to the Firebase Console and then click on Add Project to create a new project. Give it a name (we called it AngularAuth ), and then click on Create Project .

With Angular IDE, you don’t need to have any prerequisites installed to get started with Angular development. We’ll download your preferred versions of Node, NPM and the Angular CLI for you – or you can use versions you already have installed. The best part: your projects remain 100% compatible with the Angular CLI, so you can switch between the CLI and IDE as desired.

After the project has been created, you will be redirected to the project’s overview page. That’s it for now with Firebase, so let’s go back to the Angular IDE to create some components.

We need a Homepage, Login page, and Sign Up page to showcase how our Angular 5 Authentication is working, so we need to create an Angular component for each of these pages. We will use one of the features that makes Angular IDE so awesome – the Create Component shortcut. Navigate to File > New > Component to create a new component.

Give the first component the name homepage , as in the screenshot below, and uncheck the Create Component with Unit Test flag , because Unit Testing is beyond the scope of this tutorial, but we can leave the Generate Component using the prefix location flag , which is the default from Angular. The prefix is simply the word that goes before the selector of every component you generate with the CLI. If you want to know more about it or change the prefix, read more on StackOverflow.

Click Finish when you are done. This will automatically run the command ng g component homepage –spec false in Angular IDE’s terminal.

src/app/app.component.html

app.component.html

<app-homepage> </app-homepage>

The app-homepage is the selector for the homepage component we created earlier.

Next, we will create the other two components needed to run the app and then install AngularFire2 and Firebase. Instead of using the wizard, this time let’s do this with the command line. Open the Terminal+ view, make sure the AngularAuth project is selected in the Project combo and execute the following command:

ng g c login --spec false && ng g c signup --spec false && npm install firebase angularfire2

The above command will create a LoginComponent , SignupComponent and then install firebase and angularfire2 npm packages. We achieved quite a bit with that one command, nice!

Integrating with Firebase

Now, with the installed npm packages we need configure our Firebase application to enable it to be able to communicate with your Angular application.

Add Firebase to your web app

Now, let’s import the AngularFire modules to the app.module.ts file. We’re also going to paste in the config object we copied in the earlier step. Please note that we’ve renamed it to firebaseConfig .



Your app.module.ts file will look like the one below. Please remember to use your own config object, the one in the snippet below has invalid values.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import { BrowserModule } from '@angular/platform-browser' ; import { NgModule } from '@angular/core' ; import { FormsModule } from '@angular/forms' ; import { AngularFireModule } from 'angularfire2' ; import { AngularFireAuthModule } from 'angularfire2/auth' ; import { AppComponent } from './app.component' ; import { HomepageComponent } from './homepage/homepage.component' ; import { LoginComponent } from './login/login.component' ; import { SignupComponent } from './signup/signup.component' ; // Copy the firebaseConfig from your created project on the firebase console. const firebaseConfig = { apiKey : 'AIzaSyAywNGLBVmlk98jwaeqsFdm1hNMQ' , authDomain : 'angularauth-502.firebaseapp.com' , databaseURL : 'https://angularauth-502.firebaseio.com' , projectId : 'angularauth-502' , storageBucket : 'angularauth-502.appspot.com' , messagingSenderId : '11240551' } ; @ NgModule ( { declarations : [ AppComponent , HomepageComponent , LoginComponent , SignupComponent ] , imports : [ BrowserModule , FormsModule , AngularFireModule . initializeApp ( firebaseConfig ) , AngularFireAuthModule ] , providers : [ ] , bootstrap : [ AppComponent ] } ) export class AppModule { }

Next, we will set up the Authentication methods, by clicking on the Authentication link shown in the screenshot above. Once there, enable Sign-in for Email/Password and Google and then save.

To enable for other providers, you need an API key and API secret which can be easily generated by visiting the developers’ section of each of the providers.

Next, click on the Database on the sidebar at Firebase and then click on TRY FIRESTORE BETA . Choose Start in test mode and then click ENABLE .

Upon creation of the Database, check the Rules tab and make sure the content is similar to this:

1 2 3 4 5 6 7 service cloud . firestore { match / databases / { database } / documents { match / { document = * * } { allow read , write ; } } }

Now, let’s go to the auth.service.ts file and add some code to it.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import { Injectable } from '@angular/core' ; import { Router } from '@angular/router' ; import { AngularFireAuth } from 'angularfire2/auth' ; import * as firebase from 'firebase/app' ; import { Observable } from 'rxjs/Observable' ; import 'rxjs/add/operator/switchMap' ; @ Injectable ( ) export class AuthService { constructor ( private afAuth: AngularFireAuth , private router: Router ) { } login ( email : string , password : string ) { this . afAuth . auth . signInWithEmailAndPassword ( email , password ) . then ( value = > { console . log ( 'Nice, it worked!' ) ; this . router . navigateByUrl ( '/profile' ) ; } ) . catch ( err = > { console . log ( 'Something went wrong: ' , err . message ) ; } ) ; } emailSignup ( email : string , password : string ) { this . afAuth . auth . createUserWithEmailAndPassword ( email , password ) . then ( value = > { console . log ( 'Sucess' , value ) ; this . router . navigateByUrl ( '/profile' ) ; } ) . catch ( error = > { console . log ( 'Something went wrong: ' , error ) ; } ) ; } googleLogin ( ) { const provider = new firebase . auth . GoogleAuthProvider ( ) ; return this . oAuthLogin ( provider ) . then ( value = > { console . log ( 'Sucess' , value ) , console . log ( 'The given name is ' + value . additionalUserInfo . profile . given_name ) , this . router . navigateByUrl ( '/profile' ) ; } ) . catch ( error = > { console . log ( 'Something went wrong: ' , error ) ; } ) ; } logout ( ) { this . afAuth . auth . signOut ( ) . then ( ( ) = > { this . router . navigate ( [ '/' ] ) ; } ) ; } private oAuthLogin ( provider ) { return this . afAuth . auth . signInWithPopup ( provider ) ; } }

Now let’s create two more components, the EmailComponent and ProfileComponent , using the same method as before. Next, we’ll create the AppRoutingModule where we will create our routes. Create the app-routing.module.ts file in the src/app folder and fill it out with the following content:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { NgModule } from '@angular/core' ; import { Routes , RouterModule } from '@angular/router' ; import { LoginComponent } from './login/login.component' ; import { ProfileComponent } from './profile/profile.component' ; import { SignupComponent } from './signup/signup.component' ; import { EmailComponent } from './email/email.component' ; const routes: Routes = [ { path : '' , redirectTo : 'login' , pathMatch : 'full' } , { path : 'login' , component : LoginComponent } , { path : 'email-login' , component : EmailComponent } , { path : 'signup' , component : SignupComponent } , { path : 'profile' , component : ProfileComponent } ] ; @ NgModule ( { imports : [ RouterModule . forRoot ( routes ) ] , exports : [ RouterModule ] } ) export class AppRoutingModule { }

Now all we need to do is add the service we created earlier to the providers array in app.module.ts and import the AppRoutingModule we just created. Your app.module.ts file will now look like this (remember, the firebaseConfig object in the snippet below contains bogus values, ensure you have the valid values from your Firebase console):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import { AppRoutingModule } from './app-routing.module' ; import { BrowserModule } from '@angular/platform-browser' ; import { NgModule } from '@angular/core' ; import { FormsModule } from '@angular/forms' ; import { AngularFireModule } from 'angularfire2' ; import { AngularFireAuthModule } from 'angularfire2/auth' ; import { AppComponent } from './app.component' ; import { AuthService } from './auth.service' ; import { HomepageComponent } from './homepage/homepage.component' ; import { LoginComponent } from './login/login.component' ; import { SignupComponent } from './signup/signup.component' ; import { EmailComponent } from './email/email.component' ; import { ProfileComponent } from './profile/profile.component' ; // Copy the firebaseConfig from your created project on the firebase console const firebaseConfig = { apiKey : 'AIzaSyAywNGLBVmlk98jwaeqsFdm1hNMQ' , authDomain : 'angularauth-502.firebaseapp.com' , databaseURL : 'https://angularauth-502.firebaseio.com' , projectId : 'angularauth-502' , storageBucket : 'angularauth-502.appspot.com' , messagingSenderId : '11240551' } ; @ NgModule ( { declarations : [ AppComponent , HomepageComponent , LoginComponent , SignupComponent , EmailComponent , ProfileComponent ] , imports : [ BrowserModule , FormsModule , AppRoutingModule , AngularFireModule . initializeApp ( firebaseConfig ) , AngularFireAuthModule ] , providers : [ AuthService ] , bootstrap : [ AppComponent ] } ) export class AppModule { }

Now let’s go ahead and work in our LoginComponent file, so navigate to the login/login.component.ts . The method we will use there is the googleLogin() .

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { Component , OnInit } from '@angular/core' ; import { AuthService } from '../auth.service' ; @ Component ( { selector : 'app-login' , templateUrl : './login.component.html' , styleUrls : [ './login.component.css' ] } ) export class LoginComponent implements OnInit { constructor ( private authService: AuthService ) { } ngOnInit ( ) { } loginGoogle ( ) { this . authService . googleLogin ( ) ; } }

Fill out the component file, login.component.html like so:

1 2 3 4 5 <div class = "form-container" > <button ( click ) = "loginGoogle()" class = "google" > Login with Google </button> <button routerLink = "/email-login" class = "email" > Email </button> <a routerLink = "/signup" routerLinkActive = "active" class = "create-account-txt" > No Account? <strong> Create one here </strong> </a> </div>

Before we go ahead and verify that everything is working, we need to change the content of the app.component.html file:

Replace <app-homepage></app-homepage> with <router-outlet></router-outlet>

We should also add some styling to the form by editing the src/styles.css file . Add the following CSS code to it:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 body { background : # E2E4E6 ; padding - top : 4em ; } . form - container { background : white ; padding : 3.5em ; width : 500px ; position : fixed ; left : 45 % ; margin - left : - 250px ; } button { padding : 0.5em ; width : 100 % ; cursor : pointer ; margin - bottom : 15px ; font - size : 1.3em ; } . google { border : 1px solid # 95989A ; background : # fff ; background - size : 25px ; } . email { background : # ECECEC ; background - size : 25px ; } . create - account - txt { text - align : center ; display : block ; margin : 15px 0 ; } . auth - btn { background : # 3B8598 ; color : white ; } input . input - txt { background : # fff ! important ; padding : 0.5em 1em ; font - size : 1.3em ; border : 1px solid # BBBBBB ; width : 90 % ; margin - bottom : 1em ; }

Lastly, the profile component, which is the simplest of all. There we just need to add a Sign Out button that will take the user back to the Login Page.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { Component , OnInit } from '@angular/core' ; import { AuthService } from '../auth.service' ; @ Component ( { selector : 'app-profile' , templateUrl : './profile.component.html' , styleUrls : [ './profile.component.css' ] } ) export class ProfileComponent implements OnInit { constructor ( public authService: AuthService ) { } ngOnInit ( ) { } signOut ( ) { this . authService . logout ( ) ; } }

1 2 3 4 <p> Welcome to your secret profile! </p> <button ( click ) = "signOut()" > Sign Out </button>

Serving the Angular 5 Authentication Example Application

Finally let us run the Angular app with the server view in Angular IDE. If you don’t already see it, select Window , then Show view , then Servers ; right click on AngularAuth and click Start Server .





Use the Run or Debug context menu actions to automatically open the app in Chrome, or manually open http://127.0.0.1:4200 in your browser to see the app in action. Note that the Angular application is served at port 4200 by the ng serve command, executed by the Start Server action – which is why we use this port to access the app.

Now the login page looks like this:

If you click Login with Google , a new window will pop up, asking you to log-in with your Google account – you will have to go through whatever authentication you have set up for your account, like specifying an additional code for 2FA or allowing the login on your phone. Once you have successfully logged in, you will be taken to our sample profile page, with the option to Sign Out.

If you keep the console in chrome open, notice the line “The given name is: Bob” – this is because of a console.out statement we added to the service which picks out the given name from the account:

console.log('The given name is ' + value.additionalUserInfo.profile.given_name)

In the next tutorial, we’ll wire this into the page, but for now your Angular app does have access to some account information.

Conclusion

It’s pretty cool that we’ve been able to get Google sign-on working with relatively few lines of code, thanks to our Firebase integration. Of course, we didn’t do anything with the connected profile and we have left a few components un-implemented (like the Sign up and Email components), we’ll flesh those out in the next article in this series.