Hi everyone. My name is Paul Bouchon and I recently joined the MetaMask team.
MetaMask and most other tools that provide access to Ethereum-enabled environments do so automatically and without user consent. This exposes users of such environments to fingerprinting attacks since untrusted websites can check for a provider object and reliably identify Ethereum-enabled clients.
This proposal outlines a new dapp initialization strategy in which websites request access to an Ethereum provider API instead of relying on its preexistence in a given environment. Feedback welcome and encouraged!
Since @bitpshr didn’t introduce himself, I’ll just briefly share that he’s one of the newest members of the MetaMask team, has been doing some great work on it, and has begun driving our privacy-centric opt-in provider effort with this spec!
MetaMask hopes to develop its future behavior based on this proposal, so please consider it seriously!
These are all desktop web-centric examples – does some of this differ in a mobile webview context? (I don’t think it does for embedded webviews, and “native” clients would be … totally different, potentially, but I thought I’d ask).
This concerns web3 only – do you think guidance / best practices on showing different addresses for different apps or other “auto address creation / switching” should be included in this proposal, or handled elsewhere?
Because without address switching, we’re still doing 100% correlation of activities between dapps on accounts.
Thanks @bitpshr - have shared with the Status team.
I’m not sure there is a big difference for us currently, as we use embedded webviews when navigating to DApps - we just care that those DApps can easily identify which provider is being used and use that for some UI info/education.
Thanks @boris, and great question about web vs. other platforms. This proposal intentionally omits platform-specific details like messaging protocols, and instead chooses only to detail a high-level strategy that can be applied agnostically of platform or available APIs. For example, a web3 environment built on a mobile platform without a DOM wouldn’t use postMessage but should still follow the strategy outlined in this proposal to provide the same parameterized, user-approved web3 access. I updated the proposal to explicitly state that it’s intended to be applied across platforms and that any code is example code.
@andytudhope thanks for the feedback. I agree that address creation / switching and anything beyond user-approved web3 access is important but outside the scope of this specific proposal. This proposal is meant to serve a single purpose: to provide user-approved, parameterized web3 access in web3-enabled environments. With this proposal in place, other features can be built on top of it, such as requesting specific account types, accounts with specific balances, etc.
This proposal, as-is, assumes that there is only one wallet listening on the window. If opt-in web3 access indeed becomes the new standard, then there must be a way for the dapp to specify which wallet the request is intended for.
Otherwise, you could get multiple wallets prompting sign-in.
Have you considered adding an identifier to the request, which would specify the intended wallet?
A discovery request type, which would send out a command to see which wallets, if any, are listening on the window, may be beneficial in some cases as well.
Interesting thought @cfly. While I think it’s slightly contrived to think that multiple wallets would be listening on a given page in a given environment, I do think this case should be gracefully handled. For example, it’s possible that a dapp browser could support the WebExtensions API and a user could have MetaMask installed. In this case (albeit slightly unrealistic) both the dapp browser environment and MetaMask would respond to a request for the web3 API.
Proposal updated, good catch!
As for a discovery API, I’m not sure we could provide this in a way that doesn’t still leave users susceptible to fingerprinting.
If there were a discovery API, this proposal would lose some of its privacy benefits.
That said, this proposal is open-ended, and a client-preference parameter could easily be added later.
If multiple wallets were listening at once in the meantime, I think it’s nice that the user would get total control of which one they used to provide accounts with, already mitigating the “multiple colliding web3 extensions” problem.
Good point about the discovery API. In my mind, the API would only disclose whether or not a user has a wallet type installed, but that’s enough to be a cause for concern. However, the discovery API idea was just an afterthought.
Mainly, I am trying to avoid 2+ sign-in windows popping up in a world of multiple web3-enabled browser extensions.
Example:
A dapp wants to add a Login with MetaMask as well as a Login with WalletB button.
The issue is resolved as long as a wallet can filter out requests using an id.
I’m wondering if it’d be worthwhile to pass the id back in the wallet’s response message as well. That way, if two requests are sent out, you know which wallet is responding. This could be excluded if you want dapps to rely on the injected provider to know who they’re talking to (e.g. web3.currentProvider.isMetaMask).
@cfly I added the id property to the response, I think it makes sense given the use cases discussed. Thanks again for identifying the multiple-wallet case!
Another privacy enabling feature that would be cool would be that when the dapp asks the provider for the user’s address, the provider returns a randomly generated 20-byte number. The provider remembers this for the session and returns the same one each time. Anytime the dapp makes a request of the provider, the provider will search and replace that 20-byte number with the user’s actual address before submitting to the blockchain or returning a result to the dapp.
This would allow users to use dapps without giving up their actual address to the dapp.
sounds like a good idea, but in practice, the address will be detectable through transaction/message being signed.
Also if the provider replace the number with the actual address for every web3 call, you would just need a contract with a public method that return the msg.sender to get back the actual address. If it does not replace the number, then you forbid the dapp to actually get info about that address.
Hmm, good point that a dapp could get around this by creating a contract that returns the address encrypted, and the website has the decryption key. Then MetaMask wouldn’t know it needs to swap anything out, and thus return the address to the dapp.
After more discussion on the EIP pull request and valid points by @MicahZoltu and @Arachnid, this proposal shifted from defining an abstract platform-agnostic protocol to defining a concrete DOM-specific protocol for user-approved web3 access. All dapp browsers that currently expose web3 also expose a DOM, so it makes sense to make an immediately-actionable EIP to standardize existing DOM-specific implementations using uniform APIs.
Agree that having an approval process will greatly help with privacy and, i believe it helps security in the long run. Since attacker can easily find out account balances and token holdings by simply having account address, if the web application use the account address together with many other information available at the time of loading web app on browser, it will make it much easier for attacker to collect large amount of accounts and scan to find accounts valuable and vulnerable to exploit.
Since this adds a handshake, have you considered adding API versioning information exchange at the time? In that we can allow future development to make use of it.