Signing messages with MetaMask
Sign in with MetaMask is a great way to authenticate users on your site. It's also a great way to sign messages with a user's Ethereum address. This is useful for a variety of reasons, including:
- Proving ownership of an Ethereum address
- Proving ownership of an Ethereum address to a smart contract
- Proving ownership of an Ethereum address to a smart contract and executing a function call on that smart contract in the same transaction
Besides the above use cases, signing messages with a user's Ethereum address is a great way to authenticate users to your site without sending them through an OAuth flow. This is because signing a message with a user's Ethereum address proves that the user is in control of the private key associated with the public address, without sending any transactions.
So a good dApp will always provide the ability to authenticate users using Sign In with MetaMask
.
Signing messages with MetaMask
To sign a message with MetaMask, we will using some utils method from ethers.js
.
Import ethers.js
import { ethers } from "ethers";
Setup a provider and signer.
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send("eth_requestAccounts", []);
Sign a message
const signer = provider.getSigner();
const message = "Hello World";
const signature = await signer.signMessage(message);
Verify a signature
const recoveredAddress = ethers.utils.verifyMessage(message, signature);
Verify message using remote API
Usually when implementing a authentication method, we need to send the signature to a remote API to verify it. After that, the server will return a JWT token that we can use to authenticate the user on subsequent requests.
We provide a remote API endpoint to simulate this process.
https://functions.video2.trade/api/metamask/signIn
This endpoint takes the following request body:
export interface Message {
message: string;
signature: string;
address: string;
}
The endpoint will verify the signature and return a JWT token if the signature is valid.
export interface Token {
accessToken: string;
}
Example
The following example shows how to sign a message with MetaMask and verify it using the remote API.