DemoCode

The Firebase platform is a perfect fit for your Angular 2 web or mobile application as it offers various useful backend services as real-time database, storage, notification, authentication etc.

In this tutorial you’ll learn how to make use of the Firebase authentication service in your Angular 2 application. We’ll start from scratch and develop a sample application step-by-step.

Authentication is a common task for most web and mobile application. By using the Firebase authentication service, authentication functionality can be easily integrated in your application. The Firebase service can be configured to make use of various authentication providers like Google, Facebook, Twitter or GitHub. By using those providers the user is able to use existing web accounts to sign in.

Let’s first take a look at the sample application we’re going to build in this tutorial.

What We’re Going To Build

The Angular 2 application we’re going to build in this tutorial makes use of the Firebase authentication service. The user will be able to sign in with an existing Google account. The first page the user sees is the login page:

Clicking on the button “Login With Google” opens up the following pop-up window, so that the user is able to enter the credentials of an existing Google account or sign up for a new Google account.

After having signed in successfully the user is automatically redirected to the home page of the application:

Trying to access the home page without being logged in takes the user to the login page.

Prerequisites

Before we can start to implement the application we need to prepare the development environment. As we’ll make use of Angular CLI to setup the initial project and generate various pieces of the project we need to install it first. Angular CLI is available as a NPM package, so that the installation can be done by using the npm command:

$ npm install -g @angular/cli

For AngularFire2 to work we will also need to install typings and typescript.

$ npm install -g typings

$ npm install -g typescript

Initiating A New Angular 2 Project

With Angular CLI installed on your system, it’s easy to setup a new Angular 2 project:

$ ng new ngfbauth

This command creates a new folder ngfbauth and downloads and installs the Angular 2 project template into that folder. After the command is completed you can change into that folder and start up the application:

$ cd ngfbauth

$ ng serve

Our app should now be visible from a browser on the default url http://localhost:4200.

Add Bootstrap

We’ll make use of the Bootstrap Framework to style the user interface of our application. To include Bootstrap in the Angular 2 project the easiest way is to add the corresponding files to index.html and use a link to a CDN:

<!doctype html> <html> <head> <meta charset="utf-8"> <title>Ngfbauth01</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <app-root>Loading...</app-root> <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html>

Firebase Setup

Create a New Firebase Project

In order to be able to make use of the Firebase authentication service, we need to set up a new Firebase project first. This step is done in the Firebase backend which is called Firebase console and available at https//console.firebase.google.com.

You first need to create a Firebase account, so that you’re able to login to the console. After having logged in you’ll be able to see the following screen:

Click on button “Create New Project” to create a new firebase project. The following pop-up window opens. Here you can specifiy the project name and the country / region in which the project should be hosted:

Click on button “Create Project” to initiate the creation process. Once the project is ready you’ll be forwarded to the project’s overview page in the Firebase console:

In the left-side menu structure you’ll find the link “Authentication”. If you click on this link you’ll be taken to the configuration page of the Firebase authentication service. Switch to the tab “Sign-In Method”. Here you’ll find a list of all sign-in providers supported by the Firebase authentication service:

By default all of the providers are disabled. In the following example we would like to use Google authentication in our Angular 2 application, so we need to enable the Google authentication provider in this view:

Install AngularFire2

AngularFire2 is the official Firebase library for Angular 2. The project website can be found at https://angularfire2.com. As we would like to use AngularFire2 to make use of the Firebase authentication service in our Angular 2 project we need to install that library first:

$ npm install firebase angularfire2 --save

Running this command makes sure that both libraries – the Firebase core library and the AngularFire2 library – are added as dependencies to package.json and are downloaded to the node_modules folder.

Add Firebase Configuration to AppModule

In the next step we need to include the AngularFire library in our project. We do that in app.module.ts by first adding an import statement for AngularFireModule and then adding AngularFireModule to the array which is assigned to the imports property of the @NgModule decorator:

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AngularFireModule} from 'angularfire2'; import { AppComponent } from './app.component'; export const firebaseConfig = { apiKey: "<your-key>", authDomain: "<your-project-authdomain>", databaseURL: "<your-database-url>", storageBucket: "<your-storage-bucket>", messagingSenderId: "<your-messaging-sender-id>" }; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule, AngularFireModule.initializeApp(firebaseConfig) ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Note, that we’re adding the AngularFireModule to our application by calling the factory method initializeApp and passing in a configuration object. This firebase configuration object consists of a set of properties (apiKey, authDomain, databaseUrl, storageBicket, massagingSenderId). These settings are specific to the Firebase project and can be retrieved from the Firebase console.

Implement An Authorization Service

In order to use the Firebase authentication service within our application it’s a good idea to create an Angular 2 service which encapsulates the code which is needed to deal with that service. Let’s create a new service by using Angular CLI again:

$ ng generate service providers/auth.service.ts

The following two files are added to the project structure:

src/app/providers/auth.service.ts

src/app/providers/auth.service.spec.ts

As we’re not focusing on setting up test cases, we’re not going to use file auth.service.spec.ts in this tutorial. The service implementation is done in file auth.service.ts:

import { Injectable } from '@angular/core'; import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2'; @Injectable() export class AuthService { constructor(public af: AngularFire) { } loginWithGoogle() { return this.af.auth.login({ provider: AuthProviders.Google, method: AuthMethods.Popup }); } logout() { return this.af.auth.logout(); } }

We need to import AngularFire, AuthProviders and AuthMethods from the AngularFire2 library first. Next, the AngularFire service is injected into the constructor of the service. By using the public keyword we’re making sure that a public class member is created at the same time, so that the service instance is accesible from inside and outside of the service class.

The implementation of the AuthService class consists of two methods:

loginWithGoogle()

logout()

The loginWithGoogle() method is used to call the login() method of the auth object of the AngularFire instance. This login methods expects to get an configuration object which describes which authentication provider and which authentication method should be used. As we would like to use Google authentication the value AuthProviders.Google needs to be assigned to the provider property. When invoking the authentication process we would also like to display a pop-up window for signing in to the user. To achieve this application behaviour we need to assign the value AuthMethods.Popup to the method property.

The logout service method only consists of one line of code. We’re calling the method logout of the auth object of the AngularFire object to make sure that the user is logged out.

Now we now need to add our provider to app.module.ts as well. This is done by adding another import statement:

import { AuthService } from './providers/auth.service';

Furthermore we need to add the providers property to the @NgModule decorator:

providers: [AuthService]

The providers property expects to get an array assigned. This array contains all service providers which should be made available. In our case this array contains one element: AuthService.

Implement LoginPage Component

Next let’s add a login page to our application. We do that by generating a new component by using the following command:

$ ng generate component loginPage

This command create a new folder src/app/login-page and in that new folder you’ll find the following new files:

login-page.component.ts

login-page.component.css

login-page.component.html

login-page.component.spec.ts

Note, when we’re using Angular 2 CLI to generate a new component, that component is automatically added to AppModule.

Let’s first implement the template of the component in login-page.component.html:

<div class="container"> <div> <h1>Login To Your Account</h1> <button class="btn btn-default" (click)="login()">Login With Google</button> </div> </div>

Nothing unexpected here! The template is just consisting of a headline and button. The click event of the button is connected to the login() method of the component. Let’s add the corresponding implementation to class LoginPageComponent in file login-page.component.ts:

import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from '../providers/auth.service'; @Component({ selector: 'app-login-page', templateUrl: './login-page.component.html', styleUrls: ['./login-page.component.css'] }) export class LoginPageComponent implements OnInit { constructor(public authService: AuthService, private router:Router) { } ngOnInit() { } login() { this.authService.loginWithGoogle().then((data) => { this.router.navigate(['']); }) } }

The login() method is implemented to make use of AuthService to initiate the Google login by using the service method loginWithGoogle. As this method is rerturning a Promise we can attach the then method to wait for the promise to be resolved. When the promise is resolved, we’re using the Router service to navigate to the default route. The router configuration will be added later to to our application.

Implementing HomePage Component

Next let’s add another component to our application: HomePageComponent. This component should be displayed when the default application router (/) is requested. Displaying this view should only be possible if the user is logged in. If the user is not logged in, he or she should be redirected to the LoginPageComponent automatically.

First let’s use Angular CLI again to generate the component:

$ ng generate component homePage

The following files will be added to the project:

home-page.component.ts

home-page.component.css

home-page.component.html

home-page.component.spec.ts

Again, we’re starting with the template implementation:

<div class="container"> <div class="row"> <div class="jumbotron"> <h1>Welcome</h1> <p>You should only be able to see that page when you're logged in!</p> <p><button class="btn btn-default" (click)="logout()">Logout</button></p> </div> </div> </div>

We’re using some Bootstrap CSS classes to style the page elements and we’re including a button. Clicking on that button calls the logout() method which is implemented in class HomePageComponent in file home-page.component.ts:

import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from '../providers/auth.service'; @Component({ selector: 'app-home-page', templateUrl: './home-page.component.html', styleUrls: ['./home-page.component.css'] }) export class HomePageComponent implements OnInit { constructor(private authService: AuthService, private router: Router) { } ngOnInit() { } logout() { this.authService.logout(); this.router.navigate(['login']); } }

Implementing Routing

The application router is configured in file app.module.ts:

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { RouterModule, Routes } from '@angular/router'; import { AngularFireModule} from 'angularfire2'; import { AppComponent } from './app.component'; import { AuthService } from './providers/auth.service'; import { LoginPageComponent } from './login-page/login-page.component'; import { HomePageComponent } from './home-page/home-page.component'; export const firebaseConfig = { [...] }; const routes: Routes = [ { path: '', component: HomePageComponent }, { path: 'login', component: LoginPageComponent } ]; @NgModule({ declarations: [ AppComponent, LoginPageComponent, HomePageComponent ], imports: [ BrowserModule, FormsModule, HttpModule, AngularFireModule.initializeApp(firebaseConfig), RouterModule.forRoot(routes) ], providers: [AuthService], bootstrap: [AppComponent] }) export class AppModule { }

The routes array consists of two Routes objects, one that connects the default route (/) with component HomePageComponent and one that connects route /login with LoginPageComponent.

This router configuration is activated by passing the configuration object to the factory method Router.Module.forRoot() and adding the returned RouterModule to the imports array.

In app.component.ts we’re now able to insert the code into the constructor which is needed to respond to the authentication status. The auth object of the AngularFire instance returns an Observable, so that we can use the subscribe method to respond to changes of the authentication status:

import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from './providers/auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { private isLoggedIn: Boolean; private user_displayName: String; private user_email: String; constructor(public authService: AuthService, private router: Router) { this.authService.af.auth.subscribe( (auth) => { if (auth == null) { console.log("Logged out"); this.isLoggedIn = false; this.user_displayName = ''; this.user_email = ''; this.router.navigate(['login']); } else { this.isLoggedIn = true; this.user_displayName = auth.google.displayName; this.user_email = auth.google.email; console.log("Logged in"); console.log(auth); this.router.navigate(['']); } } ); } }

We are defining the following three class members which are set each time the authentication status changes:

isLoggedIn : If logged in, isLoggedIn is set to true , if not to false .

: If logged in, is set to , if not to . user_displayName : If logged in this class member is set to the display name of the user account.

: If logged in this class member is set to the display name of the user account. user_email: If logged in this class member is set to the email address of the user account.

Furthermore we’re using the Router service to redirect the user each time the authentication status changes:

If authentication information is available the user is redirected to the default route, so that the output of HomePageComponent is shown.

If no authentication information is available the user is redirected to the login route, so that the output of LoginPageComponent is shown.

Now those three variables can be used in the corresponding template code as well:

<div class="container"> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="https://codingthesmartway.com">CodingTheSmartWay.com</a> </div> <div *ngIf="isLoggedIn"> <p class="navbar-text navbar-right">Logged In: {{user_displayName}} ({{user_email}})<p> </div> <div *ngIf="!isLoggedIn"> <p class="navbar-text navbar-right">Logged Out</p> </div> </div> </nav> <router-outlet></router-outlet> </div>

The template contains a Bootstrap navigation bar. Within the navigation bar the template contains code to print out the authentication status.

Summary

The Firebase authentication service makes it easy to integrate authentication functionality in your application. It support various authentication providers (like Google, Facebook, Github etc.) which can be activated and configured in the Firebase console. This makes it easy to use existing web accounts for authentication in your web or mobile application.