Web3ログイン実装で挫折した
この記事について
Ethers.jsの署名と検証を利用してOpenSeaのようなユーザー認証を実装しようとしましたが初心者の私には難しくて途中で挫折してしまいました。まったくもって不完全ですが、この記事では現状の実装方法についてまとめようと思います。この記事の関連リソースを下記に示します。
やりたいこと
Ethers.jsの署名と検証を利用したユーザー認証を実装するにあたり、下記の記事を参考にしました。
上記の記事を参考にして設計したユーザーの認証シーケンスを下記に示します。
コーディングの準備
ターミナルで下記のコマンドを実行してコーディングの準備をします。
npx create-next-app --typescript --use-npm web3login
cd web3login
npm install --save ethers iron-session
mkdir lib
touch lib/with-session.ts
touch pages/signin.tsx
touch pages/api/message.ts
touch pages/api/signin.ts
touch .env
コーディング
エディタで下記のファイルを開いて内容を入力します。
lib/with-session.ts
pages/signin.tsx
pages/api/message.ts
pages/api/signin.ts
.env
動作確認
下記のコマンドを実行してサーバーを起動します。
npm run dev
ブラウザで http://localhost:3000/signin にアクセスします。
Signinボタンをクリックします。
MetaMaskの署名の要求が表示されたら署名ボタンをクリックします。
Sign in completedとメッセージが表示されることを確認します。
参考画像
アクセス直後
Signinボタン押下直後
署名ボタン押下直後
おわりに
この記事で紹介した方法は下記の点で不完全です。
- ユーザーがページをリロードした時のことが考慮されていない
- ユーザーがMetaMaskを操作して接続解除した時のことが考慮されていない
- ユーザーがMetaMaskを操作して別のアカウントに切り替えた時のことが考慮されていない
Alchemy公式ドキュメントのIntegrating Your Smart Contract with the Frontendによると、リロードについては下記のように取扱いが可能です。
useEffect(() => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const [address] = provider.send('eth_accounts', [])
console.log({address})
}, [])
また、MetaMask操作による接続解除や別アカウントへの切り替えについては下記のように取扱いが可能です。
useEffect(() => {
const onAccountsChanged = ([address]) => {
console.log({address})
}
window.ethereum.on('accountsChanged', onAccountsChanged)
return () => {
window.ethereum.removeListener('accountsChanged', onAccountsChanged)
}
}, [])
リロードなどのイベントを取扱う方法はわかったのですが、各種イベントが発生した時にどのように動作するべきかのベストプラクティスについては何が正解かがわかりませんでした。自己流の方法を考案して実装することも不可能ではないですがセキュリティホールを作ってしまう恐れがあるので可能な限り自己流は避けてベストプラクティスに従いたい所です。
そんなことを色々と考えているうちに面倒になって挫折してしまいました(笑)
通常のユーザー認証であればAuth0などの確立されたIDaaSを利用することができます。Web3でのユーザー認証についてもweb3authなどがあり、少し触ってみただけでしくみは全然理解できていないですが有望な感じがしました。このようなサービスが増えることを期待します。
何か参考になる情報をご存じの方がいましたらご指導のコメントをいただければ幸いです。
Discussion