NFTマーケットプレイス「FanTop」のフロントエンドについて「Web3におけるユーザー認証」
NFTマーケットプレイスであるFanTopでは、パブリックチェーンのFlowを採用しており、一般的なフロント開発に加えてブロックチェーンの性質を考慮した開発が必要となります。今回は、そのようなFanTopのフロント開発全般の概要と認証周り等について解説します。本記事では特に「Web3におけるユーザー認証」に関して取り上げています。
登壇者紹介
安村 亮祐
新卒入社2年目。1年目は、FanTopのフロントエンドの開発に携わる。現在はバックエンドと管理画面の開発に従事し、幅広い分野に挑戦・勉強中。
Web3とは
Web3とはどういうものか、Web2.0と比較しながら説明します。Web2.0というのはSNSの台頭によって、双方向性コミュニケーションが実現した時代だと言われています。しかし、この背景にはTwitterやFacebookといった巨大企業の存在があり、それら企業によるユーザー情報の一元管理によって成り立っている状態です。これはセキュリティの問題であったり、管理者に権力が集中してしまうといった問題が注目されています。これらのことから、Web2.0は中央集権的であると言われています。
そのWeb2.0のアンチテーゼとして生まれた概念がWeb3です。根底にある考え方として、データの主権をユーザーのものにしていこうといったものがあります。特徴としては以下の3点が挙げられます。
- ブロックチェーンによるデータ管理によって誰でもデータを参照できる
- 公開鍵暗号方式によって保有者が自分自身のデータを管理できる
- 管理者が介在せず、ユーザーが直接取引できる
こういった中で、Web3は非中央集権的であると言われています。
Web3における認証方式について
Web3では認証方式についても違いがあります。Web2.0におけるユーザー認証は、一般的にユーザーしか知り得ない情報(ID/パスワードなど)をサーバーに送信して、サーバー側で照合することによって認証を行っています。Web3においては、ユーザーしか持っていない秘密鍵でメッセージを署名して、その署名をブロックチェーン側で検証することによってユーザー認証を行います。
このようにWeb3では秘密鍵を保有していること = アカウントを保有していることの証明になる、といった大きな違いがあります。続いて、その大切な秘密鍵の管理方式について説明します。
主に3つの方式があります。
- Non-Custodial(非管理)
- Custodial(管理)
- Mixed-Custodial(混合管理)
Non-Custodial(非管理)タイプは秘密鍵の所有や管理をユーザー自身で行う方式になります。メリットは、ユーザー自身が保有しているすべての資産をコントロールする権限を持っていることです。しかし、その鍵を紛失してしまった場合、その資産にアクセスできなくなるデメリットがあります。
Custodial(管理)タイプは秘密鍵の所有や管理をウォレットプロバイダー(外部のサーバー)で管理する方式です。メリットは鍵の管理を考えなくても良い点です。しかし、ハッキングなどによって鍵が流出してしまうと、自分の資産に他人がアクセスできてしまうといったデメリットが存在します。
そしてBloctoではMixed-Custodial(混合管理)を採用しています。これはデフォルトではウォレットプロバイダーによって鍵を管理しているのですが、ユーザーのブロックチェーン・ウォレットの理解度や知識に応じて、ユーザー自身の管理に切り替えられるタイプとなります。FanTopはBloctoのウォレットプロバイダーによる管理を採用しています。理由としては一般ユーザーの方に秘密鍵を管理してもらうのが、サービス運用していく中で難しく、利便性を優先させた結果となっています。
FanTopのユーザー認証について
上記右の図がその概要、流れです。大まかな流れとしては、以下のようになります。
- ブラウザとBloctoの間で署名を作成する
- 署名をバックエンド・サーバーに送信する
- バックエンドとFlowの間で署名の検証を行う
- 署名を行った人がFlowのアカウント所有者であると確認できたらFanTopのユーザー認証が完了する
詳細な流れは次のようになります。
ブラウザとBloctoの間で署名を作成する
まずFCL(Flow Client Library)の初期設定を行います。FlowやBloctoはテストネット(開発者用の環境)と、メインネット(本番環境)が用意されており、FCLの初期化時にどちらを利用するか設定します。アクセスモードでは、ブロックチェーンにアクセスするためのノードのAPIを指定します。Challenge Handshakeでは、FCLで使用するウォレットサービス(今回はBlocto)を指定します。
続いてBloctoでのユーザー認証についてです。まずFCLを用いてBloctoウォレットを呼び出します。呼び出し方は上記画像の中央に書いてあるFCLの authenticate
関数を実行することによって、左下の図にあるようなiframe内にウォレットを表示できます。このウォレットの中でユーザーはメールアドレスを入力し、そのメールアドレス宛に届いた認証コードを入力することでBloctoの認証が完了します。最後にFanTopとの連携を承認すれば、Blocto側からブラウザ側にユーザー情報が返ってきます。
Bloctoから受け取った情報を各ドメインのlocalStorageに保存しています。具体的にはFanTop側のストレージにはFlowのアドレスを保管します。Blocto側にはJWT文字列を保管します。このJWTを用いて、今後のBloctoとの通信を行います。
署名をバックエンド・サーバーに送信する
続いてユーザーの秘密鍵によるメッセージ署名処理です。まず左下のコードにあるように、Flowのアドレスやリクエストタイムスタンプを含んだメッセージを作成し、そのメッセージをFCLの signUserMessage
関数に引数を与えて実行します。
そうするとウォレットが表示されて、ここで署名の作成に対する承認ボタンを押します。承認ボタンを押すと、ブラウザからBlocto側へメッセージが送信され、受け取ったBlocto側ではユーザーに紐付いている秘密鍵でメッセージの署名を作成します。続いて、作成された署名をブラウザが受け取り、バックエンド・サーバーへ送信します。この時には、署名を作成するのに使用したメッセージもバックエンド側に送信します。
バックエンドとFlowの間で署名の検証を行う
最後に公開鍵による署名の復号とFanTopのユーザ認証を行います。先ほどブラウザから受け取った署名とメッセージを、次はFlowへ送信します。署名を受け取ったFlow側では、ユーザーに紐付いている公開鍵で署名を復号化して検証を行います。検証によって、署名を行った人がFlowのアカウントアドレスの持ち主であるか分かります。この結果をバックエンド側に返却します。
署名を行った人がFlowのアカウント所有者であると確認できたらFanTopのユーザー認証が完了する
バックエンドは検証結果を受け取り、Flowのアドレスとユーザー情報の紐付けを確認します。Flowのアドレスの持ち主が署名した人であると分かった場合、そのアドレスに紐付いているユーザーの持ち主についても署名者であると分かりますので、これをもってFanTopのユーザー認証が完了するという流れになります。
これがFanTopの認証の流れになりますが、この流れは冒頭で説明したWeb3におけるユーザー認証の流れと一致するものになります。
今後の課題
質疑応答
ブロックチェーン基盤を扱う開発はテストが難しい印象がありますが、開発中はどのようにFlowと連携させていますか?
開発中はテストネットと呼ばれる開発者向けの環境を使ってテストを行っています。また、Flowエミュレータと呼ばれるローカルでの開発環境が提供されており、これらを使ってテストを行っています。
OAuthの導入にOSSなどは導入しなかったのでしょうか?
Web3の認証はWeb2.0のものとは考え方が異なります。Web2.0の場合にはTwitterやFacebook、Googleなどにアカウントを持っていれば、それぞれのサービスを利用してOAuthが利用できます。Web3の場合は認証(厳密には認証ではないですが)する先がブロックチェーンになります。そして、間をつなぐ役割としてのウォレットがあり、その中にブロックチェーンの中身を書き換えるための秘密鍵が保持されています。そのウォレットと接続する形になります。
今回の場合では、ユーザ自身はブロックチェーンとのやりとりに必要な秘密鍵を持っていませんので、まずBloctoと接続するためにメール認証を行っています。とはいえ、基本的に秘密鍵による署名が重要になります。