apeescape2.com
  • メイン
  • バックエンド
  • 革新
  • Kpiと分析
  • リモートの台頭
バックエンド

ブロックチェーンでワンクリックログイン:MetaMaskチュートリアル

オンラインユーザーは ますます耐性 従来の電子メール/パスワード登録プロセスに。 Facebook、Google、またはGitHubを介したワンクリックのソーシャルログイン機能が、はるかに望ましい代替手段であることが判明しました。ただし、トレードオフが伴います。

ソーシャルメディアログイン統合の長所:

  • 面倒なフォーム入力はもう必要ありません。
  • さらに別のユーザー名とパスワードのペアを覚えておく必要はありません。
  • プロセス全体は、数分ではなく数秒かかります。

ソーシャルメディアログイン統合の短所:



  • ユーザーの情報は外部プロバイダーから読み込まれるため、プロバイダーがこのすべての個人データをどのように使用するかについて、プライバシーに関する大きな懸念が生じます。たとえば、執筆時点で、Facebookは直面しています データプライバシーの問題 。

この記事では、新しいログイン方法を紹介します ブロックチェーン開発 :ワンクリックで暗号的に安全なログインフロー MetaMask拡張機能 、すべてのデータは独自のバックエンドに保存されます。これを「MetaMaskでログイン」と呼びます。

千の言葉に値する写真です。これから作成するログインフローのデモを次に示します。

MetaMaskログインデモを示すアニメーション。

いいね?始めましょう!

ワンクリックログインフローにメタマスクを使用する方法

基本的な考え方は、秘密鍵を使用してデータに署名することで、アカウントの所有権を暗号的に簡単に証明できるということです。バックエンドによって生成された正確なデータに署名することができた場合、バックエンドはあなたをそのパブリックアドレスの所有者と見なします。したがって、ユーザーのパブリックアドレスを識別子として使用して、メッセージ署名ベースの認証メカニズムを構築できます。

はっきりしない場合は、少しずつ説明しますので、大丈夫です。

  • MetaMaskブラウザ拡張機能
  • ログインフローの仕組み
  • ログインフローが機能する理由
  • 一緒に作りましょう
  • 今日は本番環境に対応しています
  • モバイルの欠点

に接続されているツールを使用している間、注意してください イーサリアム ブロックチェーン(MetaMask、Ethereumパブリックアドレス)の場合、このログインプロセスは実際にはブロックチェーンを必要としません。暗号化機能のみが必要です。そうは言っても、MetaMaskは そのような人気のある拡張機能 、今はこのログインフローを紹介する良い機会のようです。

MetaMaskブラウザ拡張機能

MetaMaskが何であるかをすでに知っている場合は、このセクションをスキップしてください。

MetaMask はブラウザプラグインであり、 MetaMaskChrome拡張機能 または Firefoxアドオン 。コアでは、イーサリアムウォレットとして機能します。インストールすることで、イーサリアムまたはトークンの送受信を開始できる一意のイーサリアムパブリックアドレスにアクセスできるようになります。

しかし、MetaMaskはイーサリアムウォレット以上のことをします。ブラウザ拡張機能として、閲覧している現在のウェブページとやり取りできます。これは、と呼ばれるJavaScriptライブラリを挿入することによって行われます。 web3.js あなたが訪問するすべてのウェブページで。注入されると、web3オブジェクトはwindow.web3を介して利用可能になりますこのウェブサイトのJavaScriptコードで。このオブジェクトがどのように見えるかを確認するには、window.web3と入力するだけです。 MetaMaskがインストールされている場合は、ChromeまたはFirefoxDevToolsコンソールで。

Web3.jsは、イーサリアムブロックチェーンへのJavaScriptインターフェイスです。次の機能があります。

  • チェーンの最新のブロックを取得します(web3.eth.getBlockNumber)
  • MetaMaskで現在アクティブなアカウントを確認してください(web3.eth.coinbase)
  • 任意のアカウントの残高を取得します(web3.eth.getBalance)
  • トランザクションの送信(web3.eth.sendTransaction)
  • 現在のアカウントの秘密鍵でメッセージに署名します(web3.personal.sign)
  • …そして はるかに

MetaMaskがインストールされている場合、フロントエンドコードはこれらすべての機能にアクセスできます。 ブロックチェーンと相互作用する 。という dapps または DApps (分散型アプリの場合-スタイルが「ĐApps」の場合もあります)。

DApp開発に関連: タイムロックウォレット:イーサリアムスマートコントラクトの概要

web3.jsのほとんどの関数は読み取り関数(ブロックの取得、バランスの取得など)であり、web3すぐに応答します。ただし、一部の関数(web3.eth.sendTransactionやweb3.personal.signなど)では、秘密鍵を使用して一部のデータに署名するために現在のアカウントが必要です。これらの関数は、MetaMaskをトリガーして確認画面を表示し、ユーザーが自分が何に署名しているかを知っていることを再確認します。

これにMetaMaskを使用する方法を見てみましょう。簡単なテストを行うには、DevToolsコンソールに次の行を貼り付けます。

web3.personal.sign(web3.fromUtf8('Hello from ApeeScape!'), web3.eth.coinbase, console.log);

このコマンドの意味:コインベースアカウント(つまり、現在のアカウント)を使用して、utf8からhexに変換されたメッセージに署名し、コールバックとして署名を出力します。 MetaMaskポップアップが表示され、署名すると、署名されたメッセージが印刷されます。

MetaMask確認ポップアップ

web3.personal.signを使用しますログインフローで。

このセクションに関する最後の注意:MetaMaskは現在のブラウザーにweb3.jsを挿入しますが、実際には、web3.jsを挿入する他のスタンドアロンブラウザーもあります。 靄 、 例えば。しかし、私の意見では、MetaMaskは今日、通常のユーザーがdappsを探索するための最高のUXと最も簡単な移行を提供します。

Visual StudioiOSアプリのチュートリアル

ログインフローの仕組み

から始めましょう どうやって 。ザ・ どうやって 安全だと納得していただけるといいのですが、 なぜ 部分的に短い。

概要で述べたように、ブロックチェーンについては忘れます。従来のWeb2.0クライアントサーバーRESTfulアーキテクチャがあります。フロントエンドWebページにアクセスするすべてのユーザーにMetaMaskがインストールされていることを前提としています。この仮定の下で、パスワードなしの暗号的に安全なログインフローがどのように機能するかを示します。

ステップ1:ユーザーモデルを変更する(バックエンド)

まず第一に、私たちのUserモデルには、2つの新しい必須フィールドが必要です:publicAddressおよびnonce。さらに、publicAddress一意である必要があります。通常のusername、email、およびpasswordを維持できますフィールド(特に、MetaMaskログインを電子メール/パスワードログインと並行して実装する場合)。ただし、これらはオプションです。

publicAddressのように、サインアッププロセスもわずかに異なります。ユーザーがMetaMaskログインを使用する場合は、サインアップ時に必須フィールドになります。ユーザーがpublicAddressを入力する必要はありませんのでご安心ください。 web3.eth.coinbaseを介してフェッチできるため、手動で取得できます。

ステップ2:ノンスを生成する(バックエンド)

データベース内のユーザーごとに、nonceでランダムな文字列を生成しますフィールド。たとえば、nonce大きなランダムな整数にすることができます。

ステップ3:ユーザーがノンスを取得する(フロントエンド)

フロントエンドJavaScriptコードでは、MetaMaskが存在すると仮定して、window.web3にアクセスできます。したがって、web3.eth.coinbaseと呼ぶことができます。現在のMetaMaskアカウントのパブリックアドレスを取得します。

ユーザーがログインボタンをクリックすると、バックエンドに対してAPI呼び出しが発生し、パブリックアドレスに関連付けられているナンスが取得されます。フィルタパラメータを持つルートのようなものGET /api/users?publicAddress=${publicAddress}する必要があります。もちろん、これは認証されていないAPI呼び出しであるため、このルート上の公開情報(nonceを含む)のみを表示するようにバックエンドを構成する必要があります。

前のリクエストで結果が返されない場合は、現在のパブリックアドレスがまだ登録されていないことを意味します。最初にPOST /usersを介して新しいアカウントを作成し、publicAddressを渡す必要があります。リクエスト本文で。一方、結果がある場合は、そのnonceを保存します。

ステップ4:ユーザーがノンスに署名する(フロントエンド)

フロントエンドがnonceを受信すると前のAPI呼び出しの応答で、次のコードを実行します。

web3.personal.sign(nonce, web3.eth.coinbase, callback);

これにより、MetaMaskは、メッセージに署名するための確認ポップアップを表示するように求められます。ナンスはこのポップアップに表示されるため、ユーザーは自分が悪意のあるデータに署名していないことがわかります。

彼女または彼がそれを受け入れると、コールバック関数は、引数として署名されたメッセージ(signatureと呼ばれる)を使用して呼び出されます。次に、フロントエンドはPOST /api/authenticationに対して別のAPI呼び出しを行い、両方のsignatureを含む本体を渡します。およびpublicAddress。

ステップ5:署名の検証(バックエンド)

バックエンドがPOST /api/authenticationを受信したときリクエストの場合、最初にpublicAddressに対応するデータベース内のユーザーをフェッチします。リクエスト本文に記載されています。特に、関連するナンスをフェッチします。

ナンス、パブリックアドレス、および署名があれば、バックエンドは次のことができます。 暗号的に検証する ナンスがユーザーによって正しく署名されていること。この場合、ユーザーはパブリックアドレスの所有権を証明しており、認証されていると見なすことができます。その後、JWTまたはセッション識別子をフロントエンドに返すことができます。

ステップ6:ノンスを変更する(バックエンド)

ユーザーが同じ署名で再度ログインするのを防ぐために(侵害された場合に備えて)、同じユーザーが次にログインしたいときに、新しいナンスに署名する必要があることを確認します。これは、別のランダムなnonceを生成することによって実現されます。このユーザーのために、それをデータベースに永続化します。

そして、あなたは行き​​ます! これが、ノンス署名のパスワードなしのログインフローを管理する方法です。

ログインフローが機能する理由

定義上、認証は実際にはアカウントの所有権の証明にすぎません。パブリックアドレスを使用してアカウントを一意に識別する場合、アカウントを所有していることを証明するのは暗号的に簡単です。

ハッカーが特定のメッセージとその署名(実際の秘密鍵ではない)を入手するのを防ぐために、署名するメッセージを次のように強制します。

  1. バックエンドによって提供され、
  2. 定期的に変更

説明では、ログインが成功するたびに変更しましたが、タイムスタンプベースのメカニズムも想像できます。

MetaMaskログインフローの6つのステップの概要。

一緒に作りましょう

このセクションでは、上記の6つの手順を1つずつ説明します。このログインフローを最初から構築する方法、またはあまり労力をかけずに既存のバックエンドに統合する方法のコードスニペットをいくつか示します。

この記事の目的のために、小さなデモアプリを作成しました。私が使用しているスタックは次のとおりです。

  • Node.js、Express、およびSQLite(Sequelize ORM経由)を使用して、バックエンドにRESTfulAPIを実装します。認証が成功するとJWTを返します。
  • フロントエンドでシングルページアプリケーションを反応させます。

私はできるだけ少ないライブラリを使用しようとしています。コードが十分に単純で、他の技術スタックに簡単に移植できることを願っています。

プロジェクト全体はで見ることができます このGitHubリポジトリ 。デモがホストされています ここに 。

ステップ1:ユーザーモデルを変更する(バックエンド)

2つのフィールドが必要です:publicAddressおよびnonce。 nonceを初期化しますランダムな大きな数として。この番号は、ログインが成功するたびに変更する必要があります。オプションのusernameも追加しましたここで、ユーザーが変更できるフィールド。

const User = sequelize.define('User', { nonce: { allowNull: false, type: Sequelize.INTEGER.UNSIGNED, defaultValue: () => Math.floor(Math.random() * 1000000) // Initialize with a random nonce }, publicAddress: { allowNull: false, type: Sequelize.STRING, unique: true, validate: { isLowercase: true } }, username: { type: Sequelize.STRING, unique: true } });

簡単にするために、publicAddressを設定します小文字のフィールド。より厳密な実装では、検証関数を追加して、ここにあるすべてのアドレスが 有効なイーサリアムアドレス 。

ステップ2:ノンスを生成する(バックエンド)

これはdefaultValue()で行われます上記のモデル定義の関数。

ステップ3:ユーザーがノンスを取得する(フロントエンド)

次のステップは、バックエンドにボイラープレートコードを追加して、UserでCRUDメソッドを処理することです。モデル。ここでは行いません。

フロントエンドコードに切り替えると、ユーザーがログインボタンをクリックすると、handleClickが表示されます。ハンドラーは次のことを行います。

class Login extends Component { handleClick = () => { // --snip-- const publicAddress = web3.eth.coinbase.toLowerCase(); // Check if user with current publicAddress is already present on back end fetch(`${process.env.REACT_APP_BACKEND_URL}/users?publicAddress=${publicAddress}`) .then(response => response.json()) // If yes, retrieve it. If no, create it. .then( users => (users.length ? users[0] : this.handleSignup(publicAddress)) ) // --snip-- }; handleSignup = publicAddress => fetch(`${process.env.REACT_APP_BACKEND_URL}/users`, { body: JSON.stringify({ publicAddress }), headers: { 'Content-Type': 'application/json' }, method: 'POST' }).then(response => response.json()); }

ここでは、web3.eth.coinbaseを使用してMetaMaskアクティブアカウントを取得しています。次に、これがpublicAddressかどうかを確認しますバックエンドにすでに存在するかどうか。ユーザーがすでに存在する場合はそれを取得するか、存在しない場合はhandleSignupに新しいアカウントを作成します。方法。

ステップ4:ユーザーがノンスに署名する(フロントエンド)

handleClickで前進しましょう方法。これで、バックエンドによって指定されたユーザーが所有されます(取得されたものであれ、新しく作成されたものであれ)。特に、nonceがありますおよびpublicAddress。これで、これに関連付けられた秘密鍵を使用してナンスに署名する準備が整いましたpublicAddress web3.personal.signを使用します。これはhandleSignMessageで行われます関数。

web3.personal.signに注意してください文字列の16進表現を最初の引数として取ります。 web3.fromUtf8を使用して、UTF-8でエンコードされた文字列を16進形式に変換する必要があります。また、ナンスのみに署名する代わりに、MetaMask確認ポップアップに表示されるため、よりユーザーフレンドリーな文に署名することにしました:I am signing my once-time nonce: ${nonce}。

class Login extends Component { handleClick = () => { // --snip-- fetch(`${process.env.REACT_APP_BACKEND_URL}/users?publicAddress=${publicAddress}`) .then(response => response.json()) // If yes, retrieve it. If no, create it. .then( users => (users.length ? users[0] : this.handleSignup(publicAddress)) ) // Popup MetaMask confirmation modal to sign message .then(this.handleSignMessage) // Send signature to back end on the /auth route .then(this.handleAuthenticate) // --snip-- }; handleSignMessage = ({ publicAddress, nonce }) => { return new Promise((resolve, reject) => web3.personal.sign( web3.fromUtf8(`I am signing my one-time nonce: ${nonce}`), publicAddress, (err, signature) => { if (err) return reject(err); return resolve({ publicAddress, signature }); } ) ); }; handleAuthenticate = ({ publicAddress, signature }) => fetch(`${process.env.REACT_APP_BACKEND_URL}/auth`, { body: JSON.stringify({ publicAddress, signature }), headers: { 'Content-Type': 'application/json' }, method: 'POST' }).then(response => response.json()); }

ユーザーがメッセージに正常に署名すると、handleAuthenticateに移動します。方法。 /authにリクエストを送信するだけですバックエンドでルーティングし、publicAddressを送信します同様にsignatureユーザーが署名したばかりのメッセージの。

ステップ5:署名の検証(バックエンド)

これは少し複雑な部分です。バックエンドは/authでリクエストを受信しますpublicAddressを含むルートおよびsignatureであり、これがpublicAddressかどうかを確認する必要があります正しいnonceに署名しました。

最初のステップは、データベースから上記のpublicAddressを持つユーザーを取得することです。 publicAddressを定義したため、1つしかありません。データベース内の一意のフィールドとして。次に、メッセージを設定しますmsg手順4のフロントエンドとまったく同じように、このユーザーのナンスを使用して「…に署名しています」と表示されます。

次のブロックは検証そのものです。いくつかの暗号化が関係しています。冒険心があれば、もっと読むことをお勧めします 楕円曲線の署名 。

動作するハッキングされたクレジットカード番号

このブロックを要約すると、msgが与えられた場合の動作です。 (nonceを含む)およびsignature、ecrecover関数は、msgの署名に使用されるパブリックアドレスを出力します。 publicAddressと一致する場合リクエスト本文から、リクエストを行ったユーザーがpublicAddressの所有権を証明しました。認証済みと見なします。

User.findOne({ where: { publicAddress } }) // --snip-- .then(user => { const msg = `I am signing my one-time nonce: ${user.nonce}`; // We now are in possession of msg, publicAddress and signature. We // can perform an elliptic curve signature verification with ecrecover const msgBuffer = ethUtil.toBuffer(msg); const msgHash = ethUtil.hashPersonalMessage(msgBuffer); const signatureBuffer = ethUtil.toBuffer(signature); const signatureParams = ethUtil.fromRpcSig(signatureBuffer); const publicKey = ethUtil.ecrecover( msgHash, signatureParams.v, signatureParams.r, signatureParams.s ); const addressBuffer = ethUtil.publicToAddress(publicKey); const address = ethUtil.bufferToHex(addressBuffer); // The signature verification is successful if the address found with // ecrecover matches the initial publicAddress if (address.toLowerCase() === publicAddress.toLowerCase()) { return user; } else { return res .status(401) .send({ error: 'Signature verification failed' }); } })

認証が成功すると、バックエンドはJWTを生成し、それをクライアントに送り返します。これは古典的な認証スキームであり、JWTをバックエンドと統合するためのコードです あなたはリポジトリで見つけることができます 。

ステップ6:ノンスを変更する(バックエンド)

最後のステップは、セキュリティ上の理由から、ナンスを変更することです。認証が成功した後、次のコードを追加します。

// --snip-- .then(user => { user.nonce = Math.floor(Math.random() * 1000000); return user.save(); }) // --snip--

それほど難しくはありませんでしたね。繰り返しになりますが、アプリ全体がどのように接続されているか(JWT生成、CRUDルート、localStorageなど)を確認したい場合は、お気軽に GitHubリポジトリ 。

今日は本番環境に対応しています

ブロックチェーンには欠陥があり、まだ初期段階にある可能性がありますが、このログインフローを既存のWebサイトに実装する方法を十分に強調することはできません。 今日 。このログインフローがメールとパスワードの両方よりも望ましい理由のリストは次のとおりです そして ソーシャルログイン:

  • セキュリティの強化 :公開鍵暗号化による所有権の証明は、電子メール/パスワードまたはサードパーティによる所有権の証明よりも間違いなく安全です。MetaMaskは資格情報をオンラインサーバーではなくコンピューターにローカルに保存するため、攻撃が発生します。表面が小さい。
  • 簡素化されたUX :これはワンクリック(大丈夫、おそらく2クリック)のログインフローであり、パスワードを入力したり覚えたりすることなく、数秒で実行されます。
  • プライバシーの向上 :メールは不要で、サードパーティも関与していません。

もちろん、MetaMaskログインフローは、他の従来のログイン方法と並行して完全に使用できます。各アカウントとそれが保持するパブリックアドレスの間でマッピングを行う必要があります。

ただし、このログインフローはすべての人に適しているわけではありません。

  • ユーザーはMetaMaskをインストールする必要があります :このログインフローは、MetaMaskまたはweb3対応のブラウザがないと明らかに機能しません。視聴者が暗号通貨に興味がない場合は、MetaMaskのインストールを検討する可能性もわずかにあります。最近の暗号ブームで、私たちがに向かっていることを願っています Web3.0インターネット 。
  • バックエンドでいくつかの作業を行う必要があります :これまで見てきたように、このログインフローの単純なバージョンを実装するのは非常に簡単です。ただし、既存の複雑なシステムに統合するには、認証に関係するすべての領域(サインアップ、データベース、認証ルートなど)でいくつかの変更が必要です。これは、各アカウントが1つ以上のパブリックアドレスに関連付けられるため、特に当てはまります。
  • モバイルでは機能しません :これは独自のセクションに値します—読み続けてください。

モバイルの欠点

これまで見てきたように、web3このログインフローの前提条件です。デスクトップブラウザでは、MetaMaskがそれを注入します。ただし、モバイルブラウザには拡張機能がないため、このログインフローは、モバイルSafari、Chrome、またはFirefoxではそのままでは機能しません。 web3を挿入するスタンドアロンのモバイルブラウザがいくつかあります。基本的に、MetaMaskはブラウザにラップされています。この記事の執筆時点ではかなり初期段階ですが、興味がある場合は、をご覧ください。 暗号 、 状態 、および Toshi 。 「LoginwithMetaMask」は、これらのモバイルブラウザで動作します。

モバイルアプリに関しては、答えは「はい」です。ログインフローは機能しますが、準備するための多くの基礎があります。基本的に、単純なイーサリアムウォレットを自分で再構築する必要があります。これには、パブリックアドレスの生成、シードワードの回復、安全な秘密鍵の保存、およびweb3.personal.signが含まれます。と確認ポップアップ。幸いなことに、あなたを助けるためのライブラリがあります。アプリ自体が秘密鍵を保持しているため、焦点を当てるべき重要な領域は当然のことながらセキュリティです。デスクトップブラウザでは、このタスクをMetaMaskに委任しました。

したがって、簡単な答えはノーであると私は主張します。このログインフローは今日のモバイルでは機能しません。この方向に努力が注がれていますが、今日の簡単な解決策は、モバイルユーザー向けの従来のログイン方法と並行しています。

ユーザーにMetaMaskでログインさせます

この記事では、「MetaMaskを使用したログイン」と呼ばれる、サードパーティが関与しない、暗号で保護されたワンクリックのログインフローを紹介しました。バックエンドで生成されたランダムナンスのデジタル署名がアカウントの所有権を証明し、認証を提供する方法を説明しました。また、デスクトップとモバイルの両方で、従来の電子メール/パスワードまたはソーシャルログインと比較したこのログインメカニズムのトレードオフについても調査しました。

このようなログインフローのターゲットオーディエンスは今日でもまだ少ないですが、従来のログインフローと並行して、独自のWebアプリでMetaMaskを使用したログインを提供することにインスピレーションを感じている方もいらっしゃると思います。ぜひお聞かせください。もし、するなら。ご不明な点がございましたら、下のコメント欄にてお気軽にお問い合わせください。

関連: 究極のENSとĐAppチュートリアル

Hotjar:UXと変換のヒント

Uxデザイン

Hotjar:UXと変換のヒント
モバイルエクスペリエンスのためのeコマースUX

モバイルエクスペリエンスのためのeコマースUX

Uxデザイン

人気の投稿
WebRTCアプリケーションを構築する1年:スタートアップエンジニアリングの教訓
WebRTCアプリケーションを構築する1年:スタートアップエンジニアリングの教訓
Googleスプレッドシートに移行する理由
Googleスプレッドシートに移行する理由
機械学習の問題に取り組む方法
機械学習の問題に取り組む方法
JWT for RESTAPIを使用したSpringSecurity
JWT for RESTAPIを使用したSpringSecurity
感圧タッチはUIとUXにとって何を意味しますか?
感圧タッチはUIとUXにとって何を意味しますか?
 
ApeeScapeサーベイ:最近の卒業生は、学位や仕事の柔軟性を使うよりもお金に関心があります
ApeeScapeサーベイ:最近の卒業生は、学位や仕事の柔軟性を使うよりもお金に関心があります
教師あり機械学習アルゴリズムの調査
教師あり機械学習アルゴリズムの調査
ApeeScapeデザインブログカラーオブザイヤー2020
ApeeScapeデザインブログカラーオブザイヤー2020
Firebaseをサーバーレス化–モバイルおよびWebアプリケーションを簡単に
Firebaseをサーバーレス化–モバイルおよびWebアプリケーションを簡単に
マインドズアイ–データ視覚化心理学の考察
マインドズアイ–データ視覚化心理学の考察
人気の投稿
  • フォームなしのangularjs入力検証
  • ウェブアプリからモバイルアプリへ
  • c法人は、s法人よりも所有者に大きな法的保護を提供します。
  • グラフィックデザインの原則は何ですか
  • お金がかかっているクレジットカードをハッキングした
カテゴリー
製品ライフサイクル 投資家と資金調達 アジャイル 仕事の未来 ライフスタイル プロジェクト管理 財務プロセス Kpiと分析 技術 収益性と効率性

© 2021 | 全著作権所有

apeescape2.com