Angular and Firebase Authentication: A Complete Guide

This tutorial will guide you through the process of setting up and implementing Firebase Authentication in an Angular project. Firebase Authentication provides a secure and easy way to manage user authentication in your application, including features such as email/password authentication, social media authentication, and user roles. By the end of this tutorial, you will have a fully functional authentication system in your Angular application using Firebase.

angular firebase authentication guide

Introduction

What is Angular?

Angular is a popular JavaScript framework for building web applications. It allows developers to build dynamic and interactive web pages using a component-based architecture. Angular provides a wide range of features and tools that make it easy to develop scalable and maintainable applications.

What is Firebase Authentication?

Firebase Authentication is a service provided by Google Firebase that allows developers to easily add authentication functionality to their applications. It provides a secure way to authenticate users using email/password, social media logins, and more. Firebase Authentication also handles user management tasks such as user registration, password reset, and email verification.

Setting up Angular Project

Before we can start implementing Firebase Authentication in our Angular project, we need to set up the project itself. This involves installing the Angular CLI and creating a new Angular project. We will also need to add Firebase to our project.

Installing Angular CLI

To install the Angular CLI, open your terminal or command prompt and run the following command:

npm install -g @angular/cli

Creating a new Angular project

Once the Angular CLI is installed, we can create a new Angular project by running the following command:

ng new my-project

This will create a new directory called "my-project" with the basic structure of an Angular project.

Adding Firebase to the project

To add Firebase to our Angular project, we need to install the Firebase SDK. Run the following command in your terminal or command prompt:

npm install firebase

Now that we have our Angular project set up and Firebase installed, we can move on to implementing Firebase Authentication.

Firebase Authentication

In this section, we will configure Firebase Authentication in our Angular project and implement the necessary functionality for user sign up, sign in, sign out, and handling user authentication state.

Configuring Firebase Authentication

To configure Firebase Authentication, we need to create a new Firebase project and enable the Authentication service.

  1. Visit the Firebase Console and create a new project.
  2. Once the project is created, navigate to the "Authentication" section in the Firebase Console.
  3. Click on the "Sign-in method" tab and enable the desired authentication providers (e.g., email/password, Google, Facebook, etc.).

Implementing Sign Up functionality

To allow users to sign up for our application, we need to create a sign-up form and handle the form submission in our Angular project.

  1. In your Angular project, create a new component called "SignUp" using the Angular CLI:
ng generate component SignUp
  1. Open the "sign-up.component.html" file and add the following form:
<form (ngSubmit)="onSubmit()">
  <input type="email" [(ngModel)]="email" name="email" placeholder="Email" required>
  <input type="password" [(ngModel)]="password" name="password" placeholder="Password" required>
  <button type="submit">Sign Up</button>
</form>
  1. In the "sign-up.component.ts" file, add the following code:
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';

@Component({
  selector: 'app-sign-up',
  templateUrl: './sign-up.component.html',
  styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent {
  email: string;
  password: string;

  constructor(private afAuth: AngularFireAuth) {}

  onSubmit() {
    this.afAuth.createUserWithEmailAndPassword(this.email, this.password)
      .then((userCredential) => {
        // Handle successful sign up
      })
      .catch((error) => {
        // Handle error
      });
  }
}

In this code, we import the AngularFireAuth module from @angular/fire/auth and inject it into our component. In the onSubmit() method, we use the createUserWithEmailAndPassword() method to create a new user with the provided email and password.

Implementing Sign In functionality

To allow users to sign in to our application, we need to create a sign-in form and handle the form submission in our Angular project.

  1. In your Angular project, create a new component called "SignIn" using the Angular CLI:
ng generate component SignIn
  1. Open the "sign-in.component.html" file and add the following form:
<form (ngSubmit)="onSubmit()">
  <input type="email" [(ngModel)]="email" name="email" placeholder="Email" required>
  <input type="password" [(ngModel)]="password" name="password" placeholder="Password" required>
  <button type="submit">Sign In</button>
</form>
  1. In the "sign-in.component.ts" file, add the following code:
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';

@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.component.html',
  styleUrls: ['./sign-in.component.css']
})
export class SignInComponent {
  email: string;
  password: string;

  constructor(private afAuth: AngularFireAuth) {}

  onSubmit() {
    this.afAuth.signInWithEmailAndPassword(this.email, this.password)
      .then((userCredential) => {
        // Handle successful sign in
      })
      .catch((error) => {
        // Handle error
      });
  }
}

In this code, we import the AngularFireAuth module from @angular/fire/auth and inject it into our component. In the onSubmit() method, we use the signInWithEmailAndPassword() method to sign in the user with the provided email and password.

Implementing Sign Out functionality

To allow users to sign out of our application, we need to create a sign-out button and handle the sign-out action in our Angular project.

  1. In your Angular project, open the "app.component.html" file and add the following button:
<button (click)="signOut()">Sign Out</button>
  1. In the "app.component.ts" file, add the following code:
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private afAuth: AngularFireAuth) {}

  signOut() {
    this.afAuth.signOut()
      .then(() => {
        // Handle successful sign out
      })
      .catch((error) => {
        // Handle error
      });
  }
}

In this code, we import the AngularFireAuth module from @angular/fire/auth and inject it into our component. In the signOut() method, we use the signOut() method to sign out the currently authenticated user.

Handling User Authentication State

To handle the user authentication state in our Angular project, we can use the authState observable provided by Firebase Authentication.

  1. In your Angular project, open the "app.component.ts" file and add the following code:
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  user: Observable<firebase.User>;

  constructor(private afAuth: AngularFireAuth) {
    this.user = afAuth.authState;
  }
}

In this code, we import the AngularFireAuth module from @angular/fire/auth and inject it into our component. We also import the Observable class from rxjs to handle the asynchronous nature of the authState observable. In the constructor, we assign the authState observable to the user property.

Additional Authentication Features

In addition to the basic sign up, sign in, and sign out functionality, Firebase Authentication provides additional features such as resetting passwords, email verification, social media authentication, securing Angular routes, and handling user roles.

Resetting Password

To allow users to reset their passwords, we can use the sendPasswordResetEmail() method provided by Firebase Authentication.

  1. In your Angular project, create a new component called "ResetPassword" using the Angular CLI:
ng generate component ResetPassword
  1. Open the "reset-password.component.html" file and add the following form:
<form (ngSubmit)="onSubmit()">
  <input type="email" [(ngModel)]="email" name="email" placeholder="Email" required>
  <button type="submit">Reset Password</button>
</form>
  1. In the "reset-password.component.ts" file, add the following code:
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';

@Component({
  selector: 'app-reset-password',
  templateUrl: './reset-password.component.html',
  styleUrls: ['./reset-password.component.css']
})
export class ResetPasswordComponent {
  email: string;

  constructor(private afAuth: AngularFireAuth) {}

  onSubmit() {
    this.afAuth.sendPasswordResetEmail(this.email)
      .then(() => {
        // Handle successful password reset email
      })
      .catch((error) => {
        // Handle error
      });
  }
}

In this code, we import the AngularFireAuth module from @angular/fire/auth and inject it into our component. In the onSubmit() method, we use the sendPasswordResetEmail() method to send a password reset email to the user with the provided email.

Email Verification

To verify user email addresses, we can use the sendEmailVerification() method provided by Firebase Authentication.

  1. In your Angular project, open the "sign-up.component.ts" file and add the following code to the onSubmit() method:
onSubmit() {
  this.afAuth.createUserWithEmailAndPassword(this.email, this.password)
    .then((userCredential) => {
      userCredential.user.sendEmailVerification();
      // Handle successful sign up
    })
    .catch((error) => {
      // Handle error
    });
}

In this code, we call the sendEmailVerification() method on the user object returned by the createUserWithEmailAndPassword() method to send a verification email to the user.

Social Media Authentication

Firebase Authentication supports social media logins such as Google, Facebook, Twitter, and more. To implement social media authentication in our Angular project, we need to enable the desired authentication providers in the Firebase Console and use the corresponding methods provided by Firebase Authentication.

  1. In your Angular project, open the "sign-in.component.ts" file and add the following code to the onSubmit() method:
onSubmit() {
  this.afAuth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
    .then((userCredential) => {
      // Handle successful sign in
    })
    .catch((error) => {
      // Handle error
    });
}

In this code, we use the signInWithPopup() method with the GoogleAuthProvider to sign in the user using their Google account. You can replace GoogleAuthProvider with the desired provider (e.g., FacebookAuthProvider, TwitterAuthProvider, etc.).

Securing Angular Routes

To secure certain routes in our Angular application and restrict access to authenticated users, we can use route guards provided by Angular.

Implementing Route Guards

  1. In your Angular project, create a new service called "AuthGuard" using the Angular CLI:
ng generate service AuthGuard
  1. Open the "auth-guard.service.ts" file and add the following code:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AngularFireAuth } from '@angular/fire/auth';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(private afAuth: AngularFireAuth, private router: Router) {}

  canActivate(): Observable<boolean> {
    return this.afAuth.authState.pipe(
      map((user) => {
        if (user) {
          return true;
        } else {
          this.router.navigate(['/sign-in']);
          return false;
        }
      })
    );
  }
}

In this code, we import the CanActivate interface and the Router module from @angular/router, the AngularFireAuth module from @angular/fire/auth, and the Observable and map operators from rxjs. We then implement the CanActivate interface and define the canActivate() method. In this method, we use the authState observable to check if the user is authenticated. If the user is authenticated, we return true to allow access to the route. If the user is not authenticated, we navigate the user to the sign-in page and return false.

Restricting Access to Authenticated Users

To restrict access to certain routes in our Angular application to only authenticated users, we can use the canActivate property in the route configuration.

  1. In your Angular project, open the "app-routing.module.ts" file and add the following code:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './auth-guard.service';

const routes: Routes = [
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
  { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
  // ...
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

In this code, we import the Routes and RouterModule modules from @angular/router and the AuthGuard service we created earlier. We define our routes and use the canActivate property to specify that the route can only be accessed by authenticated users.

Handling User Roles

To handle user roles in our Angular application, we can create user roles and restrict access to certain routes based on those roles.

Creating User Roles

  1. In your Angular project, create a new service called "RoleService" using the Angular CLI:
ng generate service RoleService
  1. Open the "role.service.ts" file and add the following code:
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class RoleService {
  private roles: string[] = [];

  constructor() {}

  getRoles(): string[] {
    return this.roles;
  }

  setRoles(roles: string[]): void {
    this.roles = roles;
  }

  hasRole(role: string): boolean {
    return this.roles.includes(role);
  }
}

In this code, we create a RoleService with methods to get the user roles, set the user roles, and check if the user has a specific role.

Restricting Access based on User Roles

To restrict access to certain routes based on user roles, we can modify the canActivate method in our AuthGuard service.

  1. In your Angular project, open the "auth-guard.service.ts" file and modify the canActivate() method as follows:
canActivate(): Observable<boolean> {
  return this.afAuth.authState.pipe(
    map((user) => {
      if (user) {
        const roles = this.roleService.getRoles();
        if (roles.includes('admin')) {
          return true;
        } else {
          this.router.navigate(['/access-denied']);
          return false;
        }
      } else {
        this.router.navigate(['/sign-in']);
        return false;
      }
    })
  );
}

In this code, we import the RoleService and inject it into our AuthGuard service. We then check if the user has the "admin" role before allowing access to the route. If the user does not have the "admin" role, they will be redirected to the "access-denied" page.

Conclusion

In this tutorial, we have learned how to set up and implement Firebase Authentication in an Angular project. We have covered the basics of Firebase Authentication, including sign up, sign in, and sign out functionality, as well as additional features such as resetting passwords, email verification, social media authentication, securing routes, and handling user roles. By following the steps in this tutorial, you should now have a solid foundation for implementing user authentication in your Angular applications using Firebase Authentication.