Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firebase ID token has invalid signature #184

Closed
trieulh-ict opened this issue May 18, 2021 · 13 comments
Closed

Firebase ID token has invalid signature #184

trieulh-ict opened this issue May 18, 2021 · 13 comments
Labels
needs info/repro Needs more info or a reproduction from the reporter

Comments

@trieulh-ict
Copy link

trieulh-ict commented May 18, 2021

Describe the bug
After i logged in using email and password method, I got this error for every pages using withAuthUser.

Unhandled Runtime Error
Error: Received 500 response from login API endpoint: {"error":{"code":"auth/argument-error","message":"Firebase ID token has invalid signature. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token."}}

Call Stack
eval
node_modules/next-firebase-auth/build/index.browser.js (1:7863)
Generator.next
<anonymous>
asyncGeneratorStep
node_modules/@babel/runtime/helpers/asyncToGenerator.js (3:0)
_next
node_modules/@babel/runtime/helpers/asyncToGenerator.js (25:0)

Do you guys have any ideas how to get rid of this issue? I run on localhost. Thanks a lot.

Version
Version: 0.13.1

Additional context
My source code:

/api/login.js

import { setAuthCookies } from "next-firebase-auth";
import initAuth from "../../lib/initAuth";

initAuth();

const handler = async (req, res) => {
  try {
    await setAuthCookies(req, res);
  } catch (error) {
    return res.status(500).json({ error: error });
  }
  return res.status(200).json({ success: true });
};

export default handler;

index.js

export const getServerSideProps = wrapper.getServerSideProps(
  async ({ store }) => {
    store.dispatch(getBoards());
    return {
      props: {},
    };
  }
);

const Home = () => {
  const { boards } = useSelector((state) => state.board);
  return <BoardList items={boards} />;
};

export default withAuthUser({
  whenUnauthedAfterInit: AuthAction.REDIRECT_TO_LOGIN,
})(Home);

/lib/initAuth.js

import { init } from "next-firebase-auth";
import ROUTES from "../src/routes";

const ROUTE_API_LOGIN = "/api/login";
const ROUTE_API_LOGOUT = "/api/logout";

const initAuth = () => {
  init({
    authPageURL: ROUTES.ROUTE_LOGIN,
    appPageURL: ROUTES.ROUTE_ROOT,
    loginAPIEndpoint: ROUTE_API_LOGIN,
    logoutAPIEndpoint: ROUTE_API_LOGOUT,
    firebaseAuthEmulatorHost: process.env.FIREBASE_AUTH_EMULATOR_HOST,
    firebaseAdminInitConfig: {
      credential: {
        projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
        clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
        privateKey: process.env.FIREBASE_PRIVATE_KEY,
      },
      databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
    },
    firebaseClientInitConfig: {
      apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
      authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
      databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
      projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    },
    cookies: {
      name: "MyBoard",
      keys: [
        process.env.COOKIE_SECRET_CURRENT,
        process.env.COOKIE_SECRET_PREVIOUS,
      ],
      httpOnly: true,
      maxAge: 12 * 60 * 60 * 24 * 1000, // twelve days
      overwrite: true,
      path: "/",
      sameSite: "strict",
      secure: false, // set this to false in local (non-HTTPS) development
      signed: true,
    },
  });
};

export default initAuth;
@kmjennison
Copy link
Contributor

[Same as discussion #182]

It's hard to tell what's going wrong here without a clear way to reproduce it, so please share more info or a reproduction, if possible.

Here are a few things that might point you in the right direction:

Hope this helps. Please follow up if you figure out what's going on.

@kmjennison kmjennison added the needs info/repro Needs more info or a reproduction from the reporter label May 18, 2021
@trieulh-ict
Copy link
Author

trieulh-ict commented May 19, 2021

[Same as discussion #182]

It's hard to tell what's going wrong here without a clear way to reproduce it, so please share more info or a reproduction, if possible.

Here are a few things that might point you in the right direction:

Hope this helps. Please follow up if you figure out what's going on.

Hi @kmjennison , i tried to print out the idToken from user.getIdToken() and used it on jwt.io, and it is still decoded.

More infor about my .env.local

NEXT_PUBLIC_FIREBASE_API_KEY = ...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN = ....firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID = ...
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET = ....appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID = ...
NEXT_PUBLIC_FIREBASE_APP_ID = ...
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID = ...
NEXT_PUBLIC_FIREBASE_DATABASE_URL = https://....firebaseio.com/

FIREBASE_AUTH_EMULATOR_HOST=localhost:3000

FIREBASE_PRIVATE_KEY ='"-----BEGIN PRIVATE KEY-----\n.......\n-----END PRIVATE KEY-----\n"'
FIREBASE_CLIENT_EMAIL = [...]@[...].iam.gserviceaccount.com

COOKIE_SECRET_CURRENT = trieulh
COOKIE_SECRET_PREVIOUS = trieulh

I also update the parser of privateKey in initAuth method

credential: {
        projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
        clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
        privateKey: process.env.FIREBASE_PRIVATE_KEY
          ? JSON.parse(process.env.FIREBASE_PRIVATE_KEY)
          : undefined,
      },

but still got the error.
Do i need any config on next.config.js?

my current package.json

  "dependencies": {
    "@material-ui/core": "^4.11.4",
    "@material-ui/icons": "^4.11.2",
    "firebase": "^8.6.1",
    "firebase-admin": "^9.8.0",
    "next": "10.2.0",
    "next-firebase-auth": "^0.13.1",
    "next-redux-wrapper": "^6.0.2",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-redux": "^7.2.4",
    "redux": "^4.1.0",
    "redux-devtools-extension": "^2.13.9",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.3.0"
  }

@kmjennison
Copy link
Contributor

No, you shouldn't need anything in next.config.js.

Please verify that the email and private key are for the same account, or try generating a new key:
https://firebase.google.com/docs/admin/setup

You might try clearing data/cookies for localhost in case you previously signed in with another Firebase account and still have auth cookies signed by another private key.

If you haven't yet, try setting up your credentials in the example app just to be sure your app code isn't a problem.

@GorvGoyl
Copy link

GorvGoyl commented May 22, 2021

I was facing the same issue and turned it happens when I add FIREBASE_AUTH_EMULATOR_HOST=localhost:9099 to the env.local file. If I remove this, id token issue is gone.
It also happens, if I add firebaseAuthEmulatorHost to initAuth but not set the env value.

Funny thing is it's not enough to properly setup local auth emulator just by adding it to env file or to the initAuth object: firebaseAuthEmulatorHost: "localhost:9099". we need to follow both steps else it'l break.

@kmjennison I feel like this can be further simplified, can't we just take the value from initAuth object (i.e. firebaseAuthEmulatorHost) only and forget the env file? that way I can put it a boolean flag in initAuth.ts if I want to enable the emulator:

if (!isProd && enableAuthEmulator) {
    authObj.firebaseAuthEmulatorHost = "localhost:9099";
  }

@kmjennison
Copy link
Contributor

kmjennison commented May 23, 2021

@GorvGoyl The rationale for the duplication is that the Firebase emulator requires the environment variable. Meanwhile, I think it's confusing/limiting for Node packages to use environment variables (and definitely confusing for packages to set them), especially when a config object already exists–which is why there's a config option for it here.

@AbdUlHamedMaree
Copy link

I was facing the same issue and turned it happens when I add FIREBASE_AUTH_EMULATOR_HOST=localhost:9099 to the env.local file. If I remove this, id token issue is gone.
It also happens, if I add firebaseAuthEmulatorHost to initAuth but not set the env value.

Funny thing is it's not enough to properly setup local auth emulator just by adding it to env file or to the initAuth object: firebaseAuthEmulatorHost: "localhost:9099". we need to follow both steps else it'l break.

@kmjennison I feel like this can be further simplified, can't we just take the value from initAuth object (i.e. firebaseAuthEmulatorHost) only and forget the env file? that way I can put it a boolean flag in initAuth.ts if I want to enable the emulator:

if (!isProd && enableAuthEmulator) {
    authObj.firebaseAuthEmulatorHost = "localhost:9099";
  }

you saved my day <3.

@maxlibin
Copy link

I still have this problem, has anyone found a way to solve it?

@fedorish
Copy link

fedorish commented Jun 27, 2021

I still have this problem, has anyone found a way to solve it?

I just solved it after a few mins of headscratching. There might be some other error for you but for me it was that I had formatted my privateKey wrong in the environment-file. . I was tricked (and I assume other will be as well) by the vercel cli upload example, i blame it on being tired.)

WRONG
FIREBASE_PRIVATE_KEY='"-----BEGIN PRIVATE KEY-----\WORDSCHARSLETTERSNUMBERCAPNOTCAPETC\n-----END PRIVATE KEY-----"'

CORRECT
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\WORDSCHARSLETTERSNUMBERCAPNOTCAPETC\n-----END PRIVATE KEY-----"

@kmjennison
Copy link
Contributor

Closing this in favor of #232, given that the problem seems to be related to private key formatting.

@brandonrisell
Copy link

I was facing the same issue and turned it happens when I add FIREBASE_AUTH_EMULATOR_HOST=localhost:9099 to the env.local file. If I remove this, id token issue is gone.
It also happens, if I add firebaseAuthEmulatorHost to initAuth but not set the env value.

Funny thing is it's not enough to properly setup local auth emulator just by adding it to env file or to the initAuth object: firebaseAuthEmulatorHost: "localhost:9099". we need to follow both steps else it'l break.

@kmjennison I feel like this can be further simplified, can't we just take the value from initAuth object (i.e. firebaseAuthEmulatorHost) only and forget the env file? that way I can put it a boolean flag in initAuth.ts if I want to enable the emulator:

if (!isProd && enableAuthEmulator) {
    authObj.firebaseAuthEmulatorHost = "localhost:9099";
  }

I've been fighting this issue all morning. Thank you so much!

@thanhtutzaw
Copy link

No, you shouldn't need anything in next.config.js.

Please verify that the email and private key are for the same account, or try generating a new key: https://firebase.google.com/docs/admin/setup

You might try clearing data/cookies for localhost in case you previously signed in with another Firebase account and still have auth cookies signed by another private key.

If you haven't yet, try setting up your credentials in the example app just to be sure your app code isn't a problem.

Here is my app and

It works in local but

didn't work in Netlify and Vercel

env.local

FIREBASE_PRIVATE_KEY='"-----BEGIN PRIVATE KEY-----\nfsdfsd \n-----END PRIVATE KEY-----\n"'

initAuth.js

privateKey: process.env.FIREBASE_PRIVATE_KEY ? JSON.parse(process.env.FIREBASE_PRIVATE_KEY) : undefined

Error Message

Screenshot (1148)

@thanhtutzaw
Copy link

thanhtutzaw commented Nov 7, 2022

Vercel

Now It works in Netlify. Didn't work In local . What a weird problem. #574 @kmjennison

@KhudhurMD
Copy link

For me, the issue was because the environment variable: FIREBASE_AUTH_EMULATOR_HOST was not available to the client (only to the server). I've added a new variable named NEXT_PUBLIC_FIREBASE_AUTH_EMULATOR_HOST with the same exact value and it worked!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs info/repro Needs more info or a reproduction from the reporter
Projects
None yet
Development

No branches or pull requests

9 participants