@my-f-startup/firebase-auth-express
v0.1.0
Published
Express middleware and guards for Firebase Authentication.
Maintainers
Readme
firebase-auth-express
Zero-trust Firebase Authentication middleware for Express.js.
Express middleware and guards for Firebase Authentication. Validates ID tokens, exposes the authenticated user context to handlers, and enforces role-based access control. Includes unit, integration (in-memory), and E2E tests with Firebase Auth emulator via Testcontainers.
Why this exists
Firebase Authentication provides secure identity tokens, but most Express applications end up repeating the same boilerplate in every route:
- Extracting
Authorization: Bearer <token> - Calling
verifyIdToken - Handling missing or invalid tokens
- Propagating
uidand token claims - Enforcing role-based access
- Mocking authentication in tests
- Integrating with the Firebase Auth emulator
This package centralizes those concerns into a single, composable, and testable authentication layer, so your handlers can focus purely on business logic.
Features
- Zero-trust authentication – Validates Firebase ID tokens on every request
- Typed identity context – Populates
req.authwithuidand token claims - Role-based authorization –
requireRoleenforces custom-claim roles - Composable guards – Clear separation between authentication and authorization
- Emulator-first testing – Unit, integration, and E2E tests using Firebase Auth emulator
Installation
npm install @my-f-startup/firebase-auth-expressQuick Start (dev)
import express from "express";
import admin from "firebase-admin";
import {
firebaseAuthMiddleware,
requireAuth,
requireRole,
} from "@my-f-startup/firebase-auth-express";
admin.initializeApp({ projectId: "demo-project" });
const app = express();
app.use(express.json());
// Global authentication middleware
app.use(firebaseAuthMiddleware());
app.get(
"/me",
requireAuth((req, res) => {
res.json({ uid: req.auth!.uid });
})
);
app.get(
"/admin",
requireRole("admin", (req, res) => {
res.json({ uid: req.auth!.uid });
})
);
app.listen(3000, () => console.log("listening on http://localhost:3000"));Mental model
This package separates authentication concerns into two layers:
1. Middleware
firebaseAuthMiddleware- Runs once per request
- Extracts and validates the Firebase ID token
- Populates
req.auth
2. Guards
requireAuthrequireRole- Applied per-route
- Enforce access rules before executing handlers
This model keeps authentication logic centralized and routes clean.
Using the Firebase Auth Emulator
When using the Firebase Auth emulator locally:
export FIREBASE_AUTH_EMULATOR_HOST=localhost:9099
export PROJECT_ID=demo-projectThe firebase-admin SDK automatically routes authentication calls to the emulator when FIREBASE_AUTH_EMULATOR_HOST is set.
Emulator image for E2E tests
The E2E suite uses the Docker image myfstartup/firebase-emulator-suite:15 via Testcontainers.
The container expects PROJECT_ID and supports mounting firebase.json and .firebaserc into /app for configuration.
API
firebaseAuthMiddleware(options?)
Factory that returns an Express middleware. It:
- Requires
Authorization: Bearer <token> - Calls
admin.auth().verifyIdToken(token) - Sets
req.auth = { uid, token } - Returns
401on missing or invalid token - Returns
500if the auth infrastructure is not initialized
You can inject a custom auth client for tests:
firebaseAuthMiddleware({
authClient: {
verifyIdToken: async (token) => ({ uid: "user-1" } as any),
},
});requireAuth(handler)
Ensures that the request is authenticated before executing the handler.
- Returns
401ifreq.authis missing
requireRole(role | roles[], handler)
Ensures the authenticated user has the required role(s), as defined in Firebase custom claims.
- Returns
401ifreq.authis missing - Returns
403if required role(s) are not present inreq.auth.token.roles
Security model
- Stateless authentication
- No sessions
- No token caching
- Every request validates its Firebase ID token
- Authorization is based exclusively on verified token claims
This design favors correctness and security over performance shortcuts.
Testing philosophy
This package treats the Firebase Auth emulator as a first-class dependency.
- Unit tests – Pure logic
- Integration tests – In-memory auth clients
- E2E tests – Real Firebase Auth emulator via Testcontainers
This ensures production-like behavior without external dependencies.
Tests
- Unit:
npm run test:unit - Integration (in-memory):
npm run test:int - E2E (Auth emulator):
npm run test:e2e - All tests:
npm test
Build & Runtime
- Dev:
npm start(tsx) - Build JS:
npm run build(outputsdist/)
Compatibility
- Node.js: >= 20
- Firebase Admin SDK:
firebase-admin
Non-goals
- User management
- Session handling
- Token refresh
- OAuth flows
This package focuses strictly on request authentication and authorization.
