Logging in with MetaMask in a Blazor WebAssembly app
Blazor WebAssembly and the decentralized web are a great match. You can host your Blazor WebAssembly app on decentralized storage like https://siasky.net and you don't have to worry about servers or hosting costs. That's exactly what I'm doing with SkyDocs, a decentralized Google Docs alternative: https://skydocs.hns.siasky.net
Documents created in SkyDocs are also stored on Sia Skynet. You can login with any username/password combination, it will form a seed that generates a public/private keypair to communicate with the Skynet APIs.
But I also want to give users the option to login with MetaMask. It's a common option you see a lot with web3 projects and a great way to identity yourself. Logging in should not cost any money, no Ethereum gas should be used.
To communicate with the MetaMask extension from Blazor, I first created a new package, MetaMask.Blazor. It's available on NuGet and GitHub: https://github.com/michielpost/MetaMask.Blazor This package makes it easy to use the MetaMask extension, by providing C# wrappers of JavaScript functions that are needed to use MetaMask.
Login flow
- Check if the user has MetaMask installed, or show a warning that MetaMask is not installed
- Request the user to sign a string in MetaMask, this results in a hash.
- We also requests the current Ethereum address from MetaMask, this can be done without any user interaction.
- The Ethereum address + hash of the signed string are used as seed to generate a public/private keypair for Skynet.
- The address and hash are also saved in your browser's Local Storage, that's a weak spot for security, but a pro for usability. You don't have to sign the message with MetaMask every time you login.
- To increase security, the data stored to Local Storage is encrypted with the Ethereum address as key.
- When you login, your saved address from Local Storage is checked with your current MetaMask address, if they don't match, you need to sign the string with MetaMask again.