Adding web3 authentication with Metamask, Coinbase Wallet & WalletConnect

Wilson Tan
5 min readApr 7, 2022

These days, most of the web applications that we use integrate with social media login such as Google, Facebook, Twitter etc. No doubt, it provides a seamless user experience and removes the cumbersome task of registering a new account and verifying the account with OTP or activation link.

Social media login

However, there has been rising concerns about data privacy with some of the social media giants and people are becoming more hesitant about connecting to the web application with their social media.

In this post, we are going to talk about web3 authentication to authenticate users with Metamask, Coinbase Wallet and WalletConnect.

Pros and cons of web3 authentication

Pros:

  • Simplified UI/UX: Similar to social media logins, it provides single click login function which does not require user to enter OTP or click activation link
  • Anonymity: User can remains anonymous and there’s no need to input any user data like email to authenticate user

Cons:

  • Crypto wallet is a must: User must have crypto wallet installed. This may be an obstacle to those who do not have a crypto wallet
  • Web3 is still in infancy stage: While web3 is gaining more and more popularity, its usage is still very much at its infancy stage and thus may have more bugs

How web3 authentication works

Process flow of web3 authentication
  1. User connects to the selected crypto wallet (Metamask, Coinbase Wallet or WalletConnect)
  2. Frontend sends the public address of the selected wallet account to backend
  3. Backend creates a new user account if not exists and generates a random nonce
  4. The nonce is returned to the frontend
  5. User signs the nonce and sends the signature back to backend
  6. Backend verifies the signature and generates JWT token
  7. JWT token is passed to the frontend
  8. The JWT token is then added in the authorization header in the subsequent requests to backend

Let’s build it together

In this section, I have built a demo application with MongoDB as database, backend using Golang (Echo framework) and frontend using React.js (Next.js framework).

Backend

On the backend, we will be adding two routes:

  1. /v1/generate-nonce: To generate nonce
  2. /v1/verify-signature: To verify signature and generate JWT token
Router for web3 authentication

In the handler to generate nonce, it will first accept the public address of the account passed from frontend. We then creates a new user account (if not exists) and generates a random nonce and store in to the user record in database. The nonce is then passed to frontend.

As for the handler to verify signature, we are taking in the public address and the signature that is signed cryptographically with the crypto wallet. We first retrieve the user’s nonce by the public address and verify the signature. Once verified, a JWT token is generated and passed to frontend.

Web3 authentication handler

Frontend

For the frontend to connect to the Ethereum network, we need to first create an account in Infura and create a new project. We will then need to copy the project ID or the endpoints to connect to Infura.

Infura project

In this project we are using web3-react package to integrate with different crypto wallets as per listed. If you wish to integrate with more crypto wallets, feel free to go to the GitHub page to add on other crypto wallets.

Let’s add all the required dependencies

yarn add web3 @web3-react/core @web3-react/injected-connector @web3-react/walletconnect-connector @web3-react/walletlink-connector

Next, we can build some helper functions to instantiate different wallet connectors. This is where we connect to the Infura endpoints. Notice the activateInjectedProvider function below. The injected connector can be used for both Metamask wallet and Coinbase Wallet. Hence, the activateInjectedProvider function is used to select the provider (in this case Metamask) when using the injected connector in order to prevent double prompting of Metamask and Coinbase Wallet at the same time to users.

wallet connector helper functions

Once the helper functions are ready, we can start building the UI interface. Here, we have a simplistic login form with 3 separate buttons for each crypto wallet that we are using.

Simplistic login form with different crypto wallet

With the login UI in mind, we can start building the interface by first wrapping the application in Web3ReactProvider in order to use the web3 react functions.

index.js

In line 21, we have created a common function to activate the connectors which we have instantiated and imported from the helper file earlier on (which you can see in line 103, 112, 119). Upon activation, we will be able to get the public address of the connected crypto wallet.

With the address, we then start calling authenticateWallet function in line 41 to pass the public address to backend in order to obtain the nonce. Upon getting nonce, we then trigger the sign request in line 50–54 which you will see the following popup request (for Metamask).

Metamask sign request

After signing the request, we forward the signature together with the address to backend to retrieve the JWT token. User will then be authenticated in the subsequent requests with the token injected in the authorization header.

We’ve come to an end for this article. What we have explored so far is an alternative way to authenticate user using user’s crypto wallet without data privacy concern as opposed to the social media login. It also removes the need to register an account and activate the account by means of OTP or activation link.

However, there are still shortcomings with web3 authentication. As majority of the internet users do not own a crypto wallet, it may hinder users from using your website. Nevertheless, web3 is gaining traction these days and may become very popular in the days to come.

Feel free to take a look at the source code in web3-authentication directory in the link below. Cheers!

Source: https://github.com/wilsontwm/web3-learning

--

--