Firebase Authentication offers a dependable, straightforward backend solution for handling user sign-in within your Angular apps.

A wide range of authentication strategies are available, such as email/password, third-party providers like Google and Facebook, as well as phone-based verification.

We'll cover the entire process here: configuring Firebase Authentication, connecting it to your Angular app, and examining different sign-in options, recommended practices, and typical use cases.

Visualize Firebase as the security checkpoint for your application, much like a club's doorman. Gaining access to the premium areas—your app's core data and features—requires valid proof of identity. Configuring Firebase is essentially recruiting that doorman and outlining how they should verify visitor IDs.

Setting Up Firebase in Your Angular Project

  • A Firebase project is a prerequisite; if you haven't got one yet, head over to the console (console.firebase.google.com) and create it.

  • Once you're in the console, access your project, hit "Add app," choose "Web," and proceed with the registration steps for your Angular app.
    This yields a configuration object armed with API keys and other essential details.

  • Use npm to add the Firebase package to your Angular project's dependencies:

npm install @angular/fire
Enter fullscreen mode Exit fullscreen mode
  • Bring in the required Firebase dependencies and set up the Firebase app initialization inside your app.config.ts file:
import { provideHttpClient } from '@angular/common/http';
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { getAuth, provideAuth } from '@angular/fire/auth';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideRouter } from '@angular/router';
import { environment } from '../environments/environments';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideAuth(() => getAuth()),
    provideAnimationsAsync(),
    provideHttpClient(),
  ]
};
Enter fullscreen mode Exit fullscreen mode

Your environment.firebase property — located inside both environment.ts and environment.prod.ts — must hold the complete Firebase configuration object:

export const environment = {
    production: false,
    firebase: {
        apiKey: "-----",
        authDomain: "-----",
        projectId: "-----",
        storageBucket: "-----",
        messagingSenderId: "-----",
        appId: "-----",
    }
};
Enter fullscreen mode Exit fullscreen mode

Email/Password Authentication

Among all authentication options, this one is used most frequently.

  • To keep your codebase tidy and support reuse, set up a dedicated service. Start by adding a new file called auth.service.ts:
import { Injectable } from '@angular/core';
import {
  Auth,
  browserSessionPersistence,
  GoogleAuthProvider,
  signInWithEmailAndPassword,
  signInWithPopup,
  signOut,
  user,
  User,
} from '@angular/fire/auth';
import { setPersistence } from 'firebase/auth';
import { from, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  user$: Observable<User | null>;

  constructor(private firebaseAuth: Auth) {
    this.setSessionStoragePersistence();
    this.user$ = user(this.firebaseAuth);
  }

  private setSessionStoragePersistence(): void {
    setPersistence(this.firebaseAuth, browserSessionPersistence);
  }

  login(email: string, password: string): Observable<void> {
    const promise = signInWithEmailAndPassword(
      this.firebaseAuth,
      email,
      password
    ).then(() => {
      //
    });
    return from(promise);
  }

  logout(): Observable<void> {
    const promise = signOut(this.firebaseAuth).then(() => {
      sessionStorage.clear();
    });
    return from(promise);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Bring the AuthService into your components via dependency injection
import { Component, inject } from '@angular/core';
import {
  FormsModule,
  Validators,
  ReactiveFormsModule,
  FormBuilder,
} from '@angular/forms';
import { AuthService } from './service/auth.service';
import { Router, RouterLink } from '@angular/router';

@Component({
  selector: 'app-user-login',
  standalone:true,
  imports: [FormsModule, ReactiveFormsModule, RouterLink],
  templateUrl: './login.component.html',
  styles: '',
})
export class LoginComponent {
  error: boolean = false;
  fb: FormBuilder = inject(FormBuilder);
  authService: AuthService = inject(AuthService);
  router: Router = inject(Router);
  form = this.fb.nonNullable.group({
    email: [
      '',
      [
        Validators.required,
        Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/),
      ],
    ],
    password: ['', Validators.required],
  });

  onSubmit(): void {
    const rawForm = this.form.getRawValue();
    this.authService.login(rawForm.email, rawForm.password).subscribe({
      next: () => {
        this.router.navigateByUrl('/protected-content');
      },
      error: (error) => {
        this.error = true;
        console.error('Email/Password Sign-In error:', error);
      },
    });
  }

  guestLogin(): void {
    const values = { email: 'guest@mail.uk', password: 'fake_password' };
    this.form.patchValue(values);
    const subscription = this.form.valueChanges.subscribe(() => {
      if (this.form.valid) {
        subscription.unsubscribe();
        this.onSubmit();
      }
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Considerations

  • Error Handling: It's crucial to implement robust error handling that gives users clear feedback and manages failed authentication attempts gracefully. Firebase exposes detailed error codes, allowing you to tailor your messages accordingly.
  • Security Best Practices: Avoid placing sensitive data such as API keys directly in client-side code. Instead, safeguard your credentials through environment variables or server-side logic.
  • Observables: Leverage observables to respond to authentication state changes, which lets you adjust your UI dynamically depending on the user's logged-in status.
  • Asynchronous Operations: Since Firebase authentication calls are asynchronous, always use async/await or promise-based patterns to process the results.

Social Logins

Working with social login providers becomes much easier with Firebase. Start by activating the providers you need under the Authentication section in your Firebase console. Below is a sample implementation for Google Sign-In:

async onGoogleSignIn(): Promise<void> {
  try {
    await this.authService.googleLogin();
    this.router.navigateByUrl('/main');
  } catch (error) {
    console.error('Google Sign-In error:', error);
  }
}

---

async googleLogin(): Promise<void> {
  const provider = new GoogleAuthProvider();
  try {
    const result = await signInWithPopup(this.firebaseAuth, provider);
    const user = result.user;
    if (!user) {
      throw new Error('Google-Login error');
    }
  } catch (error) {
    console.error('Google-Login error:', error);
    throw error;
  }
}
Enter fullscreen mode Exit fullscreen mode

Protecting Routes

To secure pages that depend on a logged-in user, rely on Angular's route guard mechanism.

import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../service/auth.service';
import { inject } from '@angular/core';
import { map } from 'rxjs';

export const authGuard: CanActivateFn = () => {
  const authService = inject(AuthService);
  const router = inject(Router);

  return authService.user$.pipe(
    map((user) => {
      if (user) {
        return true;
      } else {
        router.navigate(['']);
        return false;
      }
    })
  );
};
Enter fullscreen mode Exit fullscreen mode

Next, wire up the guard inside your routing configuration:

import { Routes } from '@angular/router';
import { authGuard } from './guards/auth.guard';
import { LoginComponent } from './login.component';
import { ProtectedContentComponent } from './protected-content.component';

export const routes: Routes = [
  {
    path: '',
    component: LoginComponent,
  },
  {
    path: 'protected-content',
    component: ProtectedContentComponent,
    canActivate: [authGuard], 👈
  },
  { path: '**', redirectTo: '' },
];
Enter fullscreen mode Exit fullscreen mode

Managing User State and Data

Within your components, tap into the user$ observable to track authentication shifts and tailor what the user sees, so their content adapts dynamically:

import { Component, inject, OnInit } from '@angular/core';
import { AuthService } from './service/auth.service';
import { AsyncPipe, CommonModule } from '@angular/common';
import { Router, RouterLink } from '@angular/router';

@Component({
  selector: 'app-protected-content',
  standalone: true,
  template: `
    <div *ngIf="user$ | async as user">
      <p>Welcome, {{ user.email }}!</p>
      <button (click)="signOut()">Sign Out</button>
    </div>
  `,
  styleUrls: ['./profile.component.css'],
  imports: [AsyncPipe, CommonModule]
})
export class ProtectedContentComponent implements OnInit {
  router: Router = inject(Router);
  authService: AuthService = inject(AuthService);
  user$ = this.authService.user$;

  ngOnInit(): void {}

  async signOut() {
    try {
      await this.authService.logout();
      console.log('User signed out');
      this.router.navigateByUrl('/');
    } catch (error) {
      console.error('Sign out error:', error);
      // Handle the error appropriately, e.g., show a message to the user
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This guide walks you through the core aspects of integrating Firebase Authentication into an Angular app. By applying these approaches, you’ll be able to protect your application and deliver an effortless user journey. Always weigh the security ramifications of authentication and treat user data with care. As you move forward, dive into the more sophisticated options Firebase Authentication offers to customize the login experience according to your requirements.


😄 Honestly, I’m thrilled about how straightforward this feature is to implement.

Feel free to connect with me on GitHub, where I’m working on interesting projects.

Thanks for reading, and please leave a ❤️ if you liked it.
See you later 👋

gioboa image