Authentication api problem

here’s the request evm challenge code:

func GeneratePersonalSign(domain string, chainId int, address string, expirationTime string, notBefore string) (GetPersonalSignContent, error) {
	var resp GetPersonalSignContent
	url1 := "https://authapi.moralis.io/challenge/request/evm"
	address = strings.ToLower(address)

	str := fmt.Sprintf("{\"domain\":\"%s\",\"chainId\":%d,\"address\":\"%s\",\"statement\":\"Please confirm\",\"uri\":\"https://console.bytehunter.xyz/\",\"expirationTime\":\"%s\",\"notBefore\":\"%s\",\"resources\":[\"https://console.bytehunter.xyz\"],\"timeout\":120}",
		domain, chainId, address, expirationTime, notBefore)

	payload := strings.NewReader(str)
	req, errRequest := http.NewRequest("POST", url1, payload)
	if errRequest != nil {
		log.Println("error creating request", errRequest)
		return GetPersonalSignContent{}, errRequest
	}

	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("X-API-Key", lb.GetKey())

	res, errDoClient := http.DefaultClient.Do(req)
	if errDoClient != nil {
		log.Println("error", errDoClient)
		return GetPersonalSignContent{}, errDoClient
	}

	defer res.Body.Close()
	body, errReadBody := ioutil.ReadAll(res.Body)
	if errReadBody != nil {
		log.Println("error reading body: ", errReadBody)
		return GetPersonalSignContent{}, errReadBody
	}

	errUnmarshal := jsoniter.Unmarshal(body, &resp)
	if errUnmarshal != nil {
		log.Println("err unmarshal", errUnmarshal)
		return GetPersonalSignContent{}, errUnmarshal
	}

	return resp, nil
}

here’s the verify code:

func VerifySignature(message, signature string) (bool, error) {
	url1 := "https://authapi.moralis.io/challenge/verify/evm"

	str := fmt.Sprintf("{\"message\":\"%s\",\"signature\":\"%s\"}", message, signature)
	log.Println("str2", message)
	payload := strings.NewReader(str)

	req, _ := http.NewRequest("POST", url1, payload)

	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("X-API-Key", lb.GetKey())

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	//fmt.Println(res)
	fmt.Println(string(body))

	return false, nil
}

And i meet the error:{"statusCode":400,"name":"BadRequestException","message":"Unexpected token \n in JSON at position 70"}
And when i replace the \n, and i meet the other error:

{
"statusCode": 400,
"name": "Error",
"message": "Invalid message: {\"success\":false,\"state\":103,\"length\":362,\"matched\":0,\"maxMatched\":58,\"maxTreeDepth\":15,\"nodeHits\":222,\"inputLength\":362,\"subBegin\":0,\"subEnd\":362,\"subLength\":362}"
}

And I use the personal_sign to generate the signature, what should I do to solve the problem?
The photo is a comparison between the generated message and the verified message.

Hi @bafang

Is it possible to share you server and client through github? It will be easy to test it that way.

sorry, I can’t, it’s a company private project, if you need any info, just tell me

Hi @bafang

I just need the part of the backend code for starting the go server with the moralis auth functions and the part of the frontend code where you are calling the backend functions.


Before that here are few points to check

-can you also try using the below signer function to get the signature? This is what I was using in my code while testing auth API.

const signer = provider.getSigner(); // provider is defined from ethers package
const signature = await signer.signMessage(message);

-Make sure you are using the correct wallet to sign the signature. In case your wallet has multiple accounts disconnect the unused accounts.

const submit = async () => {
	if (!walletAddr.value) {
		Message.warning('please check「wallet」');
		return;
	}
	loginLoading.value = true;

	let chainIdRes = await window.ethereum.request({ method: 'eth_chainId' });
	chainIdRes = parseInt(chainIdRes.split('0x')[1], 10);
	if (!utils.MoralisSupportChainId.includes(chainIdRes)) {
		Message.warning(t('not_support_sign'));
		loginLoading.value = false;
		return;
	}
	const msg = await api.post('user/getPersonalSignContent', {
		domain: document.domain,
		chain_id: chainIdRes,
		address: walletAddr.value,
		expired_time: dayjs().add(30, 'day').toISOString(),
		not_before: dayjs().toISOString(),
	});
	const provider = new ethers.BrowserProvider(window.ethereum);
	const signer = await provider.getSigner(); // provider is defined from ethers package
	const signRes = await signer.signMessage(msg.message);

	console.log('signres', signRes);
	api
		.post('user/login', {
			wallet_addr: walletAddr.value,
			time_zone: dayjs.tz.guess(),
			language: store.lang,
			signature: signRes,
			message: msg.message,
		})
};

This is the frontend code where i call the backend functions, and the backend code use the Go and the frame is GoFrame. So the backend code for starting the go server is standard GoFrame router.

As per the code logic it looks correct. I dont see anything that would have caused the error.:thinking:

have you testing again after updating the signer?

yeah ,sure, but it still happen the error:{“statusCode”:400,“name”:“BadRequestException”,“message”:“Unexpected token \n in JSON at position 70”}

could you give me some correct params to let me use the request endpoint and verify endpoint correctly?

Here is an example of correct params data which I tested with.

let time = new Date();
let expTime = new Date(time.getTime() + 10*60000);
time = time.toISOString();
expTime = expTime.toISOString()

let data = {
          "domain": "localhost",
          "chainId": 1,
          "address": "0x....", // your address
          "statement": "Please confirm",
          "uri": "http://localhost:5500/",
          "expirationTime": expTime,
          "notBefore": time,
          "resources": ["https://docs.moralis.io/"],
          "timeout": 60 
					};

And what are the params to use verify endpoint?

This one. resultMessage is the json response received from request endpoint.

const signer = provider.getSigner();
const signature = await signer.signMessage(resultMessage.message);

let data = {
          "message": resultMessage.message,
	  "signature": signature,
	};

Do you ever use Go to call the both endpoint?

Does golang has a way to use json directly? I am new to golang so not sure about this. If there is a different way to post json to a http request you can try using it.

No, I haven’t tried with go. However it is just an API call so it should work like any other API calls.

{"id":"9jnKcQWNq1HEB87vJ",
"domain":"localhost",
"chainId":1,"address":"0x3f53893bdd70220F167f920a519de830BF2A3A84","statement":"Please confirm",
"uri":"https://console.bytehunter.xyz/",
"expirationTime":"2023-09-28T02:23:56.920Z",
"notBefore":"2023-08-29T02:23:56.920Z",
"resources["https://console.bytehunter.xyz"],
"version":"1",
"nonce":"wO4UkQPyiVpNjp9D1",
"profileId":"0x24e536ef34a6d6d2a88d6c65dcc2543a2b1bc2d3b6fe910ba406ae70a8975fc3"}

Does it mean verify success?

Yes, the is the object which is returned after success. :grinning_face_with_smiling_eyes:

How did you fix it?

I just change the way of params, I use json.marshal instead of fmt.spintf, so i solve the problem, so How do I know if the validation was successful, by obtaining a certain parameter?

Just through the API response status code. You will only get that once the message signature verification is success.

The profile Id which you see in the response is the unique id generated for the wallet. So it will remain same for your wallet address all the time.