Try to authen with authData parser server failed

HI,

I tried to authen with parser-server failed.

When i send the signed message to the back-end function, which verifies and authenticates with parse-server got error:

Error: Moralis auth failed, invalid data {“code”:101,“stack”:"Error: Moralis auth failed, invalid data

const headers = {
          'X-Parse-Application-Id': process.env.NEXT_PUBLIC_MORALIS_APPLICATION_ID,
          // 'X-Parse-REST-API-Key': process.env.NEXT_PUBLIC_MORALIS_STREAM_API_KEY,
          'X-Parse-Installation-Id': installationId,
          'Content-Type': 'application/json',
        };
        await axios
          .post(
            process.env.NEXT_PUBLIC_MORALIS_SERVER_URL + '/users',
            {
              authData: {
                moralisEth: authData,
              },
            },
            {
              headers: headers,
            }
          )

My authData:

id: ‘0xbfd197550ad3d062c98f8f2df7c05039e182ecd8’,
signature: ‘0x6e91364985a6119632293c9f74dd54bebd4ff9d6d756bd485a465f82700fd7f46d6908e1060b7420fe615e3590d0aefc408456142524e59b5d3a660203c0a5281b’,
data: ‘localhost wants you to sign in with your Ethereum account:\n’ +
‘0xbfd197550AD3d062C98F8F2df7C05039e182ECd8\n’ +
‘\n’ +
‘Please sign this message to confirm your identity.\n’ +
‘\n’ +
‘URI: http://localhost:1337/server\n’ +
‘Version: 1\n’ +
‘Chain ID: 97\n’ +
‘Nonce: 94TfWSjgNu219etkd\n’ +
‘Issued At: 2023-10-17T13:10:25.411Z\n’ +
‘Expiration Time: 2023-10-17T13:25:52.037Z\n’ +
‘Not Before: 2023-10-17T13:10:52.037Z’
}

What’s wrong ?
Generate sign from message:

 let sigObj = await web3.eth.accounts.sign(message, private_key);

      return sigObj.signature;

I stuck here more one a week, help me plsss

I should use account sign or personal sign

let sigObj = await web3.eth.accounts.sign(web3.utils.utf8ToHex(message), private_key);

or

let sigObj = await web3.eth.personal.sign(web3.utils.utf8ToHex(message), fromAddress);

Hi @vampiregrodon

As per your other post everything looks ok.
Do you have your code on GitHub or is it deployed somewhere so I can test it from my end?

Yes, I can shrare to you my code here. I using NextJs

login.js

const [web3auth, setWeb3auth] = useState(null);
  const [torusPlugin, setTorusPlugin] = useState(null);
  const [provider, setProvider] = useState(null);
  const [loggedIn, setLoggedIn] = useState(false);
  useEffect(() => {
    const init = async () => {
      try {
        const web3auth = new Web3Auth({
          clientId,
          chainConfig: {
            chainNamespace: CHAIN_NAMESPACES.EIP155,
            chainId: process.env.NEXT_PUBLIC_MAIN_NET_CHAINID,
            rpcTarget: process.env.NEXT_PUBLIC_RPC_TARGET, // This is the public RPC we have added, please pass on your own endpoint while creating an app
          },
          // uiConfig refers to the whitelabeling options, which is available only on Growth Plan and above
          // Please remove this parameter if you're on the Base Plan
          uiConfig: {
            name: 'nameName',
            logoLight: process.env.NEXT_PUBLIC_URL + '/logo.png',
            logoDark: process.env.NEXT_PUBLIC_URL + '/logo.png',
            defaultLanguage: 'en',
            dark: true, // whether to enable dark mode. defaultValue: false
            loginMethodsOrder: ['apple', 'google', 'twitter'],
            loginGridCol: 1,
            primaryButton: 'socialLogin', // "externalLogin" | "socialLogin" | "emailLogin"
          },
          web3AuthNetwork: process.env.NEXT_PUBLIC_NET,
        });

        // plugins and adapters are optional and can be added as per your requirement
        // read more about plugins here: https://web3auth.io/docs/sdk/web/plugins/

        // adding torus wallet connector plugin

        const torusPlugin = new TorusWalletConnectorPlugin({
          torusWalletOpts: {},
          walletInitOptions: {
            whiteLabel: {
              theme: {isDark: true, colors: {primary: '#00a8ff'}},
              logoDark: 'https://web3auth.io/images/w3a-L-Favicon-1.svg',
              logoLight: 'https://web3auth.io/images/w3a-D-Favicon-1.svg',
            },
            useWalletConnect: true,
            enableLogging: true,
          },
        });
        setTorusPlugin(torusPlugin);
        await web3auth.addPlugin(torusPlugin);

        setWeb3auth(web3auth);
        setProvider(web3auth.provider);

        await web3auth.initModal();
        if (web3auth.connected) {
          setLoggedIn(true);
        }
      } catch (error) {
        console.error(error);
      }
    };

    init();
  }, []);
 async function getPrivateKey(provider) {
    try {
      const privateKey = await provider.request({
        method: 'eth_private_key',
      });

      return privateKey;
    } catch (error) {
      return error;
    }
  }

  async function signMessage(provider, message, private_key) {
    try {
      const web3 = new Web3(provider);
      const fromAddress = (await web3.eth.getAccounts())[0];

      // sign
      let sigObj = await web3.eth.accounts.sign(message, private_key);
      // const signedMessage = await web3.eth.sign(message, fromAddress);

      return sigObj.signature;
    } catch (error) {
      return error;
    }
  }

  async function getAccounts(provider) {
    try {
      const web3 = new Web3(provider);

      // Get user's Ethereum public address
      const address = (await web3.eth.getAccounts())[0];

      return address;
    } catch (error) {
      return error;
    }
  }
  const getUserInfo = async () => {
    if (!web3auth) {
      console.log('web3auth not initialized yet');
      return;
    }
    const user = await web3auth.getUserInfo();
    return user;
  };
  const logout1 = async () => {
    if (!web3auth) {
      uiConsole('web3auth not initialized yet');
      return;
    }
    await web3auth.logout();
    setProvider(null);
    setLoggedIn(false);
  };
  const login = async () => {
    if (!web3auth) {
      uiConsole('web3auth not initialized yet');
      return;
    }
    const web3authProvider = await web3auth.connect();
    if (web3authProvider) {
      const account = await getAccounts(web3authProvider);
      const userinfo = await getUserInfo();
      const privateKey = await getPrivateKey(web3authProvider);
      const jwt = await web3auth.authenticateUser();
      const {message} = await Moralis.Cloud.run('requestMessage', {
        address: account,
        chain: parseInt(process.env.NEXT_PUBLIC_MAIN_NET_CHAINID, 16),
        network: 'evm',
      });
      const signedMessage = await signMessage(web3authProvider, message, privateKey);

      // setLoading(true);

      const content = {
        jwt: jwt.idToken,
        uuid: '',
        signature: signedMessage,
        message: message,
        email: userinfo.email,
        verifyId: userinfo.verifyId,
      };
      axios.post(process.env.NEXT_PUBLIC_URL + '/api/serverSideCallAuth', content).then(
        async (response) => {
          if (response.data.error == 1) {
            console.log('stream', response);
          }
        },
        (error) => {
          console.log(error);
        }
      );

      console.log('address', signedMessage, account, jwt.idToken, userinfo, message);
      console.log('privateKey', privateKey);
    }
    setProvider(web3authProvider);
  };

api/serverSideCallAuth.js

import md5 from 'md5';
import clientPromise from '../../lib/mongodb';
import * as jose from 'jose';
import axios from 'axios';
import EthCrypto from 'eth-crypto';

export default async function handler(req, res) {
  const body = req.body;
  let token = req.headers.token;

  const hash = md5(JSON.stringify(body) + '|' + process.env.NEXT_PUBLIC_API_KEY);

  if (!token && token !== hash) {
    return res.status(401).json({error: 0, message: 'You are unauthorized to make this request'});
  }

  switch (req.method) {
    case 'POST':
      const idTokenLogin = body.jwt;
      const installationId = body.uuid;
      const signature = body.signature;
      const message = body.message;
      const publicEmailLogin = body.email;
      const verifyId = body.verifyId;

      const client = await clientPromise;
      const db = await client.db('parse');

      const jwksLogin = jose.createRemoteJWKSet(new URL('https://api.openlogin.com/jwks'));
      const jwtDecodedLogin = await jose.jwtVerify(idTokenLogin, jwksLogin, {
        algorithms: ['ES256'],
      });

      const addressLogin = await EthCrypto.publicKey
        .toAddress(jwtDecodedLogin.payload.wallets[0].public_key)
        .toLowerCase();

      if (
        jwtDecodedLogin.payload.email === publicEmailLogin ||
        jwtDecodedLogin.payload.verifierId === verifyId
      ) {
        const authData = {
          id: addressLogin,
          signature: signature,
          data: message,
        };

        const headers = {
          'X-Parse-Application-Id': process.env.NEXT_PUBLIC_MORALIS_APPLICATION_ID,
          // 'X-Parse-REST-API-Key': process.env.NEXT_PUBLIC_MORALIS_STREAM_API_KEY,
          'X-Parse-Installation-Id': installationId,
          'Content-Type': 'application/json',
        };
        await axios
          .post(
            process.env.NEXT_PUBLIC_MORALIS_SERVER_URL + '/users',
            {
              authData: {
                moralisEth: authData,
              },
            },
            {
              headers: headers,
            }
          )
          .then(
            async (response) => {
              const user_id = response.data.objectId;
              const acl = {
                [user_id]: {
                  w: true,
                  r: true,
                },
              };
              const query_setUser = {_id: user_id};
              await db.collection('_User').updateOne(query_setUser, {
                $set: {
                  ethAddress: addressLogin,
                  accounts: [addressLogin],
                  avatar: jwtDecodedLogin.payload.profileImage,
                  _acl: acl,
                  email:
                    jwtDecodedLogin.payload.email !== undefined
                      ? jwtDecodedLogin.payload.email
                      : jwtDecodedLogin.payload.verifierId + '@gmail.com',
                },
              });

              return res.status(200).send({
                status: 'success',
                error: 1,
                message: 'Successfully',
                data: response.data.sessionToken,
              });
            },
            (error) => {
              console.log('authent', error);
              return res.status(200).send({
                status: 'error',
                error: 0,
                message: error.code,
              });
            }
          );
      } else {
        return res.status(200).send({
          status: 'error',
          error: 0,
          message: 'Error Verification Failed',
        });
      }

      break;
    case 'GET':
      return res.status(405).send({message: 'Only POST requests allowed'});
  }
}

I am not sure if this actually returns the private key. Can you try adding any console.log to check the expected private key is returned?

I check everything is OK bro. I got private key, all data is ok

As you know, I have 2 console.log in code above.

console.log('address', signedMessage, account, jwt.idToken, userinfo, message);
console.log('privateKey', privateKey);

I tried to console.log on parse-server, i dont know why Invalid Data :frowning:

I dont know what else can cause this error. Do you know if there is some other way to sign message from web3auth without using the private key? Since private key cant be exposed to browser there should be a better way from web3auth to sign message with wallet.

I tried sign message by private key and without private key, got same error :frowning:

I sign message on Unity is OK. Just got error on web sdk
This is my function sign message on UNITY. I sign with private key

my assumption is that the way you are signing message in web is different or the correct way.

Have a look the below docs on how you can use web3auth hooks to sign a message.

Can i use “wagon” for sign message ?

What do you mean by wagon🤔

Sorry my wrong, wagmi not wagon

You can use wagmi for signing message. All our tutorials are using wagmi for wallet interactions.:grinning_face_with_smiling_eyes:

1 Like

ok thank bro. I will try it