Sometimes, with more extensive apps and more logic, like managing custom information about users, etc., there is a need to implement user verification on the app's backend side. The Minter Dapp doesn't require the backend verification to work. It uses a public blockchain, and the user signs every transaction, but still, it is good to know how to extend it.
Elven Tools Dapp is an excellent base for building more complicated stuff on it. It uses the NextJS framework, so you also have a free backend setup. Here are basic steps on how you could verify the user on the backend side of your dapp:
useLogin()
hook. You can do this by passing additional parameter: useLogin({ token: 'someTokenHashHere' })
. It can be a randomly generated hash or some other solution for that.There are three important things here:
The public key can be fetched using the user's address and sdk-core methods. You can do this like that:
import { UserPublicKey } from '@multiversx/sdk-wallet/out/userKeys';
import { UserVerifier } from "@multiversx/sdk-wallet";
(...)
const pubKey = new UserPublicKey(address.pubkey());
const verifier = new UserVerifier(pubKey);
The message is more complicated than just the custom token. We would need to prepare the message like that:
const msg = 'erdUserAddressHere' + 'yourCustomTokenHere' + JSON.stringify({});
Then you would need to prepare the Signature instance:
import { Signature } from '@multiversx/sdk-core/out/signature';
(...)
const signature = new Signature(Buffer.from(msg, 'hex'));
And finally, you can verify it on the backend side (sdk-core is TS/JS library):
import { SignableMessage } from "@multiversx/sdk-core";
(...)
const signMessage = new SignableMessage({
address: address,
message: Buffer.from(message),
signature: signature,
});
verifier.verify(signMessage);
You would also need to handle the expiration for the JWT token. The expiry for the dapp login is already handled by Elven Tools Dapp.
import { Address, SignableMessage } from "@multiversx/sdk-core";
import { Signature } from '@multiversx/sdk-core/out/signature';
import { UserPublicKey } from '@multiversx/sdk-wallet/out/userKeys';
import { UserVerifier } from "@multiversx/sdk-wallet";
function verifySignedMessage(message: string, sig: string, wallet: string) {
try {
const address = new Address(wallet);
const pubKey = new UserPublicKey(address.pubkey());
const verifier = new UserVerifier(pubKey);
const signature = new Signature(Buffer.from(sig, "hex"));
const signMessage = new SignableMessage({
address: address,
message: Buffer.from(message),
signature: signature,
});
return verifier.verify(signMessage);
} catch(e) {
console.log('error: ', e);
return false;
}
}
// message format: address + loginToken (random phrase or smth.) + payload data, here empty
const msg =
"erd1...." +
"someHashTokenHere" +
JSON.stringify({});
console.log(
verifySignedMessage(
msg,
"signature_hash_here",
"erd1...."
)
);
Also please check the quick walkthrough video:
You will find the full working example in the repository prepared by @borispoehland. Check it out: elven-tools-dapp-with-auth. Be aware that the repository can be outdated.