facebook
Bob at Genuitec
Virtual evangelist at large. The face of Genuitec often appearing in graphics. Pen-name for our more shy writers of content.
Posted on Feb 6th 2018

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.

angular-5-authentication-set-up-project-ss-1

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.

angular-5-authentication-set-up-components-ss-3

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.

angular-5-authentication-name-component-ss-4

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

Now, let’s go ahead and remove the default content that came with the new application. Navigate to `src/app/app.component.html` to see the code. Select all content of this file and delete it. The `app.component.html` file now becomes the new base/host for our homepage. Go ahead and add the selector of the homepage component there. To do that, type the following code:

`<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`

angular-5-authentication-ng-g-c-login-ss-8

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.

angular-5-authentication-configure-firebase-app-ss-9

Back in the Firebase Console, click `Add Firebase to your web app` to get a popup similar to the image below. Copy the config object from this popup, we’ll be using it in our Angular application.

angular-5-authentication-add-firebase-popup-ss-10

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.

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`.

angular-5-authentication-enable-firestore-beta-ss-11

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

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}
Now let’s go ahead and use AngularFire and Firebase in our project. First, we need to create a service file that will serve all the methods that we need to log in and log out. Go to the Angular IDE and follow the directions, as shown in the screenshots below.

angular-5-authentication-set-up-service-ss-12

angular-5-authentication-name-service-ss-13

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

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:

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):

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()`.

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:

<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:

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.

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();
  }
}
<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:

Angular 5 Authorization Application

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.