Issues connecting a user with Web3Auth and Firebase JWT Token

I have configured the Firebase extension and would like to connect the user with their wallet using the JWT token from Firebase. I receive the wallet and a JWT token from Firebase. However, I cannot connect the user with their wallet. :cry:

Error during Web3Auth initialization or login: WalletInitializationError: Wallet is not ready yet, Please call init first

I have referred to the following repo: https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-web/sfa-web-custom-jwt-example

• SDK Version:
@web3auth/base: “^8.6.1”
@web3auth/ethereum-provider: “^8.6.1”
@web3auth/single-factor-auth: “^8.0.2”
• Platform:
• Next.js local on macOS
• Browser Console Screenshots:
consoleErrorWallet

Information (optional):
• Verifier Name: w3a-firebase-awareo
• JWKS Endpoint: https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com

  • Sample idToken (JWT):
    eyJhbGciOiJSUzI1NiIsImtpZCI6IjBjYjQyNzQyYWU1OGY0ZGE0NjdiY2RhZWE0Yjk1YTI5ZmJhMGM1ZjkiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoidGhvcmUyMDA3MDEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9maXJlYmFzZXN0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vdjAvYi9hd2FyZW8tYXV0aC1kZXYuYXBwc3BvdC5jb20vby91c2VyJTJGWVFWb1FYZ3BJUVFobXN4M3RNQ2ZmV3Y0SGEyMiUyRmF2YXRhciUyRllRVm9RWGdwSVFRaG1zeDN0TUNmZld2NEhhMjJfMTcyMTQ5OTM2MjEzOF80MDB4NDAwLndlYnA_YWx0PW1lZGlhJnRva2VuPTBhNmIzZTJhLTkwOTUtNDNiYi1hMWUzLTZlNTZiMmIyN2FkNiIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9hd2FyZW8tYXV0aC1kZXYiLCJhdWQiOiJhd2FyZW8tYXV0aC1kZXYiLCJhdXRoX3RpbWUiOjE3MjE1NjE4MzksInVzZXJfaWQiOiJZUVZvUVhncElRUWhtc3gzdE1DZmZXdjRIYTIyIiwic3ViIjoiWVFWb1FYZ3BJUVFobXN4M3RNQ2ZmV3Y0SGEyMiIsImlhdCI6MTcyMTU3MDU0NSwiZXhwIjoxNzIxNTc0MTQ1LCJlbWFpbCI6ImNhdG9wYTg3NDBAYmFjYWtpLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7ImVtYWlsIjpbImNhdG9wYTg3NDBAYmFjYWtpLmNvbSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIiwic2lnbl9pbl9zZWNvbmRfZmFjdG9yIjoicGhvbmUiLCJzZWNvbmRfZmFjdG9yX2lkZW50aWZpZXIiOiI1YzFmMGIwNy1iZjU2LTRjNzMtYmIyYS03NDAyMWNlZjY5Y2EifX0.q_igVdCxTQi3sz0dignFkCbHkXo0MiclM7jDj4HQZMWpvyOrOXpWCNnf1FZuy0wZI7IiIT112s32-In5JyYHmzeEFjy4AMg7IrPcfpOuH-DqWI3pSj2gD4uk4CkHqeACpq06Qt2j939jPr6IhAqK0V1mfVNsgYnhbVi0ZO9yeR-Xkoe93VRNkfsR1iagUpUDFHJUGgvGBz69cvyBlz-Wqr795ILkVVhICSHumQcieOpelw5D618cvIfyLV7OnrKextSNvu4EQJh9dV2Uu9jCCmg2OBiczEt2p9B00XHUJKheIob2nHUUm1ZJC1P0qEzjh61KdyCKGfy28THz7pclsg

My sample snippet:

'use client';

import { useState, useEffect } from 'react';
import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from "@web3auth/base";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { decodeToken, Web3Auth } from "@web3auth/single-factor-auth";

import Loading from "./Loading";

const verifier = "w3a-firebase-awareo";
const clientId = "xxxx_xxxxxxx";

const chainConfig = {
  chainId: "0xaa36a7",
  displayName: "Sepolia Test Network",
  chainNamespace: CHAIN_NAMESPACES.EIP155,
  tickerName: "ETH",
  ticker: "ETH",
  decimals: 18,
  rpcTarget: "https://rpc.sepolia.org/",
  blockExplorerUrl: "https://sepolia.etherscan.io/",
};

const privateKeyProvider = new EthereumPrivateKeyProvider({
  config: { chainConfig },
});

const web3authSfa = new Web3Auth({
  clientId, 
  web3AuthNetwork: WEB3AUTH_NETWORK.TESTNET, 
  usePnPKey: false, 
  privateKeyProvider,
});

type Props = {
  lng: string;
  currentUser: User | null;
  idToken: string;
}

export default function WalletComponent({ lng = "en", currentUser, idToken }: Props) {
  const [isLoggingIn, setIsLoggingIn] = useState(true); // initial auf true gesetzt
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [isWeb3AuthInitialized, setIsWeb3AuthInitialized] = useState(false);
  const [userInfo, setUserInfo] = useState(null);

  useEffect(() => {
    const init = async () => {
      try {
        await web3authSfa.init();
        setIsWeb3AuthInitialized(true);
        console.log("Web3Auth initialized");

        // login after initialization
        const idTokenResult = getIdToken();
        console.log("idTokenResult", idTokenResult);
        const { payload } = decodeToken(idTokenResult);
       //Error with connect
        await web3authSfa.connect({
          verifier,
          verifierId: (payload as any).sub,
          idToken: idTokenResult,
        });
        setIsLoggedIn(true);
        setIsLoggingIn(false);

        // Retrieve user information after successful login
        const userInfo = await web3authSfa.getUserInfo();
        setUserInfo(userInfo);
        uiConsole(userInfo);

      } catch (error) {
        setIsLoggingIn(false);
        console.error("Error during Web3Auth initialization or login:", error);
      }
    };

    init();
  }, []);

  const getIdToken = () => {
    return idToken;
  };

  function uiConsole(...args: any[]): void {
    const el = document.querySelector("#console>p");
    if (el) {
      el.innerHTML = JSON.stringify(args || {}, null, 2);
    }
  }

  const getUserInfo = async () => {
    if (!web3authSfa) {
      uiConsole("Web3Auth Single Factor Auth SDK not initialized yet");
      return;
    }
    try {
      const userInfo = await web3authSfa.getUserInfo();
      uiConsole(userInfo);
    } catch (err) {
      console.error("Error getting user info:", err);
      uiConsole("Error getting user info:", err);
    }
  };

  return (
    <div className="bg-white md:w-[700px] rounded-xl p-8">
      <h1 className="mt-20 mb-8 text-3xl font-bold text-center text-gray-800">
        {currentUser?.displayName} - Your Wallet
      </h1>
      {isLoggingIn ? <Loading /> : (
        <>
          <button onClick={getUserInfo} className="card">
            Get User Info
          </button>
          <div id="console" style={{ whiteSpace: "pre-line" }}>
            <p style={{ whiteSpace: "pre-line" }}></p>
          </div>
        </>
      )}
      <div className="flex-container"></div>
    </div>
  );
}

Hey @thomas2, welcome onboard. Thanks for sharing the details, and code snippet. I’ll try check it out and update you.

1 Like

Hey @thomas2 can you check if you are using strict mode in react? You can check that in index.tsx file. If you are using strict mode, please remove that and try if that solves the issue.

Also, if that doesn’t solve the issue, can you please print the web3AuthSfa.status before web3AuthSfa.connect. From code it seems fine.

Hi @Ayush,

Thank you for your response.

I have disabled strictMode, but the issue persists.

web3AuthSfa.connect: ready
Now, I encounter another error: Error when cleaning token verifier teal-w3a-firebase-awareo not found for account id: xxxx_xxxxx

It’s confusing because my old script with this custom verifier works well. I’m currently attempting to update using your libraries with Next.js 14.04 and the following Web3Auth packages:

The Firebase extension is functioning smoothly. Could the issue potentially be related to the Firebase extension and the new mpc-core-kit 2.3.3?

Thanks for assisting with this matter.

Old Snippet with firebase-extension and mpc-core-kit 1.3.0: working fine

import { useState, useEffect } from 'react';
import { Web3Auth } from "@web3auth/single-factor-auth";
import { parseToken } from "@web3auth/mpc-core-kit";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { CHAIN_NAMESPACES } from "@web3auth/base";
import Web3 from 'web3';

let web3authSfaInstance = null;

export const useBlockchainConnection = (idToken) => {
  const [web3, setWeb3] = useState(null);
  const [ethPrivateKey, setEthPrivateKey] = useState(null);
  const [walletInfo, setWalletInfo] = useState({ address: '', balance: '' });
  const [isLoading, setIsLoading] = useState(true);
  const [isInitialized, setIsInitialized] = useState(false);
  const [isWeb3AuthReady, setIsWeb3AuthReady] = useState(false);

  // Erster useEffect für die Initialisierung von Web3Auth
  useEffect(() => {
    if (!web3authSfaInstance) {
      web3authSfaInstance = new Web3Auth({
        clientId: "xxxx__xxxxxxxx",
        web3AuthNetwork: "sapphire_devnet",
        usePnPKey: false,
      });

      const chainConfig = {
        chainNamespace: CHAIN_NAMESPACES.EIP155,
        chainId: "0xaa36a7",
        rpcTarget: "https://rpc.sepolia.org/",
        displayName: "Sepolia-Testnetzwerk",
        blockExplorerUrl: "https://sepolia.etherscan.io/",
        ticker: "ETH",
        tickerName: "ETH",
      };

      const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } });

      web3authSfaInstance.init(privateKeyProvider)
        .then(() => {
          setIsWeb3AuthReady(true);
        })
        .catch((error) => {
          console.error("Error initializing Web3Auth:", error);
        });
    }
  }, []);

  // Zweiter useEffect für die Verbindungsherstellung
  useEffect(() => {
    const connectToBlockchain = async () => {
      if (!idToken || !isWeb3AuthReady || isInitialized) {
        setIsLoading(false);
        return;
      }

      try {
        const { sub } = parseToken(idToken);
        const web3authSfaprovider = await web3authSfaInstance.connect({
          verifier: "w3a-firebase-awareo",
          verifierId: sub,
          idToken: idToken,
        });
        
        if (!web3authSfaprovider) {
          throw new Error("Web3Auth-Provider can't connect");
        }

        const privateKey = await web3authSfaprovider.request({ method: "eth_private_key" });
        setEthPrivateKey(privateKey);

        const web3Instance = new Web3(web3authSfaInstance.provider);
        setWeb3(web3Instance);

        const address = (await web3Instance.eth.getAccounts())[0];
        fetchWalletInfo(web3Instance, address);

        setIsInitialized(true);
      } catch (error) {
        console.error("Error connect Blockchain:", error);
      } finally {
        setIsLoading(false);
      }
    };

    connectToBlockchain();
  }, [idToken, isWeb3AuthReady, isInitialized]);

  const fetchWalletInfo = async (web3Instance, address) => {
    if (!web3Instance || !address) {
      console.warn("Web3-Instanz or Wallet-Adresse not defined");
      return;
    }
    try {
      const balance = await web3Instance.utils.fromWei(
        await web3Instance.eth.getBalance(address),
        "ether"
      );
      setWalletInfo({ address, balance });
    } catch (error) {
      console.error("Error with get Wallet-Infos", error);
    }
  };

  return { web3, ethPrivateKey, walletInfo, isLoading, fetchWalletInfo };
};

export default useBlockchainConnection;

For the other error yo have encountered, I’ll need few details. Can you share the information of the verifier you are using? The error says teal-w3a-firebase-awareo not found and in code, you have passed the w3a-firebase-awareo. Can you check and update on which network teal-w3a-firebase-awareo is hosted? Is it on sapphire_devnet?

That’s a good question.

I am only using the verifier w3a-firebase-awareo. I did not create a verifier like teal-w3a-firebase-awareo on the sapphire_devnet. The configuration is as per my code. When I search through my project, I find “teal” mentioned in toruslabs.js as a network identifier, but I did not configure any vendor or explicitly write “teal-” in my code.

The Firebase extension is functioning smoothly with mpc-core-kit 1.3.0 - but I have trouble with firebase-extension and mpc-core-kit 2.3.3 in this example . Could the issue potentially be related to the Firebase extension and the mpc-core-kit 2.3.3?

I’ll try to run our quick start, I don’t think that should be issue. Can you share your client id?

Many thanks. Here is the clientID: BHN7UXB30MXu__i6t1IKghr0vOD_snlZHseQUuo3TLMK_1yAA1FQjwcTPBQa0wrb08rcWolCLNFNduMmBIWbgqg

Hello , any updates? I have the same issue :smiling_face_with_tear:

Steps to reproduce:

  1. clone your example from: web3auth-core-kit-examples/single-factor-auth-web/sfa-web-custom-jwt-example at main · Web3Auth/web3auth-core-kit-examples · GitHub
  2. move login functionality into useEffect near init, so user will autologin after initing:

image

result:

Hey, can you please confirm if the strict mode is enabled in your react app? Can you disable the strict mode and try if it solves the issue?

Hello sir, I tried on your example, and that didn’t helped

Okay, I’ll try moving the login function into userEffect. I’ll let you know by today EOD.

@valeriia.danyliuk why are you setting the setIsLoggingIn(true) after init? It should be only used web3authSfa.connect has been successfully executed.

This should solve your issue. We do persist session, so it’s important to check whether the user is already logged in or not, and then do connect.

 if (web3authSfa.status === ADAPTER_EVENTS.CONNECTED) {
          setIsLoggedIn(true);
        } else {
          const idTokenResult = await getIdToken();
          const { payload } = decodeToken(idTokenResult);
          await web3authSfa.connect({
            verifier,
            verifierId: (payload as any).sub,
            idToken: idTokenResult,
          });
          setIsLoggedIn(true);
        }

Thank you for the guidance; it looks helpful! I’ll test it out tomorrow and let you know how it goes.