Complete Step-by-Step Firebase Authentication in Angular 2

Published Aug 26, 2017
Complete Step-by-Step Firebase Authentication in Angular 2

Firebase Authentication provides back-end services, easy-to-use software development kits (SDK), and ready-made UI libraries to authenticate users to your app. It supports authentication by using passwords, phone numbers, popular federated identity providers (e.g. Google, Facebook, Twitter, GitHub), and more.

Throughout this post, I’ll refer to Angular 2 as simply Angular. Note that Angular 1 is referred to as AngularJS.

In this tutorial, I’ll take you through how to easily handle authentication in your Angular application by using the following sign-in methods:

  • Twitter
  • Facebook
  • Regular Email/Password
  • GitHub
  • Gmail

Let's Get Started

Generally speaking (oh sorry, coding), you can follow these steps to create your new Angular app. We’ll be using Angular CLI. Alternatively, you can skip this step and clone the starter version of the app in my GitHub repository.

$ ng new angular2-authentication-firebase
$ cd angular2-authentication-firebase
$ ng serve
$ npm install --save font-awesome angular2-fontawesome

In the above code, we've created a new Angular app using Angular CLI. We moved into the directory and served the application using the ng serve command. We also pulled in the Font Awesome library so we can take advantage of its icons.

If your browser doesn't automatically open, visit http://localhost:4200.

Include Bootstrap and Font Awesome in your app by adding the following lines to your src/styles.css file:

@import "~bootstrap/dist/css/bootstrap.min.css";
@import "~font-awesome/css/font-awesome.css";

Clone the Starter Repository

I've created a starter Angular 2 application already — clone it here. These are all pre-installed:

  • A login component and a dashboard component with their HTML and CSS written.
  • Bootstrap’s HTML and CSS.`
  • Font Awesome — for the social icons

The final version can be found here.

Now, run the command:

npm install

It will look like this:
Screen Shot 2017-08-13 at 2.20.40 AM.png
Screen Shot 2017-08-13 at 2.20.24 AM.png

Let's Add Authentication

Create a Firebase app. Visit firebase.google.com and click Sign In. Then click Go to Console.

Click Add A Project and you’ll see the image below. Fill it out like so:

Screen Shot 2017-08-13 at 2.46.31 AM.png

Once you're in your dashboard, click Add Firebase to your web app and copy the configuration settings as highlighted in the image below:

Screen Shot 2017-08-13 at 3.10.22 AM.png

Screen Shot 2017-08-13 at 3.12.25 AM.png

Run the command below in your terminal to pull in angularfire2 for your authentication:

$ npm install angularfire2 firebase --save

Go to src/environments/environments.ts and paste the configuration like this:

// src/environments/environments.ts
export const environment = {
   production: false,
   firebase: {
      apiKey: "<Your_API_KEY_HERE>",
      authDomain: "AUTH-DOMAIN-HERE",
      databaseURL: "DATABASE-URL-HERE",
      projectId: "PROJECT-ID-HERE",
      storageBucket: "STORAGE-BUCKET-HERE",
      messagingSenderId: "MESSAGING-SENDER-ID-HERE"
   };
};

Go to app.module.ts and import the AngularFireModule, AngularFireDatabaseModule, and AngularFireAuth modules. Also, import the environment configuration. Add these to 'imports' under 'NgModule Decorator' like so:

// src/app/app.modules.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutes } from "./app.routes";
import { AppComponent } from './app.component';
import { LoginComponent } from './views/login/login.component';
import { DashboardComponent } from './views/dashboard/dashboard.component';

**import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';**

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    AppRoutes,
   ** AngularFireModule.initializeApp(environment.firebase, 'angular-auth-firebase'),
    AngularFireDatabaseModule,
    AngularFireAuthModule**
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Let's create an auth service to implement the authentication. We'll create services so that it can be accessible and used by all of our components whenever and wherever they're located. We can do this using Angular CLI:

$ ng generate service services/auth

This creates auth.service.ts inside the src/app/services folder. Import it in your modules. Then we'll add it to providers in our app.module.ts.

// src/app/services/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutes } from "./app.routes";
import { AppComponent } from './app.component';
import { LoginComponent } from './views/login/login.component';
import { DashboardComponent } from './views/dashboard/dashboard.component';

import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';

**import { AuthService } from './services/auth.service';**

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    AppRoutes,
    AngularFireModule.initializeApp(environment.firebase, 'angular-auth-firebase'),
    AngularFireDatabaseModule,
    AngularFireAuthModule
  ],
  providers: [**AuthService**],
  bootstrap: [AppComponent]
})
export class AppModule { }

In the auth.service.ts file, import AngularFireAuth, Firebase, and Observable. Create an Observable user variable, inject Firebase Auth in the constructor, and create sign in methods. Your auth.service.ts becomes:

// src/app/services/auth.service.ts
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';
@Injectable()
export class AuthService {
  private user: Observable<firebase.User>;
constructor(private _firebaseAuth: AngularFireAuth, private router: Router) { 
      this.user = _firebaseAuth.authState;
  }
}

Sign In With Twitter

Go to the Firebase Console. Click Authentication menu item on the right. Click Sign-In Method and choose Twitter. Enable it.

Go to dev.twitter.com/apps and create an app. Fill in the information, including a valid URL where your application will be hosted.
Click on the Keys and Access Token tab. Copy the Consumer Key (API Key) and Consumer Secret (API Secret), then paste them in your Firebase console. Click save.

Screen Shot 2017-08-13 at 3.58.39 AM.png

When you hit Save, it generates a link for you. Copy the link from your Firebase console. Go to the Settings tab on your Twitter Developer dashboard and paste the link in the Callback URL Field. This is very important. See images below.

Screen Shot 2017-08-13 at 5.10.21 AM.png

Screen Shot 2017-08-13 at 5.11.41 AM.png

Add the signInWithTwitter() function in your auth service, like so:

// ...auth.service.ts
...    
    signInWithTwitter() {
      return this._firebaseAuth.auth.signInWithPopup(
        new firebase.auth.TwitterAuthProvider()
      )
    }
...

In your app/views/login.ts, import the AuthService, inject it in the constructor, and implement Twitter login.

// src/app/views/login/login.component.ts
import { Injectable } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthService {
  private user: Observable<firebase.User>;
constructor(private _firebaseAuth: AngularFireAuth) { 
      this.user = _firebaseAuth.authState;
  }
signInWithTwitter() {
      return this._firebaseAuth.auth.signInWithPopup(
        new firebase.auth.TwitterAuthProvider()
      )
    }
}

Add the click function in your login HTML file. Open the login.component.html and add the click function. See snippet below:

<button type="button" class="btn btn-block" **(click)="signInWithTwitter()**">
   <i class="fa fa-twitter" aria-hidden="true"></i>
      Login with Twitter
</button>

Go to your app on the web and click the Login with Twitter button. It will ask you to authorize the app or log in with your Twitter credentials, then it'll take you to the dashboard page.

Screen Shot 2017-08-13 at 5.14.42 AM.png

Screen Shot 2017-08-13 at 5.15.35 AM.png

Sign In With Facebook

For authentication using Facebook, visit developer.facebook.com and log in with your Facebook credentials. Create/Add a new app. Type in the Display Name and Create App ID.

Screen Shot 2017-08-13 at 5.22.08 AM.png

Click Settings on the side menu. Copy the app ID, click to show the app secret, and copy that as well. Go to your Firebase console, and under sign-in methods, enable Facebook then paste the app ID and app secret.

Now, let's add the signInWithFacebook() function to our login component and login HTML.

// login.component.ts
...
   signInWithFacebook() {
      this.authService.signInWithFacebook()
      .then((res) => { 
          this.router.navigate(['dashboard'])
        })
      .catch((err) => console.log(err));
    }
...

In our login HTML file, let's add all the logins once and for all. Our HTML becomes:

// login.component.html
...
<div class="form-group">
    <button type="buton" class="btn btn-block" (click)="signInWithFacebook()">
      <i class="fa fa-facebook" aria-hidden="true"></i> 
      Login with Facebook
    </button>
<button type="button" class="btn btn-block" (click)="signInWithTwitter()">
      <i class="fa fa-twitter" aria-hidden="true"></i>
      Login with Twitter
    </button>
<button type="button" class="btn btn-block" (click)="signInWithGithub()">
      <i class="fa fa-github" aria-hidden="true"></i>
      Login with Github
    </button>
<button type="button" class="btn btn-block" (click)="signInWithGoogle()">
      <i class="fa fa-google" aria-hidden="true"></i>
      Login with Google
    </button>
</div>                  
...

Sign In With Google

For Google account sign-in, enable Google authentication in your Firebase console and click Save.

// src/app/services/auth.service.ts
...
signInWithGoogle() {
    return this._firebaseAuth.auth.signInWithPopup(
      new firebase.auth.GoogleAuthProvider()
    )
  }
...

It's important to add the following functions: isLoggedIn() and Logout(). isLoggedIn() will return a Boolean type if the user is logged in. This will ensure that certain pages and displays are only available to authorized users.

logout() function, when called, logs the current user out. It is also essential to protect the application once the user is finished using it.

A complete auth.service file looks like this:

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';

@Injectable()
export class AuthService {

  private user: Observable<firebase.User>;
  private userDetails: firebase.User = null;
  
constructor(private _firebaseAuth: AngularFireAuth, private router: Router) { 
      this.user = _firebaseAuth.authState;
this.user.subscribe(
        (user) => {
          if (user) {
            this.userDetails = user;
            console.log(this.userDetails);
          }
          else {
            this.userDetails = null;
          }
        }
      );
  }
  
signInWithTwitter() {
    return this._firebaseAuth.auth.signInWithPopup(
      new firebase.auth.TwitterAuthProvider()
    )
  }
  
signInWithFacebook() {
    return this._firebaseAuth.auth.signInWithPopup(
      new firebase.auth.FacebookAuthProvider()
    )
  }
  
signInWithGoogle() {
    return this._firebaseAuth.auth.signInWithPopup(
      new firebase.auth.GoogleAuthProvider()
    )
  }
  
isLoggedIn() {
  if (this.userDetails == null ) {
      return false;
    } else {
      return true;
    }
  }
  
**logout() {
    this._firebaseAuth.auth.signOut()
    .then((res) => this.router.navigate(['/']));
  }
}

logout() {
    this._firebaseAuth.auth.signOut()
    .then((res) => this.router.navigate(['/']));
  }
}**

Thank you for taking the time to read this post — hopefully it's been helpful to you. I'll be publishing Part Two, which will entail:

  • GitHub authentication
  • Regular signup/signin
  • Safeguarding the dashboard page

Thanks! Kindly share, like, and comment. Also, you can follow me on Twitter @ hellotunmbi!


This post is originally published by the author here. This version has been edited for clarity and may appear different from the original post.

Discover and read more posts from Tunmbi Banto
get started