Introduction
Managing authentication in a modern web app can be challenging, especially when dealing with various identity providers and securing endpoints. Firebase Authentication simplifies this process by providing robust authentication out of the box, and NestJS offers a powerful framework for building scalable applications.
In this post, I'll introduce you to @alpha018/nestjs-firebase-auth
, a library that makes integrating Firebase Authentication into NestJS simple and flexible. Whether you need basic authentication or role-based access control (RBAC) using Firebase custom claims, this library has you covered.
What Does nestjs-firebase-auth
Do?
This library extends NestJS’s authentication capabilities using Firebase's Admin SDK and Passport strategy. It provides a variety of tools that make it easier to:
- Authenticate users via Firebase tokens.
- Validate user roles using Firebase custom claims.
- Customize token extraction and handle revoked tokens.
- Secure routes with minimal boilerplate code.
Let’s dive into how to set up the library and explore its key features.
Installation
To get started, install the package along with the Firebase Admin SDK:
npm i @alpha018/nestjs-firebase-auth firebase-admin
You will also need to configure Firebase in your project by downloading the service account key from your Firebase Console.
Core Features and Components
1. Module Configuration
The FirebaseAdminModule
allows you to configure Firebase for your NestJS app. You can pass a base64-encoded service account JSON string or use regular options to configure Firebase.
Here's an example of how to import and configure the module:
import { Module } from '@nestjs/common';
import { FirebaseAuthGuard, FirebaseAdminModule } from '@alpha018/nestjs-firebase-auth';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
FirebaseAdminModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
base64: configService.get('FIREBASE_SERVICE_ACCOUNT_BASE64'),
options: {}, // Optionally, provide Firebase configuration here
auth: {
config: {
extractor: ExtractJwt.fromAuthHeaderAsBearerToken(), // Extract JWT from the header
checkRevoked: true, // Optionally check if the token is revoked
validateRole: true, // Enable role validation if needed
},
},
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
2. Auth Guards and Role Validation
The FirebaseAuthGuard
is at the heart of securing your endpoints. You can use it to protect routes and validate user tokens. If your app needs role-based access control, the library integrates Firebase custom claims to enforce RBAC seamlessly.
Protecting Routes Without Role Validation
If you only need basic authentication, the FirebaseAuthGuard
will ensure that only authenticated users can access your routes.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { FirebaseAuthGuard } from '@alpha018/nestjs-firebase-auth';
@Controller()
export class AppController {
@UseGuards(FirebaseAuthGuard)
@Get()
getProtectedData(): string {
return 'This route is protected by Firebase Auth!';
}
}
Role-Based Access Control (RBAC)
For more advanced use cases, you can use Firebase custom claims to implement role-based access. The library supports setting and validating these roles with ease.
Here’s how you can set a user’s role:
import { Controller, Get } from '@nestjs/common';
import { FirebaseProvider } from '@alpha018/nestjs-firebase-auth';
enum Roles {
ADMIN = 'ADMIN',
USER = 'USER',
}
@Controller()
export class AppController {
constructor(private readonly firebaseProvider: FirebaseProvider) {}
@Get('/set-role')
async setAdminRole() {
await this.firebaseProvider.setClaimsRoleBase<Roles>('FirebaseUID', [Roles.ADMIN]);
return { status: 'Admin role assigned!' };
}
}
Then, use the RolesGuard
to enforce role validation for specific endpoints:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { FirebaseAuthGuard, RolesGuard } from '@alpha018/nestjs-firebase-auth';
enum Roles {
ADMIN = 'ADMIN',
USER = 'USER',
}
@Controller()
export class AppController {
@RolesGuard(Roles.ADMIN, Roles.USER) // This line checks the custom claims of the Firebase user to protect the endpoint
@UseGuards(FirebaseGuard)
@Get('/admin')
getAdminData(): string {
return 'Admin-only data!';
}
}
3. User from token and Claims Extraction
The library makes it easy to retrieve user details and claims from Firebase tokens. Using the @FirebaseUser()
and @FirebaseUserClaims()
decorators, you can extract important information from the authenticated user.
For example:
import { Controller, Get } from '@nestjs/common';
import { FirebaseUser, FirebaseUserClaims } from '@alpha018/nestjs-firebase-auth';
import { auth } from 'firebase-admin';
enum Roles {
ADMIN = 'ADMIN',
USER = 'USER',
}
@Controller()
export class AppController {
@Get('/user-info')
getUserInfo(
@FirebaseUser() user: auth.DecodedIdToken,
@FirebaseUserClaims() claims: Roles[],
) {
return { user, claims };
}
}
4. Handling Token Revocation
Firebase supports token revocation, which allows you to invalidate tokens after they’ve been issued. This is a useful security feature in case a user is compromised. You can configure the guard to check for revoked tokens automatically by enabling checkRevoked
.
@Module({
imports: [
ConfigModule.forRoot(),
FirebaseAdminModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
base64: configService.get('FIREBASE_SERVICE_ACCOUNT_BASE64'),
auth: {
config: {
checkRevoked: true, // Ensure revoked tokens are invalidated
},
},
}),
inject: [ConfigService],
}),
],
})
Additional Utilities
The library also provides utility methods for managing claims and handling role-based logic. With FirebaseProvider
, you can set, get, and validate claims easily, allowing you to manage complex access control systems with minimal effort.
Why Use nestjs-firebase-auth
?
The beauty of this library is its simplicity and flexibility. With a few configurations, you can have a robust authentication system ready to go. Whether you’re building a small project or scaling up with more complex security needs, nestjs-firebase-auth
provides all the tools you need.
Key benefits include:
- Seamless Firebase Integration: Leverage the full power of Firebase Auth within NestJS.
- Role-Based Access Control: Secure your routes with custom claims and easily manage roles.
- Token Revocation Support: Automatically handle revoked tokens to keep your app secure.
- Custom Token Extractors: Flexibility in how you extract and validate tokens from requests.
Conclusion
If you’re looking to add Firebase Authentication to your NestJS project, nestjs-firebase-auth
is the perfect library to get you started quickly and securely. It simplifies the process of adding authentication and role validation, making your API secure with minimal setup.
Feel free to check out the full source code and contribute to the project on GitHub. Your feedback and contributions are always welcome!
Happy coding!
Top comments (0)