DEV Community

Cover image for 🚀 Supercharge NestJS Authentication with Firebase
Tomás Alegre Sepúlveda
Tomás Alegre Sepúlveda

Posted on • Edited on

🚀 Supercharge NestJS Authentication with Firebase

🇪🇸 Lee este post en Español

If you're building a modern application with NestJS, you probably love its modularity, decorators, and type safety. But when it comes to authentication, integrating external providers often feels like a chore—boilerplate guards, manual token verification, and messy role handling.

Today, I want to re-introduce nestjs-firebase-auth, a library designed to make Firebase Authentication feel native to the NestJS ecosystem.

🤔 Why this library?

Firebase Authentication is robust, but the official Admin SDK is just that—an SDK. It doesn't know about NestJS Guards, Decorators, or Dependency Injection.

You shouldn't have to write custom middleware to decode tokens or manually check claims in every controller. nestjs-firebase-auth bridges this gap, giving you a simplified, declarative API for securing your application.

With the latest v1.9.0 release, I've polished the experience even further with cleaner decorators and better integration with other Firebase services like Firestore.

Installation

npm install @alpha018/nestjs-firebase-auth firebase-admin
Enter fullscreen mode Exit fullscreen mode

🛠️ Deep Dive into the Code

Let's look at how this changes your daily workflow.

1. Declarative Authentication (@Auth)

Forget about manually importing and binding guards with @UseGuards(FirebaseGuard). You now have a clean @Auth() decorator that makes your intention clear.

import { Auth } from '@alpha018/nestjs-firebase-auth';

@Auth() // 🛡️ Protects this entire controller
@Controller('users')
export class UsersController {

  @Get('profile')
  getProfile() {
    return "This data is secure.";
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Role-Based Access Control (RBAC)

Managing roles shouldn't be complicated. I use Firebase Custom Claims to store user roles, and the @Roles decorator to enforce them without writing a single line of validation logic.

import { Auth, Roles } from '@alpha018/nestjs-firebase-auth';

@Controller('admin')
export class AdminController {

  @Auth()
  @Roles('ADMIN', 'SUPERUSER') // ⛔ Only allows users with these roles
  @Get('dashboard')
  getDashboard() {
    return "Top secret admin data";
  }
}
Enter fullscreen mode Exit fullscreen mode

Note: The @Roles decorator automatically triggers the underlying role validation logic when used with @Auth.

3. Type-Safe User Access

Accessing the current user's data is straightforward and type-safe using @FirebaseUser.

@Get('me')
getProfile(@FirebaseUser() user: DecodedIdToken) {
  // `user` is the standard Firebase DecodedIdToken
  console.log(user.uid, user.email);
}
Enter fullscreen mode Exit fullscreen mode

4. Integrating with other Firebase Services

Need to talk to Firestore or send a clear-cut FCM message? It has always been possible, but I want to highlight how easy it is to access the initialized admin.app.App instance directly from my provider.

import { FirebaseProvider } from '@alpha018/nestjs-firebase-auth';
import { getFirestore } from 'firebase-admin/firestore';

@Injectable()
export class UserDataService {
  constructor(private readonly firebaseProvider: FirebaseProvider) {}

  async saveUserData(uid: string, data: any) {
    // 🔥 Use the auth module's app instance for Firestore
    const firestore = getFirestore(this.firebaseProvider.app);
    return firestore.collection('users').doc(uid).set(data);
  }
}
Enter fullscreen mode Exit fullscreen mode

🎯 Best Use Cases

  • SaaS Applications: Where you need robust, secure authentication with minimal setup.
  • Microservices: Sharing authentication logic across multiple NestJS services easily using a shared library approach.
  • RBAC Systems: Apps that require granular control over who can do what (Admins vs. Users).

⚠️ Trade-offs (Honesty First)

  • Remote Validation: By default, I verify roles by fetching the user record from Firebase. This ensures roles are always up to date (no stale tokens), but it incurs a small network latency.
  • Local Validation: You can opt-in to useLocalRoles: true to validate against the ID token's claims directly (zero latency), but you must accept that role changes effectively update only when the user refreshes their token.

💌 Special Acknowledgments

This project has been built with many hours of dedication and love for code.

To a girl who always inspires me in silence, and whose mere existence incentivizes me to keep programming in my free time, thank you "YLP".

☕ Support the Project

If you found this project useful or interesting, please consider supporting it:

  • ⭐️ Star on GitHub: It's free and helps others find the library.
  • Buy me a Coffee: If you want to go the extra mile, you can do so at buymeacoffee.com/alpha018.

🔗 Try it and Contribute

What do you think? Are you ready to simplify your authentication flow? 👇

Top comments (0)