Sajiron
Published on Jan 31, 2025Authenticating users in a Next.js application using Firebase Admin SDK allows for secure session handling with cookies, ensuring a smooth and scalable authentication mechanism. In this guide, we’ll explore how to implement Firebase authentication using the Admin SDK for server-side session management.
What We’ll Cover:
Setting up Firebase Admin SDK in Next.js
Implementing authentication with session cookies
Handling user authentication and authorization
Best practices for securing authentication
Before implementing authentication, we need to configure Firebase Admin SDK in our Next.js project.
Install Firebase Admin SDK:
npm install firebase-admin
Configure Firebase Admin in server-app.ts
:
This file initializes the Firebase Admin SDK and connects to Firestore, Firebase Auth, and Firebase Storage.
import 'server-only';
import { initializeApp, getApps, getApp, App, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
import { getFirestore } from 'firebase-admin/firestore';
import { getStorage } from 'firebase-admin/storage';
let app: App;
if (getApps().length === 0) {
console.log('Initializing Firebase Admin App');
app = initializeApp({
credential: cert({
projectId: process.env.FIREBASE_ADMIN_PROJECT_ID,
clientEmail: process.env.FIREBASE_ADMIN_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY.replace(/\\n/g, '\n'),
}),
databaseURL: process.env.FIRESTORE_DATABASE_URL,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
});
} else {
app = getApp();
}
export const adminFirestore = getFirestore(app);
export const adminAuth = getAuth(app);
export const adminStorage = getStorage(app);
Note: Make sure to configure your Firebase Admin credentials in .env
.
2.1 Handling Authentication Requests (/auth
)
In auth.ts
, we create an endpoint to handle authentication requests by verifying Firebase tokens and setting secure session cookies.
import { cookies } from 'next/headers';
import { adminAuth } from '@/lib/firebase/server-app';
import { AUTH_TOKEN } from '@/constants/config';
import { Message } from '@/constants/messages';
export async function POST(request: Request) {
const authTokenHeader = request.headers.get('Authorization');
if (!authTokenHeader) {
return Response.json({ message: Message.AuthTokenMissing }, { status: 401 });
}
const [, token] = authTokenHeader.split('Bearer ');
const expiresIn = 7 * 24 * 60 * 60 * 1000;
return adminAuth
.createSessionCookie(token.trim(), { expiresIn })
.then(async sessionCookie => {
const requestCookies = await cookies();
requestCookies.set({
name: AUTH_TOKEN,
value: sessionCookie,
httpOnly: true,
sameSite: 'strict',
secure: true,
priority: 'high',
});
return adminAuth.verifySessionCookie(sessionCookie, true);
})
.then(claim => Response.json(claim))
.catch(() => Response.json({ message: Message.InvalidToken }, { status: 401 }));
}
Key Features:
✅ Uses Firebase ID token for authentication
✅ Creates a secure session cookie
✅ Ensures httpOnly
and secure
cookie settings
2.2 Checking Authentication Status (/auth/check
)
In auth.ts
, we create an endpoint to handle authentication requests by verifying Firebase tokens and setting secure session cookies.
import { Message } from '@/constants/messages';
import { authenticateRequest } from '@/lib/firebase/server-auth';
export async function GET() {
return authenticateRequest()
.then(claims => Response.json(claims))
.catch(() => Response.json({ message: Message.Unauthorised }, { status: 401 }));
}
Authentication Utility (server-auth.ts
):
import 'server-only';
import { cookies } from 'next/headers';
import { adminAuth } from './server-app';
import { AUTH_TOKEN } from '@/constants/config';
import { Message } from '@/constants/messages';
export const authenticateRequest = async () => {
const requestCookies = await cookies();
try {
const token = requestCookies.get(AUTH_TOKEN);
if (!token) throw new Error(Message.AuthTokenMissing);
return adminAuth.verifySessionCookie(token.value, true);
} catch (error) {
requestCookies.delete(AUTH_TOKEN);
throw error;
}
};
Key Features:
✅ Reads authentication cookies
✅ Verifies session cookies with Firebase
✅ Handles unauthorized requests
The Firebase client SDK manages user authentication in the frontend.
3.1 Initializing Firebase in client-app.ts
import { initializeApp, getApps, getApp } from 'firebase/app';
import { getAuth, inMemoryPersistence, setPersistence } from 'firebase/auth';
import firebaseConfig from './config';
const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApp();
const auth = getAuth(app);
setPersistence(auth, inMemoryPersistence);
export { auth };
Why inMemoryPersistence
?
It ensures Firebase Authentication state doesn’t persist across sessions, enhancing security.
3.2 Handling Authentication in client-auth.ts
import { signInWithEmailAndPassword as firebaseSignInWithEmailAndPassword } from 'firebase/auth';
import { auth } from './client-app';
import { API_ROUTE } from '@/constants/routes';
const sendAuthTokenForServerAuth = async (token: string) => {
const headers = new Headers();
headers.set('Authorization', `Bearer ${token}`);
return fetch(API_ROUTE.AUTH_AUTHENTICATE, {
method: 'POST',
headers,
}).then(res => res.json());
};
export const signInWithEmailAndPassword = async (email: string, password: string) => {
const userCredential = await firebaseSignInWithEmailAndPassword(auth, email, password);
const token = await userCredential.user.getIdToken();
return sendAuthTokenForServerAuth(token);
};
How It Works:
1️⃣ Firebase authenticates the user
2️⃣ Retrieves the ID token
3️⃣ Sends token to the server for validation
4️⃣ Server sets secure session cookies
Use httpOnly
cookies: Prevents XSS attacks
Use sameSite: 'strict'
: Protects against CSRF attacks
Store private keys securely: Never hardcode them in code
Restrict Firebase API keys: Ensure API keys are domain-restricted
Implementing authentication with Firebase Admin SDK in Next.js allows for secure session-based authentication using cookies. We covered:
Firebase Admin setup
Secure authentication endpoints
Client-side authentication
Best practices for security
🚀 Next Steps
Implement user roles and permissions
Add OAuth sign-in with Google, Facebook, etc.
Improve session management with automatic refresh