Firebase Authentication In Angular using AngularFire


In this tutorial, we are going Learn how to handle Firebase Authentication In Angular using Google’s Cloud Firestore and Angularfire.

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 Firebase Firestore.

Firestore is a flexible, scalable database for mobile, web, and server development.

What you will learn

In this article, you will learn to develop a fully functioning authentication system in Angular using Firestore.

We will be using the official tool for Angular and Firebase integration – AngularFire.

AngularFire allows you to work with Cloud Firestore, the new flagship database for mobile app development.

It improves on the successes of Real-time Database with a new, more intuitive data model. Cloud Firestore also features richer, faster queries and scales better than Realtime Database.

PREREQUISITES

In order to follow along with this tutorial please 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 which we will work with, in this tutorial.

Create a new Angular project using the Angular CLI

Incase you don’t have the angular CLI globally installed in your development machine, open up your terminal and type:


npm install -g @angular/cli

Open your terminal on your desktop and type this command to create a new Angular project:

ng new Angularauth

This will ideally take some time, depending on how fast your internet is, so be patient.

Creating a Firebase project

Once the project is created, the next thing to do is 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, I’ll call mine AngularAuth, then click on Create Project afterward.

Now after the project has been created, you will be redirected to the project’s overview page, there you are meant to choose the option – Add Firebase to your web app. 

On clicking that, you will get a pop up with all the info such as the API key that you need to be able to interact with your newly created Firebase app from the Angular application That’s it for now with Firebase, let’s go back to the Angular Project to create some components.

Creating Necessary components

We need a Homepage, Login page, and Sign Up page to showcase how our Authentication is working. So we need to create an Angular component for each of these pages.

ng g c Homepage
ng g c Loginpage
ng g c SignUppage

Now let us run our app to confirm everything is working.

ng serve

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. When you hit save and check your browser now, the page should be blank.

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.

<app-homepage> </app-homepage>

The app-homepage is the selector for the homepage component we created earlier.

Now we will install AngularFire in our project:

ng add @angular/fire

Working with Firebase Authentication In Angular

Now, with the installed npm packages we need to configure our Firebase application to enable it to be able to communicate with your Angular application.

Click on the Authentication link and choose sign in method on the top tab after adding the firebaseConfig to app.module.ts file.

Firebase Authentication In Angular

First, we will import the AngularFire modules to the app.module.ts file. My app.module.ts file looks like this after the new config is added.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
 
import { AngularFirestore } from '@angular/fire/firestore';

import { AngularFireAuthModule } from "@angular/fire/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. Here, click on the project name and then on the project dashboard, click on Add firebase to your web app. Replace the values below with yours, values below will not work for you because I have removed some characters from it.
const firebaseConfig = {
apiKey: 'your_keyhere_jwaeqsFdm1hNMQ',
authDomain: 'yourdomain.firebaseapp.com',
databaseURL: 'https://angularauth-yourlinkhere.firebaseio.com',
projectId: 'angularauth-yourIDHere',
storageBucket: 'angularauth-Idhere.appspot.com',
messagingSenderId: '11240551_IDhere'
};
 
@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 described 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. Then click ENABLE.

Firebase Authentication In Angular

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 which will serve all the methods that we need to login and logout.

ng generate service auth

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 { AngularFirestore } from '@angular/fire/firestore';
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.

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:

<div class="form-container">
  <button (click)="loginGoogle()" class="google">Login or Signup 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:

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

Firebase Authentication In Angular

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:

<div class="form-container">
  <h2>Login</h2>
  <form #formData='ngForm' (ngSubmit)='onSubmit(formData)'>
    <input type="text" placeholder="Email address" (ngModel)="email" name="email" class="input-txt" required>
    <input type="password" placeholder="Password" (ngModel)="password" name="password" class="input-txt" required>
    <button type="submit" [disabled]="!formData.valid" class="auth-btn">Log in</button>
  </form>
  <a routerLink="/signup" routerLinkActive="active" class="create-account-txt">No account? <strong>Create one here</strong></a>
</div>

The login form now looks like this:

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:

<div class="form-container">
  <a routerLink="/login" id="goback">Login</a>
  <h2>Sign Up</h2>
  <form #formData='ngForm' (ngSubmit)="onSubmit(formData)">
    <input type="text" placeholder="Email address" (ngModel)="email" name="email" class="input-txt" required>
    <input type="password" placeholder="Password" (ngModel)="password" name="password" class="input-txt" required>
    <button type="submit" [disabled]="!formData.valid" class="auth-btn">Create Account</button>
  </form>
</div>

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>

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 the User’s profile without Logging in. If you are reading this, you’ve probably navigated your way through this tutorial successfully. I hope you learned a few things about handling Firebase Authentication In Angular. Every article can be made better, so please leave your suggestions and contributions in the comments below. If you have questions about any of the steps, please do also ask in the comments section below.


Share on social media

//