@alpha018/nestjs-firebase-auth
Version:
NestJS Firebase library and Role based guard for authentication with some utils functions
312 lines (235 loc) • 11.1 kB
Markdown
# NestJS Firebase Auth
<div align="center">
<a href="http://nestjs.com/" target="_blank">
<img src="https://nestjs.com/img/logo_text.svg" width="150" alt="Nest Logo" />
</a>
</div>
<h3 align="center">NestJS Passport Strategy for Firebase Auth using Firebase Admin SDK, which includes the Firebase SDK library for use.</h3>
<p align="center">
<b><a href="docs/wiki/Home.md">Check out the Wiki for full documentation and guides!</a></b>
</p>
<div align="center">
<a href="https://nestjs.com" target="_blank">
<img src="https://img.shields.io/badge/built%20with-NestJs-red.svg" alt="Built with NestJS">
</a>
<a href="https://github.com/Alpha018/nestjs-firebase-auth/actions">
<img src="https://github.com/Alpha018/nestjs-firebase-auth/actions/workflows/build.yml/badge.svg" alt="Test Status">
</a>
<a href="https://github.com/Alpha018/nestjs-firebase-auth">
<img src="https://img.shields.io/github/stars/Alpha018/nestjs-firebase-auth?style=social" alt="GitHub stars">
</a>
</div>
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Import the Module](#import-the-module)
- [Parameter Options](#parameter-options)
- [Auth Guard Without Role Validation](#auth-guard-without-role-validation)
- [Auth Guard With Role Validation](#auth-guard-with-role-validation)
- [Additional Information](#additional-information)
- [Documentation](#documentation)
- [Resources](#resources)
- [Stay in touch](#stay-in-touch)
- [License](#license)
> **⚠️ Important:** Starting from this version, the minimum required Node.js version is **20**, due to the Firebase Admin SDK v12 upgrade.
## Installation
```bash
npm i /nestjs-firebase-auth firebase-admin
```
## Usage
### Import The Module
To use Firebase authentication in your application, import the module into your main module.
```ts
import { FirebaseAdminModule } from '@alpha018/nestjs-firebase-auth';
({
imports: [
...
FirebaseAdminModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
// SELECT ONLY ONE: BASE64 OR OPTIONS (Firebase Options)!
base64: configService.get('FIREBASE_SERVICE_ACCOUNT_BASE64'), // Base64 encoded service account JSON string
options: {}, // Use this if not using base64
auth: {
config: {
extractor: ExtractJwt.fromAuthHeaderAsBearerToken(), // Choose your extractor from the Passport library
checkRevoked: true, // Set to true if you want to check for revoked Firebase tokens
validateRole: true, // Set to true if you want to validate user roles
useLocalRoles: true, // Set to true if you want to validate user roles locally without firebase call
rolesClaimKey: 'user_roles' // Set the name of the key within the Firebase custom claims that stores user roles
},
},
}),
inject: [ConfigService],
}),
...
],
})
```
## Parameter Options
| Parameter | Type | Required | Description |
|-----------------------------|------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `base64` | `string` | Yes* | Base64 encoded service account JSON string. Required if `options` is not provided. |
| `options` | `object` | Yes* | Firebase Admin SDK configuration options. Required if `base64` is not provided. |
| `auth.config.extractor` | `function` | Optional | A custom extractor function from the Passport library to extract the token from the request. |
| `auth.config.checkRevoked` | `boolean` | Optional | Set to `true` to check if the Firebase token has been revoked. Defaults to `false`. |
| `auth.config.validateRole` | `boolean` | Optional | Set to `true` to validate user roles using Firebase custom claims. Defaults to `false`. |
| `auth.config.useLocalRoles` | `boolean` | Optional | Set to `true` to validate user roles using local custom claims inside the JWT token. Defaults to `false`. **Note:** If you update the claims, previously issued tokens may still contain outdated roles and remain valid. |
| `auth.config.rolesClaimKey` | `string` | Optional | The name of the key within the Firebase custom claims that stores user roles. Defaults to `'roles'`. This allows you to customize the property name for roles in your custom claims object. |
### Auth Guard Without Role Validation
> **⚠️ Deprecation Warning:** Direct usage of `UseGuards(FirebaseGuard)` is deprecated. Please use the `` decorator instead.
To protect an endpoint without validating user roles, use the Auth Guard to ensure the Firebase user's token is valid.
```ts
import { Auth, FirebaseProvider } from '@alpha018/nestjs-firebase-auth';
export class AppController {
constructor(
private readonly firebaseProvider: FirebaseProvider,
) {}
() // This line protects your endpoint with Firebase Auth
()
mainFunction() {
return 'Hello World';
}
}
```
### Auth Guard With Role Validation
To enforce role-based access control, you need to set role-based custom claims in Firebase. Here's how you can set roles for a user using `setClaimsRoleBase`:
```ts
import { FirebaseProvider } from '@alpha018/nestjs-firebase-auth';
enum Roles {
ADMIN,
USER,
}
('')
export class AppController {
constructor(
private readonly firebaseProvider: FirebaseProvider,
) {}
()
async setUserRoles() {
await this.firebaseProvider.setClaimsRoleBase<Roles>(
'some-firebase-uid', // The UID of the user you want to set roles for
[Roles.ADMIN]
);
return { status: 'ok' }
}
}
```
Then, use the Auth Guard with role validation to check if a user has the necessary permissions to access an endpoint:
```ts
import { Roles } from '@alpha018/nestjs-firebase-auth';
enum Roles {
ADMIN,
USER,
}
('')
export class AppController {
constructor(
private readonly firebaseProvider: FirebaseProvider,
) {}
(Roles.ADMIN, Roles.USER) // This line checks the custom claims of the Firebase user AND ensures the user is authenticated (implicitly applies FirebaseGuard)
()
mainFunction() {
return 'Hello World';
}
}
```
### Controller-Level Authentication with Method-Level Authorization
You can apply authentication at the controller level using `()` and then define specific roles for individual routes using `()`. The library is optimized to prevent redundant token verification in this scenario.
```ts
import { Auth, Roles } from '@alpha018/nestjs-firebase-auth';
enum AppRoles {
ADMIN,
USER,
}
() // Protects all routes in this controller (ensures valid token)
('users')
export class UsersController {
('profile')
getProfile() {
// Accessible by any authenticated user
return { status: 'ok' };
}
(AppRoles.ADMIN) // Adds specific authorization requirement
('admin-dashboard')
getAdminDashboard() {
// Accessible ONLY by authenticated users with ADMIN role
return { status: 'secure' };
}
}
```
### Additional Information
To retrieve the Decoded ID Token and role claims within a protected route, use the `` and `` parameter decorators.
```ts
import {
FirebaseProvider,
FirebaseUser,
FirebaseRolesClaims,
Roles,
} from '/nestjs-firebase-auth';
import { auth } from 'firebase-admin';
enum Roles {
ADMIN,
USER,
}
('')
export class AppController {
constructor(
private readonly firebaseProvider: FirebaseProvider,
) {}
(Roles.ADMIN, Roles.USER)
()
async mainFunction(
() user: auth.DecodedIdToken,
() claims: Roles[],
) {
return {
user,
claims
};
}
}
```
#### Difference Between `` and ``
> **Note:** Starting from version `>=1.7.x`, these two decorators are explicitly separated to avoid confusion (see [issue #11](https://github.com/Alpha018/nestjs-firebase-auth/issues/11)):
- `()` → Returns the **full decoded token** (`auth.DecodedIdToken`).
- `()` → Returns only the **custom role claims** (roles/permissions) defined for the user.
This separation ensures that developers can access both the raw Firebase user object and the role/claims information independently.
## Migration Guide (v1.9.x)
To improve semantic clarity and developer experience, direct usage of guards has been deprecated in favor of more descriptive decorators.
### 1. Replace `RolesGuard` with ``
**Deprecated:**
```ts
(FirebaseGuard) // or alone if global
(Roles.ADMIN)
```
**New Way:**
```ts
(Roles.ADMIN)
```
*Note: `` automatically applies the authentication guard.*
---
### 2. Replace `UseGuards(FirebaseGuard)` with ``
**Deprecated:**
```ts
(FirebaseGuard)
```
**New Way:**
```ts
()
```
---
### Why migrate?
- **Better readability**: `` vs `(FirebaseGuard)` clearly states intent.
- **Optimized Performance**: The new decorators use an optimized guard that prevents redundant token verification checks when composing controllers and methods.
- **Future Proofing**: Direct class exports for guards will be removed in the next major version.
## Documentation
For more detailed information, guides, and advanced examples, please visit our [Project Wiki](docs/wiki/Home.md).
## Resources
Check out a few resources that may come in handy when working with NestJS:
- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
## Stay in touch
- Author - [Tomás Alegre](https://github.com/Alpha018)
## License
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).