You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Node.js+Express结合Firebase Auth存储用户会话的通用方案及跨端会话维持咨询

Node.js + Express + Firebase Auth: Cross-Platform Session & JWT Auth Solution

Hey there! Let’s walk through a clean, scalable way to handle user authentication and sessions across your Android, iOS, and future web clients using Firebase Auth with Express. The key here is leaning into Firebase’s built-in JWT handling and Express middleware to avoid repetitive token checks, while letting Firebase manage session persistence on the client side.

Core Concept

Instead of relying on cookie-based sessions (which don’t play nice with mobile apps), we’ll use Firebase Auth’s ID Tokens as the authorization credential for every request. Firebase handles session persistence on the client automatically, so users won’t have to re-login unless they explicitly sign out. Your Express server only needs to validate these tokens reliably—no need to store sessions in MongoDB or elsewhere.

Step 1: Set Up Firebase Admin SDK

First, install the required dependencies:

npm install firebase-admin express cors

Initialize the Firebase Admin SDK in your Express app (use your service account JSON file from the Firebase Console):

const admin = require('firebase-admin');
const serviceAccount = require('./path/to/your/service-account-key.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

Step 2: Create a Reusable Auth Middleware

This is where we eliminate manual token checks—write a single middleware function that validates the ID Token from every incoming request, then attaches the user data to the request object for use in your routes.

const authMiddleware = async (req, res, next) => {
  // Extract token from the Authorization header (format: "Bearer <token>")
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Unauthorized: No token provided' });
  }

  const token = authHeader.split(' ')[1];

  try {
    // Verify the ID Token with Firebase Admin
    const decodedToken = await admin.auth().verifyIdToken(token);
    // Attach decoded user data to the request object
    req.user = decodedToken;
    next(); // Proceed to the protected route
  } catch (error) {
    return res.status(401).json({ error: 'Unauthorized: Invalid or expired token' });
  }
};

Step 3: Protect Your API Routes

Now you can use this middleware to secure any route that requires authentication—no more repeating token validation code across endpoints!

const express = require('express');
const cors = require('cors');
const app = express();

// Enable CORS (critical for web clients and mobile apps to send requests)
app.use(cors({ origin: true }));
app.use(express.json());

// Public route (no auth required)
app.get('/api/public', (req, res) => {
  res.json({ message: 'This is a public endpoint—no login needed!' });
});

// Protected route (requires valid ID Token)
app.get('/api/protected', authMiddleware, (req, res) => {
  res.json({ 
    message: `Welcome back, ${req.user.email}!`,
    userDetails: {
      uid: req.user.uid,
      email: req.user.email,
      createdAt: req.user.auth_time
    }
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Step 4: Handle Session Persistence on Clients

Firebase Auth SDKs handle session persistence out of the box for all platforms—you don’t need to build this logic yourself:

  • Android/iOS: After calling signInWithEmailAndPassword (or any sign-in method), Firebase automatically persists the user session. On app launch, use getCurrentUser() to check if a session exists. When making API requests, fetch the ID Token with user.getIdToken() and include it in the Authorization header as Bearer <token>.
  • Web: The Firebase Web SDK similarly persists sessions using local storage or secure cookies. Use firebase.auth().currentUser.getIdToken() to get the token and attach it to your API requests.

Optional: Optimize with Token Caching

If you want to reduce repeated calls to Firebase’s token verification API, you can cache valid tokens (since ID Tokens are valid for 1 hour). Use a library like lru-cache to store decoded tokens until they expire:

npm install lru-cache

Update the middleware to use caching:

const LRU = require('lru-cache');
// Cache up to 1000 tokens, expire after 55 minutes (tokens expire after 60)
const tokenCache = new LRU({ max: 1000, ttl: 55 * 60 * 1000 });

const authMiddleware = async (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Unauthorized: No token provided' });
  }

  const token = authHeader.split(' ')[1];

  // Check cache first to avoid redundant Firebase API calls
  const cachedUser = tokenCache.get(token);
  if (cachedUser) {
    req.user = cachedUser;
    return next();
  }

  try {
    const decodedToken = await admin.auth().verifyIdToken(token);
    tokenCache.set(token, decodedToken);
    req.user = decodedToken;
    next();
  } catch (error) {
    return res.status(401).json({ error: 'Unauthorized: Invalid or expired token' });
  }
};

Key Notes

  • Token Refresh: Firebase client SDKs automatically refresh ID Tokens before they expire. If your server returns a 401, the client should trigger a token refresh and retry the request.
  • No Server-Side Session Storage: Since JWTs are self-contained, you don’t need to store sessions in MongoDB or any database. Firebase handles all session state on the client.
  • Cross-Platform Consistency: This approach works identically for Android, iOS, and web—no platform-specific auth logic needed on the server.

内容的提问来源于stack exchange,提问作者Nikola-Milovic

火山引擎 最新活动