How to Build a Firebase Angular App with Authentication and Real-Time Database

Are you looking to build a modern web application with secure user authentication and real-time data synchronization? Combining the power of Angular and Firebase provides an excellent stack for developing high-quality apps with minimal time and effort.

In this in-depth tutorial, I‘ll walk you through the process of building a Firebase Angular app from scratch. You‘ll learn how to set up authentication, read and write data to a real-time database, and deploy the app to production. Let‘s get started!

Why Angular and Firebase?

Angular is a robust JavaScript framework for building complex single-page apps. It provides a powerful CLI, well-defined best practices, and an extensive ecosystem of third-party libraries. Angular encourages writing clean, modular, and maintainable code.

Firebase is a backend platform that abstracts many low-level implementation details of authentication, database, storage, and hosting infrastructure. It allows developers to focus on building client-side experiences without worrying about provisioning and managing servers.

The tight integration between Angular and Firebase makes them a popular and productive stack for full-stack web development. You can build complete, real-time apps with only a few lines of code.

Setting Up a Firebase Project

To start, you‘ll need a Firebase account. Go to the Firebase Console and click "Add project". Give your project a name, accept the terms, and click "Create project".

Once your project is provisioned, click "Add Firebase to your web app". This will show you a code snippet that initializes the Firebase SDK in your app. We‘ll add this to our Angular app shortly.

Generating an Angular App

Next, make sure you have Node.js and the Angular CLI installed on your development machine. Open a terminal and run the following command to generate a new Angular app:

ng new my-app

Answer the prompts to set up routing and select a CSS format. Once the app is generated, navigate into the project directory:

cd my-app 

To connect the Angular app to your Firebase project, install the official Angular library for Firebase:

npm install @angular/fire firebase --save

Next, add the Firebase config to your Angular app. Open the src/environments/environment.ts file and add the following:

export const environment = {
  production: false,
  firebase: {
    apiKey: ‘your-api-key‘,
    authDomain: ‘your-auth-domain‘,
    databaseURL: ‘your-database-url‘,
    projectId: ‘your-project-id‘,
    storageBucket: ‘your-storage-bucket‘,
    messagingSenderId: ‘your-sender-id‘
  }
};

Replace the placeholders with the values from the Firebase "Add Firebase to your web app" code snippet.

Finally, import the Firebase modules in your app‘s root module. Open src/app/app.module.ts and add the following:

import { AngularFireModule } from ‘@angular/fire‘;
import { AngularFireAuthModule } from ‘@angular/fire/auth‘;
import { AngularFireDatabaseModule } from ‘@angular/fire/database‘;
import { environment } from ‘../environments/environment‘;

// ...

@NgModule({
  imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule,
    AngularFireDatabaseModule,
  ],
  // ...
})

Your Angular app is now set up to use Firebase authentication and real-time database!

Implementing User Authentication

Firebase supports several authentication methods out of the box, including email/password, Google sign-in, and Facebook login. We‘ll implement all three in our example app.

To get started, generate an authentication service to handle signing in and out:

ng generate service services/auth

Open the generated src/app/services/auth.service.ts file and replace its contents with:

import { Injectable } from ‘@angular/core‘;
import { AngularFireAuth } from ‘@angular/fire/auth‘;
import { auth } from ‘firebase/app‘;

@Injectable({
  providedIn: ‘root‘
})
export class AuthService {

  constructor(public afAuth: AngularFireAuth) {}

  login(email: string, password: string) {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password);
  }

  loginWithGoogle() {
    return this.afAuth.auth.signInWithPopup(new auth.GoogleAuthProvider());
  }

  loginWithFacebook() {
    return this.afAuth.auth.signInWithPopup(new auth.FacebookAuthProvider());
  }

  logout() {
    return this.afAuth.auth.signOut();
  }

}

The AuthService class uses the injected AngularFireAuth instance to access the underlying Firebase authentication methods. We define separate methods for email/password, Google, and Facebook sign-in.

Next, we can create a login component for our app. Generate one with the Angular CLI:

ng generate component login

Open the src/app/login/login.component.ts file and implement a basic login form:

import { Component } from ‘@angular/core‘;
import { AuthService } from ‘../services/auth.service‘;

@Component({
  selector: ‘app-login‘,
  template: `
    <h2>Login</h2>

    <button (click)="authService.loginWithGoogle()">
      Login with Google
    </button>

    <button (click)="authService.loginWithFacebook()">
      Login with Facebook
    </button>

    <form (submit)="login(email.value, password.value)">
      <label for="email">Email</label>
      <input type="email" #email required>

      <label for="password">Password</label>  
      <input type="password" #password required>

      <button type="submit">Login</button>
    </form>
  `,
})
export class LoginComponent {

  constructor(public authService: AuthService) {}

  login(email: string, password: string) {
    this.authService.login(email, password)
      .catch(error => console.log(error));    
  }

}

We create buttons to sign in with Google and Facebook by calling the respective AuthService methods. For email/password sign-in, we bind the form inputs to a login() method that passes the values to the AuthService login method.

Finally, update your app.component.html to show the login form:



<app-login></app-login>

You should now be able to sign into your app with email/password, Google, or Facebook! The Firebase Authentication dashboard will show the registered user accounts.

Using the Real-Time Database

Firebase‘s Realtime Database is a NoSQL cloud database that stores data as JSON and synchronizes changes to all connected clients in real-time. It‘s a great fit for chat apps, collaborative apps, and anything requiring real-time updates.

To use the database in our Angular app, we need to first define its security rules. By default, Firebase databases are secured and not accessible by any client. We need to explicitly grant read and write access.

Go to the "Database" section in your Firebase Console and click the "Rules" tab. Replace the default rules with the following:

{
  "rules": {
    "items": {
      ".read": "auth != null",
      ".write": "auth != null"    
    }
  }
}

This allows any authenticated user to read and write to the "items" path in our database. You can customize these rules to be more granular.

Next, we‘ll create an Angular service to interact with this database. Generate a new service:

ng generate service services/item

Open the generated src/app/services/item.service.ts file and add the following code:

import { Injectable } from ‘@angular/core‘;
import { AngularFireDatabase } from ‘@angular/fire/database‘;
import { map } from ‘rxjs/operators‘;

@Injectable({
  providedIn: ‘root‘
})
export class ItemService {

  private itemsRef = this.db.list<Item>(‘items‘);

  constructor(private db: AngularFireDatabase) { }

  getAll() {
    return this.itemsRef.snapshotChanges().pipe(
      map(changes => 
        changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
      )
    );
  }

  create(item: Item) {
    return this.itemsRef.push(item);
  }

  update(key: string, value: any) {
    return this.itemsRef.update(key, value);
  }

  delete(key: string) {
    return this.itemsRef.remove(key);
  }

}

export interface Item {
  name: string;
}

This service provides methods to read the full list of items, add new items, update existing items, and delete items. We use the AngularFireDatabase service to access a DUListed reference at the "items" path. The snapshotChanges() method returns an Observable that we can map to an array of items.

Now we‘re ready to display the list of items in our app! Generate a new "items" component:

ng generate component items

Implement the component class to retrieve items from the database and render them:

import { Component } from ‘@angular/core‘;
import { ItemService } from ‘../services/item.service‘;
import { map } from ‘rxjs/operators‘;

@Component({
  selector: ‘app-items‘,
  template: `
    <h2>Items</h2>

    <ul>
      <li *ngFor="let item of items$ | async">
        {{item.name}}

        <button (click)="delete(item.key)">Delete</button>
      </li>
    </ul>

    <input type="text" #itemName>
    <button (click)="add(itemName.value)">Add</button>
  `
})
export class ItemsComponent {

  items$;

  constructor(private itemService: ItemService) { 
    this.items$ = this.itemService.getAll();
  }

  add(itemName: string) {
    this.itemService.create({ name: itemName });
  }

  delete(key: string) {
    this.itemService.delete(key);
  }

}

We subscribe to the Observable returned by the ItemService to get the array of items. An *ngFor directive renders each item, and buttons are hooked up to the service methods to add and delete items.

Finally, add the items component to your app.component.html:



<app-login></app-login>

<app-items></app-items>

Now you should see the real-time list of items! Try adding and deleting a few items and notice how the UI updates instantly. You can also view the data in the Firebase database console.

Deploying to Firebase Hosting

Once your app is ready, you can easily deploy it to Firebase Hosting for free. First, build your Angular app for production:

ng build --prod

Then, install the Firebase CLI:

npm install -g firebase-tools

Log into your Firebase account and initialize the project:

firebase login
firebase init

Select the "Hosting" option, choose your project, and set the public directory to dist/my-app. This is where the production Angular build is output.

Finally, deploy your app!

firebase deploy

After a minute, you should see a "Hosting URL" where your app is live. It will look something like https://your-app.firebaseapp.com.

Congrats, you‘ve now built and deployed a full-stack Angular app with authentication and real-time database using Firebase!

Best Practices and Next Steps

While this tutorial covered the basics, there are additional steps you can take to make your Firebase Angular app production-ready:

  • Configure custom domain on Firebase Hosting
  • Enforce stricter database security rules
  • Implement server-side data validation
  • Make use of Firebase Storage for user-generated content
  • Add a page to manage user account and profile
  • Integrate FCM for push notifications
  • Follow the official @angular/fire setup guide
  • Subscribe to a paid Firebase plan as your app scales

I also recommend studying the example apps and documentation to learn about more advanced use cases and best practices. The Firebase documentation is extensive and includes guides for most common scenarios.

To continue your learning, try adding new features to the example app like queries, filtering, and pagination! With the real-time database, you can build some really cool and responsive apps. Have fun, and let me know what you come up with!

Similar Posts