0

Web3js frontend with Vue, .NET Core with Nethereum at the back.

The key target for this functionality is to sign a message at the frontend, send the signature and the address to the backend to validate that he actually owns that address.

The problem is that I keep ending up with varying address results. This definitely means that some part of my code is wrong. Anyone can spot the problem? <3

For the purpose of development testing, I've added the raw message as part of the API for now.

  1. Frontend

                  // Modern dapp browsers...
                  if (window.ethereum) {
                      // Propagate Web3
                      window.web3 = new Web3(ethereum);
                      await window.ethereum.enable();
                      window.ethereum.autoRefreshOnNetworkChange = false;
    
                      // Obtain the user accounts
                      let authMsg = 'This is a Nozomi auth message';
                      let accounts = await window.web3.eth.getAccounts();
    
                      // Ensure that the user is holding the wallet/s by asking him to unlock his
                      // account with a random message.
                      // https://ethereum.stackexchange.com/questions/48489/how-to-prove-that-a-user-owns-their-public-key-for-free=
                      if (accounts != null && accounts.length > 0) {
                          // https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop
                          // await Promise.all(accounts.map(async (account) => {
                          // }));
    
                          let shaMsg = window.web3.utils.sha3(authMsg);
                          let signed = await window.web3.eth.accounts.sign(accounts[0], shaMsg,
                              function (err, sig) {
                                  console.dir("Signature: " + sig);
                                  this.$buefy.notification.open({
                                      duration: 5000,
                                      message: `There was an error signing the validation request.`,
                                      position: 'is-bottom-right',
                                      type: 'is-danger',
                                      hasIcon: true
                                  });
                              });
    
                          console.dir("User signed data: ");
                          console.dir(signed);
    
                          // Validate the signed object on server side and provide an auth
                          let result = await axios({
                              method: 'post',
                              headers: { "Content-Type": "application/json"},
                              url: '/api/auth/ethauth',
                              data: {
                                  "claimerAddress": accounts[0],
                                  "signature": signed.signature,
                                  "rawMessage": authMsg
                              }
                          }).then(function (response) {
                              console.log(response);
                          }).catch(function (error) {
                              console.log(error);
                          });
    
                          console.dir("result: " + result);
                      }
                  }
    
  2. Backend

        public bool ValidateOwner(ValidateOwnerQuery request)
        {
            // Null Checks
            var addrValidator = new AddressUtil();
            if (request == null || string.IsNullOrEmpty(request.RawMessage) || string.IsNullOrEmpty(request.Signature) 
                || addrValidator.IsAnEmptyAddress(request.ClaimerAddress)
                || !addrValidator.IsValidEthereumAddressHexFormat(request.ClaimerAddress))
                return false;
    
            // Check for validity
            var signer = new EthereumMessageSigner();
    
            var resultantAddr = signer.EncodeUTF8AndEcRecover(request.RawMessage, request.Signature);
            return !addrValidator.IsAnEmptyAddress(resultantAddr) && resultantAddr.Equals(request.ClaimerAddress);
        }
    
0

1 Answer 1

0

Instead of using the web3.eth.accounts API, use web3.eth.personal to sign the message since you're using the user's address to sign the message, not his/her private key.

MetaMask verification on a server with web3.personal.sign

Instead of

let signed = await window.web3.eth.accounts.sign(accounts[0], shaMsg,
                          function (err, sig) {
                              console.dir("Signature: " + sig);
                          });

Do

let signed = await window.web3.eth.personal.sign(authMsg, accounts[0],
                              function (err, sig) {
                                  console.dir("Signature: " + sig);
                              });

Not the answer you're looking for? Browse other questions tagged or ask your own question.