In this part, we will replace the existing localForage storage implementation with Firebase. This will make our application persistent between devices.


Here is what we will do:

  • Make an authentication layer to the Firebase API with email based authentication.
  • Use Firebase Storage to persist images.
  • Use Firebase Realtime Database.

More information about these technologies is available on the Firebase’s site.


Check out the other parts here:

Part 1Setup Ionic 2 Application and Take Photos with a Native Camera

Part 2Add a Local Storage Persistence Layer to your Photos

Part 3Use Location Plugins to Add Coordinates for Every Photo Taken and Place Your Images on Google Maps

Part 4: Change the Persistence Layer with Firebase, and Make a Real-time Application (This post!)



We need to sign in to the Firebase webpage with our Google account.

When it’s done, go to the developer console.

We need to make a new project for our application. There is a nice button saying “Add project.” Click it.

A modal window will pop up and ask you to type in the name of your project. You can type in what you want, or you can import Google project to Firebase (which was created before the Maps API), so I will import this project.

To create a new project, you need to select your region. After you have chosen one, click on the “Create project” button.

Create Project

It needs a little time to initialize the project. But after it’s done, you can start setting up the necessary resources. Click on the card and you will jump to the project’s dashboard.

 Let’s start with authentication.

In the authentication menu, we can setup the authentication providers for our application. I will only enable the email/password authentication, but you can enable more if you want.

Next, we will install the AngularFire2 package to handle the authentication easier. This library offers a simple API, based on Rxjs observables.

Use the following command to install the AngularFire2 package:

npm install angularfire2 firebase --save

At first, we need to initialize the AngularFire module with some config properties:

src/app/app.module.ts

import { AngularFireModule, AuthProviders, AuthMethods } from 'angularfire2';

import * as config from '../config.json';

const firebaseConfig = {
  apiKey: config.apiKey,
  authDomain: config.authDomain,
  databaseURL: config.databaseUrl,
  storageBucket: config.storageBucket,
  messagingSenderId: config.messagingSenderId,
};

const firebaseAuthConfig = {
  provider: AuthProviders.Password,
  method: AuthMethods.Password
};

// and into the imports array we add 

imports: [
  ...
  AngularFireModule.initializeApp(firebaseConfig, firebaseAuthConfig)
],

The config.json contains an object that can be copied from the Firebase console. We need to click on the web setup button

Web Setup

We get a modal that contains the secret keys. There are some lines like these:

// Initialize Firebase
var config = {
    apiKey: "...",
    authDomain: "...",
    databaseURL: "...",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "..."
};

We need to use these values above. We can put them directly to the FirebaseConfig object, or we can extract it to a json (without the 'var config = ' part) and gitignore to prevent committing secrets to the public git repository.

I also add an authentication service to separate the auth methods:

 src/service/auth.ts

import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';

@Injectable()
export class AuthService {
  constructor(
    public af: AngularFire
  ) {}

  create(email: string, password: string): firebase.Promise<any> {
    return this.af.auth.createUser({ email, password });
  }

  login(email: string, password: string): firebase.Promise<any> {
    return this.af.auth.login({ email, password });
  }

  logout(): firebase.Promise<any> {
    return this.af.auth.logout();
  }
}

These are the base methods that we will use in our components. We define the af: AngularFire provider as public, because we want to access it through the service. 

On the home page, we can check the authentication status to change the view states.

We get the af object from the service and subscribe the auth Observable to get notified from the auth status changes.

import { AlertController } from 'ionic-angular';

private user = null;

constructor(
  …
  private alertCtrl: AlertController, // to create modals
  private authService: AuthService,
  private storage: PhotoStorage
) {
  this.authService.af.auth.subscribe((auth) => {
    if (!auth) {
      this.user = null;
      this.storage.initDbByUser(null);
    } else {
      this.user = auth.auth;
      this.storage.initDbByUser(this.user.uid);
    }
  });
}

We store the user object in a private property. We will use this variable to change the view:

// At the title bar we have some buttons: login, logout, signup

<ion-buttons end>
  <button *ngIf="!user" ion-button icon-only (click)="signup()">
    <ion-icon name="person-add"></ion-icon>
  </button>
  <button *ngIf="!user" ion-button icon-only (click)="login()">
    <ion-icon name="log-in"></ion-icon>
  </button>
  <button *ngIf="user" ion-button icon-only (click)="logout()">
    <ion-icon name="log-out"></ion-icon>
  </button>
</ion-buttons>

// At the content we show the menu buttons only when user logged in

<div *ngIf="user">
  <div class="authenticated">
    {{ user.email }}
  </div>

  // … here are the home page items
</div>

We made a logout function which is simple as:

logout() {
  this.authService.logout();
}

Now, we have a signup and login function that will open a modal. We put a handler function that will run after pressing the modal’s “okay” button.

// createModal function was created because the signup and login modal is nearly the same

createModal(title: string, okLabel: string, handler: Function) {
  return this.alertCtrl.create({
    title,
    enableBackdropDismiss: false,
    inputs: [
      {
        name: 'email',
        placeholder: 'E-mail',
        type: 'email',
        value: '',
      },
      {
        name: 'password',
        placeholder: 'Password',
        type: 'password',
        value: '',
      }
    ],
    buttons: [
      {
        text: 'Cancel',
        role: 'cancel',
      },
      {
        text: okLabel,
        handler,
      }
    ]
  });
}

// the first two parameters are only labels,
// the third parameter is the handler function which is called after
// pressing the Register/Login button

signup() {
  const alert = this.createModal('Sign Up', 'Register', (data) => {
    if (this.isValid(data.email, data.password)) {
      this.authService.create(data.email, data.password);
    } else {
      return false;
    }
  });
  alert.present();
}

login() {
  const alert = this.createModal('Login', 'Login', (data) => {
    if (this.isValid(data.email, data.password)) {
      this.authService.login(data.email, data.password);
    } else {
      return false;
    }
  });
  alert.present();
}

// very minimal valdation to make sure the fields are filled

isValid(username, password) {
  return username && password;
}

These steps will allow us to make a simple authentication process to our application through the Firebase API.

I hope these steps help you integrate Firebase auth to any Angular application.

Some additional information about the AngularFire2: this library also can handle the Realtime-database actions with a simpler and more developer-friendly way than the Firebase SDK.

Unfortunately, it doesn’t handle the Firebase Storage part of the application. So, if you want to make more consistent applications, instead of multiple libraries, you can make all these steps with the original SDK with a little bit different API, but I think the AngularFire is a very useful util to Angular applications.

 You can check out the whole application repository on my GitHub. If you like it, please put a star on this repo. :)


State of Software Develoopment Report