Next, click on the Database on the sidebar at Firebase and then click on TRY FIRESTORE BETA. Then click ENABLE.

Enabling Firestore Firebase Database in Angular Authentication

Enabling Firestore Firebase Database

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

As at the time of this writing. There was a bug in the Firebase npm package, the following errors were displayed in the console. And according to this thread on Github, we need to downgrade Firebase to version 4.8.0 and upgrade AngularFire to version 5.0.0-rc.5. Remove the ^ at the beginning of the versions so as to download the exact version that we want. After changing it run yarn install to change the version.


"angularfire2": "5.0.0-rc.5-next",
"firebase": "4.8.0",

Take note that if you are using a version of Firebase and AngularFire that is higher, you might not need to make these changes. The versions causing the errors are Firebase version 4.8.1 and AngularFire 5.0.0-rc.4.

With these changes effected correctly, the errors should be gone. Now let’s go ahead and use AngularFire and Firebase in our project. First, we need to create a service file which will serve all the methods that we need to login and logout. Go to the Angular IDE and follow the direction as described in the screenshot below.

Angular Authentication With Firebase

Creating a New Service in Angular IDE

 

Angular Authentication With Firebase

Creating a New Service and giving it a name in Angular IDE

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),
     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);
  }
}

The first thing we need to do after creating a Service method is to add it to the providers array in the app.module.ts file, then after that we need to create routes for the components we created earlier and also create two more components, the EmailComponent and ProfileComponent. Use the same method we used to create components earlier to create those components. Your app.module.ts file should now look like this (The most significant changes are highlighted in bold):


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 { ProfileComponent } from './profile/profile.component';

import { AppRoutingModule } from './app-routing.module';
import { EmailComponent } from './email/email.component';

const firebaseConfig = {
  apiKey: 'AIzaSyAywNGLBVmlk98dkqahOj1hNMQ',
  authDomain: 'angularauth-502.firebaseapp.com',
  databaseURL: 'https://angularauth-502.firebaseio.com',
  projectId: 'angularauth-502',
  storageBucket: 'angularauth-502.appspot.com',
  messagingSenderId: '1124055'
};


@NgModule({
  declarations: [
    AppComponent,
    HomepageComponent,
    LoginComponent,
    SignupComponent,
    ProfileComponent,
    EmailComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireAuthModule
  ],
  providers: [ AuthService ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Next, we’ll create the AppRoutingModule where we will create our routes. Create a file app-routing.module.ts in the src/app folder, then fill it up 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 let’s go ahead and work in our LoginComponent file 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();
  }
}

And fill up the component file, login.component.html like so:

Angular Authentication with Firestore Login Form

Angular Authentication with Firestore Login Form

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 <code><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;
}

Now the login page looks like this:

Angular Firebase Authentication Email Login Form

Angular Firebase Authentication Email Login Form

Log in with Google Account now works, next, we will implement Logging in with Email and then after that, work on the Signup form. Navigate to the email/email.component.ts file:


import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-email',
  templateUrl: './email.component.html',
  styleUrls: ['./email.component.css']
})
export class EmailComponent implements OnInit {

  constructor(
    private authService: AuthService) { }

  ngOnInit() {}

  onSubmit(formData) {
    if (formData.valid) {
      console.log(formData.value);
      this.authService.login(
        formData.value.email,
        formData.value.password
      );
    }
  }
}

Next, let’s navigate to the email/email.component.html file and add the following (I’m adding the screenshot of the template because it’s been interpreted incorrectly):

Angular Authentication with Firestore Login Form

Angular Authentication with Firestore Email Login Form

The login form now looks like this:

Angular Firebase Authentication Email Login Form

Angular Firebase Authentication Email Login Form

Next, let’s work on the Signup form and its component:


import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-signup',
  templateUrl: './signup.component.html',
  styleUrls: ['./signup.component.css']
})
export class SignupComponent implements OnInit {

  constructor(public authService: AuthService) { }

  ngOnInit() {}

  onSubmit(formData) {
    if (formData.valid) {
      console.log(formData.value);
      this.authService.emailSignup(
        formData.value.email,
        formData.value.password
      );
    }
  }
}

And then the template:

Angular Firebase Authentication Email Signup Form

Angular Firebase Authentication Email Sign up Form

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();
  }
}
Angular Firebase Authentication Profile Page

Angular Firebase Authentication Profile Page

Conclusion

There’s still room for improvement, we can check the state of the current user and guard the profile page so that a stranger can’t go to User’s profile without Logging in. If you are reading this, you’ve probably navigated your way through this tutorial successfully.
In the second part of the tutorial, we will integrate animation into the forms (good for learning the basics of Angular Animations) and improve the already existing Authentication system. If you have any questions please do not hesitate to post a comment below or tweet me.

 

Chapter 2 of 2Next