Save User Data in Local Storage in Angular 16 Firebase

Last Updated on by in Angular

Today we are going to create a simple app in which we are going to save user data in local storage using Angular and Firebase real-time database.

I will be showing you how you can maintain the user state even after you refresh the page in the Angular and Firebase.

I am going to use a simple logic when a user logs in the app we will save the user data in local storage.

When a user logs out from the Angular application we remove the user data from local storage and set it to null.

Advantages of saving user’s data as an object in localStorage

  • Local Storage provides full control to users to access their data.
  • A user’s data can be retrieved quickly and easily.
  • It works even after you lose the internet connection, you can still access the data.

Let’s start coding our small app.

1. Prerequisite

– Setup Node JS development environment

Before we move further I assume you’ve already set up Node JS development environment in your system.

Please follow this article on Set up Node JS Development Environment

– Install Angular CLI

Install Angular CLI, Ignore if already installed.

npm install -g @angular/cli

– Angular Project Set up

Set up the latest Angular project.

ng new angularfiebase-authentication

Once the project is installed, get into the project folder.

cd angularfirebase-authentication

Congrats! You are in your project directory.

In order to remove strict type warnings or error make sure to set “strict”: false under compilerOptions property in tsconfig.json file.

Install Bootstrap 5 for demo purpose from NPM community.

npm install bootstrap

Go to angular.json file and replace the given below code with “styles”: [ ] array.

"styles": [
            "node_modules/bootstrap/dist/css/bootstrap.min.css",
            "src/styles.scss"
          ]

Type given command to generate components:

ng g c components/sign-in

ng g c components/dashboard

2. AngularFire2 Library Integration

I assume you already know how to create a basic Firebase account and setup a project in it, if not then follow this article How to setup a basic Firebase account and set up a Firebase Project?

How to include Firebase AngularFire2 library in your Angular app?

Add AngularFire2 library in your Angular app using Angular CLI.

npm install @angular/fire firebase@9.16.0 --legacy-peer-deps

First, create src/environments/ folder and environment.ts file, then add firebase configurations in environments/environment.ts file.

export const environment = {
  production: false,
  firebase: {
    apiKey: "xxxxxxxx-xxxxxxxx",
    authDomain: "xxxxxxxxxxxxxxxxxxxxxxxx",
    projectId: "xxxxxxxx",
    storageBucket: "xxxxxxxx",
    messagingSenderId: "xxxxxx",
    appId: "xxxxx",
  }
};

Once the AngularFire2 library included in the app then go to src/app/app.module.ts file and add the given below code.

// Firebase services + enviorment module
import { AngularFireModule } from "@angular/fire";
import { AngularFireAuthModule } from "@angular/fire/auth";
import { environment } from '../environments/environment';


@NgModule({
 declarations: [...],
  imports: [
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule
  ],
  providers: [...],
  bootstrap: [...]
})

4. Implement Router Service

Now, head over to the app/app-routing.module.ts file, here you have to update the code into the file.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';

const routes: Routes = [
  { path: '', redirectTo: '/sign-in', pathMatch: 'full' },
  { path: 'sign-in', component: SignInComponent },
  { path: 'dashboard', component: DashboardComponent },
];

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

export class AppRoutingModule {}

5. Create Auth Service

I am going to create AuthenticationServicefile, this file will hold following logics.

– Create authentication.service.ts file

This file holds the core logic of our authentication service. I’ll be covering up following methods in it.

  • Sign in with Google
  • Saving user data as an object in localStorage at login
  • Removing user data object from localStorage at log out
import { Injectable, NgZone } from '@angular/core';
import * as auth from 'firebase/auth';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root',
})

export class AuthenticationService {
  userData: any;

  constructor(
    public afAuth: AngularFireAuth,
    public router: Router,
    public ngZone: NgZone
  ) {
    this.afAuth.authState.subscribe((user) => {
      if (user) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user'));
      } else {
        localStorage.setItem('user', null);
        JSON.parse(localStorage.getItem('user'));
      }
    });
  }

  SignIn(email, password) {
    return this.afAuth
      .signInWithEmailAndPassword(email, password)
      .then((result) => {
        this.ngZone.run(() => {
          this.router.navigate(['dashboard']);
        });
      })
      .catch((error) => {
        window.alert(error.message);
      });
  }

  GoogleAuth() {
    return this.AuthLogin(new auth.GoogleAuthProvider());
  }

  AuthLogin(provider) {
    return this.afAuth
      .signInWithPopup(provider)
      .then((result) => {
        this.ngZone.run(() => {
          this.router.navigate(['dashboard']);
        });
      })
      .catch((error) => {
        window.alert(error);
      });
  }

  SignOut() {
    return this.afAuth.signOut().then(() => {
      localStorage.removeItem('user');
      this.router.navigate(['sign-in']);
    });
  }
}

After that, go to src/app.module.ts file and import authentication service and pass the AuthenticationService class into providers: [AuthenticationService] array. By doing this our authentication service will be available throughout the application.

// Auth service
import { AuthenticationService} from "./shared/services/authentication.service";

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [AuthenticationService],
  bootstrap: [...]
})

6. Setting up Sign in with Google in Angular Template

In order to consume AuthenticationService class from authentication.service.ts file we need to import AuthenticationService service into components/sign-in/sign-in.component.ts file and then inject AuthenticationServiceclass into the constructor so that these services will be available throughout the same template.

Go to sign-in.component.ts file and paste the following code.

import { Component, OnInit } from '@angular/core';
import { AuthenticationService} from '../../authentication.service';

@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.component.html',
  styleUrls: ['./sign-in.component.scss'],
})

export class SignInComponent implements OnInit {
  constructor(public authenticationService: AuthenticationService) {}

  ngOnInit() {}
}

Go to sign-in/sign-in.component.html file and include the given below code.

<div class="displayTable">
  <div class="displayTableCell">
    <div class="authBlock">
      <h3>Sign In</h3>

      <!-- Calling GoogleAuth Api from AuthenticationService-->
      <div class="formGroup">
        <button
          type="button"
          class="btn googleBtn"
          (click)="authenticationService.GoogleAuth()"
        >
          <i class="fab fa-google-plus-g"></i>
          Log in with Google
        </button>
      </div>
    </div>
  </div>
</div>

7. Check user data in Browser Console When not Logged In

When you are not lgged in, you see user === null in browser’s application console.

Auth State Null

8. Check user data in Browser Console After Logged In

When you are lgged in, you see user data in browser’s application console.

User Data Object LocalStorage

9. Reteriving User Data and Showing up in Dashboard Component

Go to dashboard.component.ts add the following code.

import { Component, OnInit } from '@angular/core';
import { AuthenticationService} from '../../authentication.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss'],
})

export class DashboardComponent implements OnInit {
  constructor(public authenticationService: AuthenticationService) {}

  ngOnInit() {}
}

Go to dashboard.component.html file, and add the data into HTML tags.

<!-- Top navigation -->
<nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
    <span class="dasboard-text">Dashboard</span>
</nav>

<!-- Sidebar navigation -->
<div class="container-fluid">
  <div class="row">
    <nav class="col-md-2 d-md-block bg-light sidebar">
      <div class="sidebar-sticky">
        <ul class="nav flex-column">
          <li class="nav-item">
            <a class="nav-link active">
              <i class="fas fa-user"></i>User Profile
            </a>
          </li>
          <!-- Calling SignOut() Api from AuthenticationService-->
          <li class="nav-item">
            <a class="nav-link" (click)="authenticationService.SignOut()">
              <i class="fas fa-sign-out-alt"></i>Log out
            </a>
          </li>
        </ul>
      </div>
    </nav>

    <!-- Main content -->
    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
      <div class="inner-adjust">
        <div class="pt-3 pb-2 mb-3 border-bottom">
          <h1 class="h2">User Profile</h1>
        </div>
        <!-- Show user data when logged in -->
        <div class="row" *ngIf="authenticationService.userData as user">
          <div class="col-md-12">
            <div class="media">
              <img
                class="align-self-start mr-5 img-thumbnail rounded-circle"
                src="{{
                  user.photoURL ? user.photoURL : '/assets/dummy-user.png'
                }}"
                alt="{{ user.displayName }}"
              />
              <div class="media-body">
                <h1>
                  Hello:
                  <strong>{{
                    user.displayName ? user.displayName : "Super Admin"
                  }}</strong>
                </h1>
                <p>
                  User ID: <strong>{{ user.uid }}</strong>
                </p>
                <p>
                  Email: <strong>{{ user.email }}</strong>
                </p>
                <p>
                  Email Verified: <strong>{{ user.emailVerified }}</strong>
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
  </div>
</div>

Here is the final code example of app.module.ts file.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthenticationService } from './authentication.service';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { AngularFireStorageModule } from '@angular/fire/compat/storage';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
import { environment } from '../environments/environment';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule,
    AngularFirestoreModule,
    AngularFireStorageModule,
    AngularFireDatabaseModule,
  ],
  providers: [AuthenticationService],
  bootstrap: [AppComponent]
})

export class AppModule { }

Please also have a look on app-routing.module.ts file and update the code in your file as given below:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';

const routes: Routes = [
  { path: '', redirectTo: '/sign-in', pathMatch: 'full' },
  { path: 'sign-in', component: SignInComponent },
  { path: 'dashboard', component: DashboardComponent },
];

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

export class AppRoutingModule {}

Next, also add the router outlet directive in app.component.html file.

<router-outlet></router-outlet>

Run the following command to start your project.

ng serve --open
You can also check out my detailed article on Full Firebase Authentication System with Angular.

Conclusion

Thanks a lot for taking the time to read this tutorial, I hope this tutorial has been helpful to you. If you think this tutorial has helped you then must share this tutorial with others.

Download complete code of this tutorial from GitHub.