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.



