How to use Firebase auth in Angular

Firebase Authentication provides secure user authentication with minimal backend code, supporting email/password, social providers, and phone authentication. As the creator of CoreUI, a widely used open-source UI library, I’ve integrated Firebase Auth in production Angular applications throughout my 12 years of frontend development since 2014. The most streamlined approach is using @angular/fire package for Angular-specific Firebase integration with reactive authentication state management. This method provides type-safe Firebase access, automatic dependency injection, and seamless integration with Angular’s reactive patterns and router guards.

Install @angular/fire and Firebase SDK, configure Firebase in environment, create auth service with email and Google sign-in methods.

npm install @angular/fire firebase
// src/environments/environment.ts
export const environment = {
  production: false,
  firebase: {
    apiKey: 'YOUR_API_KEY',
    authDomain: 'YOUR_PROJECT.firebaseapp.com',
    projectId: 'YOUR_PROJECT_ID',
    storageBucket: 'YOUR_PROJECT.appspot.com',
    messagingSenderId: 'YOUR_SENDER_ID',
    appId: 'YOUR_APP_ID'
  }
}
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideRouter } from '@angular/router'
import { provideFirebaseApp, initializeApp } from '@angular/fire/app'
import { provideAuth, getAuth } from '@angular/fire/auth'
import { environment } from '../environments/environment'
import { routes } from './app.routes'

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideAuth(() => getAuth())
  ]
}
// src/app/core/services/firebase-auth.service.ts
import { Injectable } from '@angular/core'
import { Auth, authState, User } from '@angular/fire/auth'
import {
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  signOut,
  GoogleAuthProvider,
  signInWithPopup,
  sendPasswordResetEmail,
  updateProfile
} from '@angular/fire/auth'
import { Observable } from 'rxjs'

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

  constructor(private auth: Auth) {
    this.user$ = authState(this.auth)
  }

  async signInWithEmail(email: string, password: string): Promise<User> {
    try {
      const credential = await signInWithEmailAndPassword(this.auth, email, password)
      return credential.user
    } catch (error: any) {
      throw this.handleAuthError(error)
    }
  }

  async signUpWithEmail(email: string, password: string, displayName?: string): Promise<User> {
    try {
      const credential = await createUserWithEmailAndPassword(this.auth, email, password)

      if (displayName && credential.user) {
        await updateProfile(credential.user, { displayName })
      }

      return credential.user
    } catch (error: any) {
      throw this.handleAuthError(error)
    }
  }

  async signInWithGoogle(): Promise<User> {
    try {
      const provider = new GoogleAuthProvider()
      provider.addScope('profile')
      provider.addScope('email')

      const credential = await signInWithPopup(this.auth, provider)
      return credential.user
    } catch (error: any) {
      throw this.handleAuthError(error)
    }
  }

  async signOut(): Promise<void> {
    try {
      await signOut(this.auth)
    } catch (error: any) {
      throw this.handleAuthError(error)
    }
  }

  async resetPassword(email: string): Promise<void> {
    try {
      await sendPasswordResetEmail(this.auth, email)
    } catch (error: any) {
      throw this.handleAuthError(error)
    }
  }

  getCurrentUser(): User | null {
    return this.auth.currentUser
  }

  async getIdToken(): Promise<string | undefined> {
    const user = this.getCurrentUser()
    return user ? user.getIdToken() : undefined
  }

  private handleAuthError(error: any): Error {
    let message = 'An authentication error occurred'

    switch (error.code) {
      case 'auth/user-not-found':
        message = 'No user found with this email'
        break
      case 'auth/wrong-password':
        message = 'Incorrect password'
        break
      case 'auth/email-already-in-use':
        message = 'Email already in use'
        break
      case 'auth/weak-password':
        message = 'Password should be at least 6 characters'
        break
      case 'auth/invalid-email':
        message = 'Invalid email address'
        break
      case 'auth/popup-closed-by-user':
        message = 'Sign-in popup was closed'
        break
      default:
        message = error.message
    }

    return new Error(message)
  }
}
// src/app/core/guards/auth.guard.ts
import { Injectable } from '@angular/core'
import { Router } from '@angular/router'
import { FirebaseAuthService } from '../services/firebase-auth.service'
import { map, take } from 'rxjs/operators'
import { Observable } from 'rxjs'

@Injectable({
  providedIn: 'root'
})
export class AuthGuard {
  constructor(
    private authService: FirebaseAuthService,
    private router: Router
  ) {}

  canActivate(): Observable<boolean> {
    return this.authService.user$.pipe(
      take(1),
      map(user => {
        if (user) {
          return true
        }
        this.router.navigate(['/login'])
        return false
      })
    )
  }
}
// src/app/auth/login/login.component.ts
import { Component } from '@angular/core'
import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
import { Router } from '@angular/router'
import { FirebaseAuthService } from '../../core/services/firebase-auth.service'

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div class='login-container'>
      <h2>Login</h2>

      <form (ngSubmit)='onSubmit()' #loginForm='ngForm'>
        <div class='form-group'>
          <label for='email'>Email</label>
          <input
            type='email'
            id='email'
            name='email'
            [(ngModel)]='credentials.email'
            required
            email
          />
        </div>

        <div class='form-group'>
          <label for='password'>Password</label>
          <input
            type='password'
            id='password'
            name='password'
            [(ngModel)]='credentials.password'
            required
            minlength='6'
          />
        </div>

        <button type='submit' [disabled]='!loginForm.valid || loading'>
          {{ loading ? 'Logging in...' : 'Login' }}
        </button>

        <p *ngIf='error' class='error'>{{ error }}</p>
      </form>

      <div class='divider'>
        <span>OR</span>
      </div>

      <button (click)='signInWithGoogle()' [disabled]='loading' class='google-btn'>
        Sign in with Google
      </button>

      <div class='links'>
        <a (click)='forgotPassword()'>Forgot Password?</a>
        <a [routerLink]='["/register"]'>Create Account</a>
      </div>
    </div>
  `
})
export class LoginComponent {
  credentials = {
    email: '',
    password: ''
  }

  loading = false
  error = ''

  constructor(
    private authService: FirebaseAuthService,
    private router: Router
  ) {}

  async onSubmit(): Promise<void> {
    this.loading = true
    this.error = ''

    try {
      await this.authService.signInWithEmail(
        this.credentials.email,
        this.credentials.password
      )
      this.router.navigate(['/dashboard'])
    } catch (error: any) {
      this.error = error.message
    } finally {
      this.loading = false
    }
  }

  async signInWithGoogle(): Promise<void> {
    this.loading = true
    this.error = ''

    try {
      await this.authService.signInWithGoogle()
      this.router.navigate(['/dashboard'])
    } catch (error: any) {
      this.error = error.message
    } finally {
      this.loading = false
    }
  }

  async forgotPassword(): Promise<void> {
    if (!this.credentials.email) {
      this.error = 'Please enter your email address'
      return
    }

    try {
      await this.authService.resetPassword(this.credentials.email)
      alert('Password reset email sent. Please check your inbox.')
    } catch (error: any) {
      this.error = error.message
    }
  }
}

Here the @angular/fire package provides Angular-specific Firebase integration with dependency injection. The provideFirebaseApp and provideAuth configure Firebase and Authentication modules globally. The authState observable emits current user on auth state changes. The signInWithEmailAndPassword and createUserWithEmailAndPassword handle email/password authentication. The GoogleAuthProvider with signInWithPopup enables Google sign-in with popup window. The handleAuthError method provides user-friendly error messages for common Firebase auth errors. The AuthGuard uses user$ observable to protect routes requiring authentication. The getIdToken method retrieves JWT token for backend API authentication.

Best Practice Note:

This is the Firebase Authentication integration we use in CoreUI Angular templates for rapid development of secure authentication systems. Enable email verification after signup to ensure valid email addresses, implement auth state persistence using Firebase’s built-in persistence modes, use Firebase Security Rules to secure Firestore and Storage access based on authentication state, and consider implementing multi-factor authentication for sensitive applications.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author