0

I'm a novice here and this is my first question. I'm making an API with Typescript and Express that connects to my local DB and want to authenticate the user with firebase. I read the instructions on their docs and think I'm doing what they asked, setting up the service account and admin SDK.

When I console the token on client and server side, I get the same token, but I keep getting this error:

FirebaseAuthError: Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
    at FirebaseAuthError.FirebaseError [as constructor] (C:\coisas\nlw\node\node_modules\firebase-admin\lib\utils\error.js:44:28)
    at FirebaseAuthError.PrefixedFirebaseError [as constructor] (C:\coisas\nlw\node\node_modules\firebase-admin\lib\utils\error.js:90:28)
    at new FirebaseAuthError (C:\coisas\nlw\node\node_modules\firebase-admin\lib\utils\error.js:149:16)
    at C:\coisas\nlw\node\node_modules\firebase-admin\lib\auth\token-verifier.js:138:23
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  errorInfo: {
    code: 'auth/argument-error',
    message: 'Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.'
  },
  codePrefix: 'auth'

Here's what I'm trying to do client side (mixin for a Vue app):

fetchPedidos: async function (parametros) {
  return axios.get(parametros.endpoint, {
    params: {
      filter: parâmetros.filter || "",
        page: parâmetros.page || 0,
        size: parâmetros.size || 25,
        sort: parâmetros.sort || "",
        codCliente: parametros.codCliente || "",
        codPedido: parametros.codPedido || "",
        token: await firebase.auth().currentUser.getIdToken(true)
      }
    });
} (the then and catch are elsewere on the app)

And Here is the server side, a middleware function for express:

export async function firebase_auth(req: Request, res: Response, next: NextFunction) {
  const token = JSON.stringify(req.query.token)
  console.log(token);
  try {
    const _decodedToken = await admin.auth().verifyIdToken(token);
    return next();
  } catch (error) {
    console.log(error);
    return res.status(401).json({
      mensagem: "Erro na autenticação do usuário",
      erro: error
    });
  }
}

Like I said before, that console.log on the server-side prints the same token that leaves the site, but the admin sdk throws this error saying it can't decode. What am I doing wrong here?

I've looked some similar questions but couldn't get it to work.

*Edit: The console.log(req.query): Powershell print

As for the parser, I have this in my server.ts:

app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

*Edit 2: Turns out I shouldn't be using stringify for this, and instead just specify that I want the token as a string in the function call. Thanks @Dharmaraj and @samthecodingman for clarifying this for me!

  • What error are you getting? – Dharmaraj Jul 21 '21 at 15:13
  • Sorry, forgot to put the error print in the post, but I've made an edit – MatheusFongaro Jul 21 '21 at 15:21
  • 1
    Instead of `const token = JSON.stringify(req.query.token)` can you try `const {token} = req.query` and then pass it into verifyIdToken? – Dharmaraj Jul 21 '21 at 15:23
  • But then I get a typescript error saying that I cant pass Undefined to verifyIdToken() – MatheusFongaro Jul 21 '21 at 15:25
  • I agree with Dharmaraj, as token is a JWT string similar to `abcde.abcde.abcde`, calling `JSON.stringify` will incorrectly add quotes around it which will lead to the error. – samthecodingman Jul 21 '21 at 15:26
  • Try this `verifyIdToken(token as string)`. Now typescript will treat it as string. Before that line check if token is defined. `if (!token) return res.sendStatus(401)` – Dharmaraj Jul 21 '21 at 15:27
  • Also, if TypeScript complains about a type, it's best to add some code to handle those incorrect types rather than simply ignoring them. One such way would be to send back a `400 Bad Request` using `if (token === undefined) { res.status(400).send("token is missing"); return; }` or `if (typeof token !== "string") { res.status(400).send("token is malformed"); return; }` – samthecodingman Jul 21 '21 at 15:30
  • Didn't know about the `as string` part, guess I'm just noob at typescript still. – MatheusFongaro Jul 21 '21 at 15:33
  • So is the issue resolved? – Dharmaraj Jul 21 '21 at 15:34
  • 1
    It was the stringify, removed it and now it works, thanks to you and @Dharmaraj! – MatheusFongaro Jul 21 '21 at 15:34

1 Answers1

0

Turns out I shouldn't be using stringify for this, and instead just specify that I want the token as a string in the function call. Thanks @Dharmaraj and @samthecodingman for clarifying this for me!