Is there a way to sign into a website via "sign a message" in Algorand?

Hi,

Many DApp websites run with Eth is using Metamask’s “web3.personal.sign” method to ask user to sign a special message to verify the account, then grants user to sign into their websites. After doing some search, it seems the AlgoSigner current doesn’t support this, see the issue here: Add a way to sign a message without a transaction · Issue #224 · PureStake/algosigner · GitHub

I know that Algorand Wallet uses a custom Wallet Connect schema (defined a custom algo_signTxn method), and from this post:

It seems the app doesn’t support the standard personal_sign Wallet Connect method yet:
https://docs.walletconnect.com/client-api#sign-personal-message-personal_sign

So if you are developing a website that wants user to use their wallet to sign in, and neither AlgoSigner nor Algorand Wallet support it, how do you achieve such feature? Given this seems a very fundamental function, I am wondering is there something I missed?

Thank you

1 Like

At the moment, as you discovered, wallets don’t offer an arbitrary byte singing method.

They do support transaction signing and you can validate the signature against the bytes of the transaction. This is the ‘trick’ used by https://github.com/algorandfoundation/ARCs/pull/41

I think it’d be preferable to have something like you mentioned though.

@fabrice has probably thought more about this, can you offer some thoughts here as well?

Ben

What we ended up settling with on our site that is you just Connect with your wallet for “read-only” mode and to browse around. But when you need to do something “sensitive” (must require verification that the user actually owns the wallet), the workaround we came up with is to create a $0 transaction. This will still cost 0.001 ALGO, but we haven’t found any users that complain. We’re very clear that this is just to verify ownership and will not transfer any funds or grant us any permission to do anything. (In Ethereum land you can request permission to spend someone’s funds on their behalf and all kinds of scary things, so wanted to let users know none of that is going on.)

We also weren’t able to figure out how to verify the signature on a signed transaction made by Algorand Wallet or MyAlgo wallet. I found this code for verifying a signature made by the algosdk, but couldn’t figure out how to make it work for the transaction objects that the wallets require (each one needs a slightly different structure). So the workaround to the workaround was to put a UUID into the note field and then verify that the same UUID is in the actual transaction that was added to the ledger: a transaction with that UUID would be impossible to add to the ledger unless it was signed by the owner of the wallet, so I consider that as “safe” as verifying the signature.

But then we found that folks with Ledger hardware wallets couldn’t perform this transaction. It turns out that Ledger only supports a note field of up to 32-bytes, and a UUID is 36 by default. So the workaround to the workaround to the workaround was to remove the 4 dashes in the UUID to get it down to 32. :sweat_smile:

NOW the problem is that in a few cases, users have a problem going from our site, to their wallet, and back again, and have the code flow not interrupted and properly resume where they left off. On some devices (it seems to happen a lot on Android), it seems like the browser gets lost between await wallet.signTransaction() and await algoClient.sendRawTransaction(). When they come back to the browser and it attempts to execute sendRawTransaction() it freaks out and doesn’t seem to have the result of signTransaction() in a variable any more. The most frustrating part is that I can’t reproduce locally so it’s kind of impossible to debug at the moment.

Thank you @Cannikin , there are many helpful info there. I was thinking to authenticate user by sending a 0 transaction with special notes too, and asked this in another post, @fabrice reminded me the DApp case, not sure if this is helpful to you, but you can check it here:

Anyway, seems so far there is no good solution, I will consider other methods.

When check for mine I don’t pull from the pending pool (I didn’t even know there was such a thing!), I use the algosdk’s built-in method waitForConfirmation() that doesn’t return until either the transaction is confirmed, or it times out (you can tell it to wait for a number of blocks before giving up): js-algorand-sdk/wait.ts at 9dd99e96ede0bb945605425ab0a194c84ee85086 · algorand/js-algorand-sdk · GitHub