server side auth token validation failed with firebase

Viewed 46

I am using firebase for user management and trying to pull data from server to client side after a successful user validation using auth token.

Actual flow is:

  • Server side will use the firebase admin sdk to pull data from db
  • Then expose the data to frontend using dedicated api endpoint

Without token based verification, its working fine. But while trying to do the validtaion before sending the

At the client side but not able to send it properly to the server side and getting the following error:

Server started on PORT 6250
TypeError: Cannot read properties of undefined (reading 'split')
    at authTokenVerify (file:///home/ubuntu/nodescaler/MyApp/src/middleware/index.js:13:47)
    at Layer.handle [as handle_request] (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/layer.js:95:5)
    at /home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/index.js:346:12)
    at next (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/index.js:280:10)
    at jsonParser (/home/ubuntu/nodescaler/MyApp/node_modules/body-parser/lib/types/json.js:110:7)
    at Layer.handle [as handle_request] (/home/ubuntu/nodescaler/MyApp/node_modules/express/lib/router/layer.js:95:5)

On the console, showing the below error message:

GET http://localhost:6250/ 500 (Internal Server Error)

Client Side Code:

  signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        // Signed in
        const user = userCredential.user;
        
        // Get the token
        auth.currentUser.getIdToken().then(token => {
          console.log(token);
          return axios.post("/", {                      /* Updated */
            headers: {
              'Authorization': `Bearer ${token}`,
              'Accept': 'application/json',
            },
          })
        })
        
        // Allow Login Code
      };

Middleware Code:

import { initializeApp, getApps, cert } from "firebase-admin/app";
import { getAuth } from "firebase-admin/auth";

const apps = getApps();

if (!apps.length) {
  initializeApp({
    credential: cert("src/configAuth/serviceAccountKey.json"),
  });
}

const authTokenVerify = (req, res, next) => {
  let tokenString = req.headers.authorization.split("Bearer ")[1]
    ? req.headers.authorization.split("Bearer ")[1]
    : null;

  console.log(tokenString)
  if (!tokenString) {
    res.status(401).send("No header provided.");
  } else if (!tokenString[1]) {
    res.status(401).send("No token provided.");
  } else {
    getAuth()
      .verifyIdToken(tokenString[1])
      .then((decodeToken) => {
        const uid = decodeToken.uid;
        console.log(uid);
        return next();
      })
      .catch((error) => {
        res.status(401).send(error);
      });
  }
};

export default authTokenVerify;

Server Side Code:

import express from "express";
import authTokenVerify from "./middleware/index.js";

const app = express(); 
app.use(express.json()); 

app.get("/", [authTokenVerify], (req, res) => {
  res.send("API is running...");
});
  • Without using authTokenVerify in the server side code, I can see the response using localhost:6200 but when using it, getting the error as mentioned above.

Seems some issue is in the middleware it self but i am not able to figure out.

  • My folder structure:

enter image description here

1 Answers

can you log the value for req.headers.authorization, I've just tested the very same flow using the exact same code you've provided but just used a hardcoded token value on the frontend instead of generating it through firebase. I'll put my bet on auth.currentUser being empty, you can also see if commenting app.use(express.json()); makes any difference.

Once the token arrived to the middleware authTokenVerify value was actually valid at that point.

getAuth()
  .verifyIdToken(tokenString[1])
  .then((decodeToken) => {
    const uid = decodeToken.uid;
    // append the uid value you've decoded to the request body
    // so you can make use of it inside your handler 
    req.body.uid = uid;
    console.log(uid);
    return next();
  })
  .catch((error) => {
    res.status(401).send(error);
  });
Related