Title: The_UX_of_EIP_1102
Category: Web

Author: danfinlay
Date: 2018-07-19T20:30:27.442Z

To improve Ethereum browser security, multiple browsers are now working on implementing EIP 1102, which will no longer inject the provider API by default, but instead wait for the Dapp to request a web3 API before providing one, making web3 users undetectable to sites (including dapps!)



EIP-1102: Opt-in provider access EIPs


    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 i…
  

While this change has great privacy benefits, there are open questions about the UX of this kind of invisible API. Feature detection is impossible, and so Dapps will need to present some kind of open-ended log-in button that both tries to log on and suggests installing a web3 browser if the user doesn’t have one yet.
You can roughly see the issue in this EIP 1102 flow chart from the original metamask issue:
flow chart1546×1116 187 KB
I just wanted to open the thread here, to get our UX ring thinking about the future of log-in with privacy-centric browsers.
cc @bitpshr @ricburton @boris @beltran @andytudhope

Author: ricburton
Date: 2018-07-19T21:04:35.125Z

This is great, Dan. I think that WalletConnect could be really helpful here. Pedro Gomes is leading the project full time and I am sure he has lots to say on this. Will send this to him.
I wrote about the flow here: MetaMask & WalletConnect.js. Changing the dapp experience to protect… | by Richard Burton | Medium
092798×2068 437 KB

Author: bitpshr
Date: 2018-07-19T21:12:58.876Z

Thanks for starting this @danfinlay! Some additional thoughts:


Optionally inject web3
In addition to injecting a provider API after user approval, MetaMask also plans to conditionally inject web3 based on an optional web3 property on the provider request. This is for easier backwards compatibility: while dapps will still have to update to initiate the provider request, they won’t also have to bring in web3.js if they don’t want to.


Cache approved websites
MetaMask also plans to cache website origins that have been approved for provider access. For example, if a user visits foobar.com and approves provider access, MetaMask will remember this approval in the future and bypass user approval altogether next time the user visits foobar.com. This saved approval data can be cleared at any time.


Difficult to know dapp-level UX
EIP-1102 intentionally focuses on the protocol for requesting a provider API, not the UX around it. There’s nothing to prevent a dapp from requesting provider access immediately on page load without any user action, so it’s important for dapp developers to converge on a common UX here (like WalletConnect?) I still feel it’s inevitable that some dapps will request provider access using arbitrary UX flows. For example, what if a dapp uses a login system completely unrelated to Ethereum accounts? This type of dapp would probably request provider access immediately on load and not design it as a login button the user must click, since the dapp has an unrelated login system already in place.

Author: JaceHensley
Date: 2018-08-09T00:25:15.954Z

RE: dapp-level UX
So our flow currently allows detection of install while the user remains on our dapp’s signin page. What we do is inject an iframe that refreshes until it detects web3 (since extensions can’t inject into already loaded pages). This allows the user to come to our site without MM installed and either be instructed to install MM or continue. And the page only refreshes once the iframe has detected a web3 instance.
One way forward would be to have a timeout before switching to a different view telling the user to install a dApp browser. But there are a few problems with that, the first being users would have to wait for the timeout before being instructed to take an action, the second is what if the user just takes a little longer than the timeout to accept? This would cause the dApp to move to the “Please install a dApp Browser” step too early.
Curious if anyone has any thoughts on other ways forward that don’t cause UX regression

Author: bitpshr
Date: 2018-08-09T14:55:53.577Z

Hi @JaceHensley, thanks for sharing information about your dapp. You’re right that the UX issue of detecting and suggesting MetaMask (or some other dapp browser) is challenging due to EIP-1102. It’s an unavoidable UX issue: malicious sites currently track Ethereum users the exact same way honest dapps detect MetaMask, so to protect user privacy, dapps can’t know if MetaMask is installed.
Here’s one flow that may work:

User without MetaMask navigates to dapp
Dapp posts message requesting provider
Browser ignores message since MetaMask isn’t installed
User tries to interact with dapp
Dapp attempts to use web3 or ethereum but they aren’t defined
Dapp shows user warning: “Please use a supported browser such as MetaMask.”

The main difference between this flow and current flows is that detection and user warning are done only when the user attempts to interact with the dapp in a way that uses web3 or ethereum. If these globals aren’t defined at that time, that means the user either hasn’t approved access or isn’t in a supported browser. In either case, the dapp could show a warning message to the user (or an iframe to install MetaMask) only when it needs to use these variables instead of checking for them immediately on page load.

Author: JaceHensley
Date: 2018-08-09T16:15:46.600Z

That seems like poor UX to me. Wait for a user to try and do something and only after a user tries to interact with your dApp do you tell them they need something else. I bet that would stop people from continuing. It just adds another layer of friction to signing up for/using a dApp.
Speaking of malicious sites wouldn’t this open it up for users to constantly get asked to accept or decline a sites request to inject ethereum?

Author: bitpshr
Date: 2018-08-09T16:57:43.407Z

@JaceHensley I’m not sure if users would be more turned off by a dapp suggesting an extension be installed only when they try to interact with it (meaning they’ve seen the dapp, what it is, and chose to interact with it) as opposed to when it first loads. Both are equally as obtrusive, but the former at least allows the user to see your dapp before being asked to install new software. Still, I’m not a designer, so I probably have little value to add here. The flow above was just one example of a flow that could work, but better approaches may exist.
As for the concern of malicious sites spamming provider requests, once a user rejects access on a given site, they won’t be presented with additional approval windows unless they clear their cached approval data. This is similar to how webcam approval works in browsers today.

Author: JaceHensley
Date: 2018-08-09T17:24:51.275Z

Check out how we are handling it on bloom.co/app/signup. We help onboard users by laying out what they need to do to use our dApp. Laying everything out upfront helps reduce friction and doesn’t make the user guess what’s next.
I do like the request permission to get ethereum injected pattern. I just don’t like that there’s no way to tell if a user has installed MM.
So our flow wouldn’t ask for permission right away, we’d probably have the user click a button in the list of steps after “Install Metamask”. Something like “Allow Access To Metamask” with Allow Access underlined and acting like a button. When a user clicks that then we would send off the request.
The crucial part is knowing what step the user is on so they can be helped along the way without wasting their time

Author: JaceHensley
Date: 2018-08-09T17:35:01.762Z

The goal is mass adoption of dapps and crypto in general. Fingerprinting based on using a dapp browser would be like fingerprinting based on if the user’s browser has notification possibilities.
The real problem is exposing the user’s ETH address not that they are using Metamask or another dApp browser.

Author: bitpshr
Date: 2018-08-09T19:38:43.033Z

I totally agree that mass adoption is the goal, but a lack of user privacy and resulting phishing campaigns have been negatively effecting the community for some time. Fingerprinting based on dapp browser usage informs malicious sites that a user holds and uses Ethereum, and has been heavily used to run targeted ad and phishing campaigns, regardless of access to the provider or accounts.
I agree the UX needs to be ironed out for the case where a user has no dapp browser. The above approach is one way, but I’m sure there are others that are better. I wish I had more design experience to speak from.

Author: JaceHensley
Date: 2018-08-10T16:40:08.304Z

If UX still needs to be ironed out doesn’t that indicate that this EIP is not ready?

Author: bitpshr
Date: 2018-08-10T18:31:32.716Z

@JaceHensley The intention of EIP-1102 is to fix user privacy. While it’s an interesting challenge, how dapps adjust their individual user experiences based on this new change is completely outside the scope of the proposal. Current UX relies on objectively unsafe injection, so changing it is unavoidable.
The only issue with the UX is that dapps can no longer detect if a user has a dapp browser installed, which is the very intention of the EIP: to remove the ability to detect this information (that malicious sites have successfully used to target Ethereum users for far too long.)
We’ve already identified one UX pattern above that works, but is arguably worse than what we currently have. That’s the whole point of this thread, to collaboratively identify the best UX to accommodate a necessary and crucial programmatic privacy change.

Author: danfinlay
Date: 2018-08-13T22:30:54.446Z

JaceHensley:

wouldn’t this open it up for users to constantly get asked to accept or decline a sites request to inject ethereum?


I think this could be mitigated by including a “block future requests from this site” checkbox with the sign-in page.

Author: danfinlay
Date: 2018-08-13T22:42:22.490Z

JaceHensley:

If UX still needs to be ironed out doesn’t that indicate that this EIP is not ready?


I basically agree. We’re trying to design the correct way for a browser to work, and if there isn’t even a pleasant path for users to onboard with the given changes, it’s a strong indication that we have a ways to go.
However, Paul’s points are also important: As long as web3 browsers are a minority, and as long as they are usually MetaMask users, any detectable API surface exposes users to specific phishing attacks.
That said, I think there is a silver lining:
Our active response to that type of phishing attack seems to have resulted in a reduction of its incidence rate, so it’s possible “web3 detection attacks” are indeed not the worst kind of fingerprinting.
Also, if we aim for the long-term game, where everyone has a web3 browser, and there are many kinds of web3 browser, this kind of fingerprinting becomes less and less dangerous, again emphasizing that the account detection is potentially the worst part of this.
On the other hand
While this change requires a UX change, it doesn’t need to be awful, it just would need to embrace some different assumptions:
I think the basic flow would be something like this:

A button that says Sign in with Ethereum.
When clicking the button, on a web3 browser, the login request appears.
When clicking the button, it could change to “Install a Web3 browser to begin”. Since web3 browser users are seeing a login request, this is an appropriate moment to assume the user is not using a web3 browser within the site’s UI, educate, and suggest an install.

That all said
I do think most of the discussion so far has focused on the technical aspect, not the UX, so I’m very glad that @JaceHensley is thinking of the user and pushing back here. I think it’s a decision the ecosystem needs to make together, and stick to.
It seems like it’s pretty clear that the easiest way to improve the UX is to accept a limited fingerprinting surface, to allow sites to intelligently suggest user actions, and so the question for the community is:
Is it acceptable to provide web3 fingerprinting for the benefit of user experience?
In an ecosystem with so much working against our UX in the name of security, it might be a concession worth embracing.

Author: danfinlay
Date: 2018-08-14T00:03:47.051Z

We’ve been tossing around ideas for the UX more, and I do believe we can make the UX of 1102 pleasant.
In the next MetaMask release we’re going to include a mocked version of this user consent UI, so dapp developers can experiment with the changed onboarding flow.
We’re also going to produce an example dapp to demonstrate that we can have both perfect privacy and good user experience.  Hopefully that dapp will inspire others to further improve on the experience.
While web3 fingerprinting might not be a big deal in a perfect world where everyone is using web3 browsers, we’re a long way from that world. Maybe once every browser is adopting web3 standards, we can re-introduce some global APIs for the sake of purely improved UX, but in the meanwhile, I think it’s worthwhile for us to make a few changes to our UX assumptions for the sake of protecting our very highly targeted community.

Author: dustinvs
Date: 2018-08-14T00:18:24.632Z

Hoping you provide some facility a la my comments here:




EIP-1102: Opt-in provider access EIPs


    So, re: The UX of EIP 1102 - looking for a way to guarantee both user control of privacy and preserve the relative ease of UX available with current Metamask/web3. 
My general idea to solve this is basically to find a way to automatically push a refresh and injection of window.ethereum based on an application requesting that, upon install of Metamask, their still-open tab will be able to have a pending request of availability somehow notify the user that they’ve requested access, and then upon a…
  

If Metamask’s going to permanently move in the direction of an obfuscated request-access system, hopefully you can at least provide a way for apps to seamlessly request access pre-Metamask install and then receive a refresh with window.ethereum available when it’s granted.

Author: danfinlay
Date: 2018-08-14T16:27:54.056Z

Since WebExtensions are not able to receive messages when they are not installed, detecting the moment one is installed would probably require a sort of hack like described above:

What we do is inject an iframe that refreshes until it detects web3 (since extensions can’t inject into already loaded pages).

This could be done with an iFrame that requests a login, and wrapped into a general purpose library, enabling the UX that you’re talking about.

Author: JaceHensley
Date: 2018-08-14T17:17:24.978Z

I thought about sending a request from the iframe but I don’t like that much since the user should be in control of when that request is sent.
Really I think that a limited fingerprinting surface area is a great middle ground. For instance Brave has it’s own userAgent. I think Metamask and others could follow that. Maybe not userAgent exactly but something like that

Author: ricburton
Date: 2018-08-14T17:25:18.111Z

One quick thought: every browser (including Brave) let’s the page know that it is there.
If we let the web page know a web 3 tool is there: Is it not the same principle?
I think it is really helpful for a page to know whether the user has any of the tools necessary or not. Perhaps I am missing something

Author: ricburton
Date: 2018-08-14T17:27:48.419Z

Just saw this. Yeah I agree. I am comfortable with the middle ground of: “this is someone who has got set up on Ethereum”.
Another example: Opra browser on Android?
I just wonder if we are over-swinging from usability to privacy.
Would love to hear more about how MetaMask is thinking about it.
With that said, WalletConnect.org is opt-in with the QR code.

Author: dustinvs
Date: 2018-08-14T19:35:57.824Z

Unfortunately with the iframe approach, you lack the ability to enqueue an access request prompt before Metamask has been installed.  If you can use a cookie or localStorage entry to enqueue a request, then you don’t have to implement something like a refreshing iframe or interval retry logic which could potentially bug the user if they’re just rejecting the requests.  I think if you implement the totally opaque approach, then it’s a must to implement a way of enqueuing a request before the extension is installed.  As a general rule it’s bad practice in JS to implement polling logic instead of promises or event callbacks, this is the same principle.

Author: danfinlay
Date: 2018-08-15T21:13:11.188Z

dustinvs:

If you can use a cookie or localStorage entry to enqueue a request, then you don’t have to implement something like a refreshing iframe or interval retry logic which could potentially bug the user if they’re just rejecting the requests.


A login cookie could also be added as an extension of this proposal (or as a subsequent extension), it seems like that could be a decent post-install way to instantly log-in.
Web3 browsers could also limit this annoyance by only showing up to a single login request from a given page, so even if a page was polling the request from within an iFrame (to effectively detect the extension’s installation), the user would only be prompted once.

Author: danfinlay
Date: 2018-08-15T21:32:54.445Z

ricburton:

every browser (including Brave) let’s the page know that it is there.


This isn’t completely true. Brave provides a fingerprinting protection mode, a feature that we considered at MetaMask, but is actually impossible for extensions:
An extension’s contentscript is unable to make a synchronous query to global state (like whether or not a privacy mode is enabled) before a page loads. Chrome marked this concern a WONTFIX: https://bugs.chromium.org/p/chromium/issues/detail?id=54257
Without the option of letting a user opt into greater privacy vs not, minimizing fingerprintable surface seems to be the only option that is fully aligned with w3c’s fingerprinting guidance:
https://w3c.github.io/fingerprinting-guidance/
All that said, I do think there are pleasant design paths for this new pattern, they simply need to be explored. We shouldn’t necessarily reject this proposal just because existing patterns don’t work, we should consider whether other patterns could.
A Pleasant 1102 UX Proposal
An application following 1102 should have (1) a “Login” or “Get Started” button that triggers the 1102-specified login request.
If the user has a web3 browser, that web3 browser should (2) transition the view to the browser-provided login screen, ideally in a view that is either full screen or fully obscures the requesting website.
The website meanwhile should render (3) a view that assumes the browser is not web3 enabled, and should suggest installing one, or any other login patterns that are available. (This view is invisible to web3 browser users)
If the user approves the login, the website should immediately transition to (4) a logged in view, and the web3-browser using user should never see any assumption that they did not have a web3 enabled browser.
Extra Notes
If on view 3, the page suggests installing a browser extension (because a desktop browser is detected), the site could either recommend reloading the page after installation, or could use an iframe-polling hack to request login on a loop (this is working with a limitation of extensions)
If on view 3 the user rejected the login request, they will see the fallback login options, which makes sense and is a natural next step.
We’ll be posting wire-frames and a sample dapp to demonstrate this flow soon.

Author: JaceHensley
Date: 2018-08-15T22:37:25.275Z

That brings me back to one of my earlier points

Wait for a user to try and do something and only after a user tries to interact with your dApp do you tell them they need something else.

That’s frustrating from the users perspective. They click “Login” and then they have to go install the extension, come back, remember to refresh the page, and then click “Login” again and hope they don’t need to do anything else

Author: bitpshr
Date: 2018-08-15T22:49:32.875Z

Taking a step back, there’s one main logic path that’s made more diffuclt by the total privacy detailed in 1102: handling users who have no dapp browser installed. As many have mentioned, this is an important UX consideration, especially because it directly relates to user onboarding.
There are a few options I see:
Option 1: Total privacy
The first option is to adjust current dapp UX around web3 detection to meet the requirements set forth in EIP-1102 as written today. This option provides total user anonymity on malicious sites, but makes UX more tedious because it relies on removing the ability for honest dapps to know if a user has a dapp browser installed.
To be fair, malicious sites knowing if a user specifically has a dapp browser installed means they can reliably associate IP addresses with Ethereum usage and run targeted ads, phishing campaigns, and other attacks. If a website detects it’s running in Chrome or some other non-dapp browser, these targeted attacks aren’t possible in the same way. This makes dapp browser detection funamentally more dangerous than regular browser detection, at least for the forseeable future where no Ethereum-specific API is baked into the DOM.
Some flows that we’re mocking up on our end that may work for this option:


Full-screen login (@danfinlay’s suggestion)

Request a provider at any time (e.g. after button click)
Dapp browser shows full-screen approval view
Dapp renders non-web3 view behind approval view
After success, dapp renders web3 view
Example:
option-14840×3602 947 KB



Dynamic reminder

Request a provider on page load
On first action requiring provider, check for it
If provider undefined, inform user of approval / download requirements
Example:
option-23350×3474 1 MB



Constant reminder

Request a provider at any time (e.g. after button click)
Concurrently inform user of connection attempt / download requirements
Example:
option-33350×3602 713 KB



Timed reminder

Request a provider at any time (e.g. after button click)
Inform user of connection attempt
After timeout, inform user of approval / download requirements
Example: same as “constant reminder” above but download text only shown after timeout



Option 2: Minimally-fingerprintable API
It’s possible that total privacy shouldn’t be the end-goal of EIP-1102 and it should only serve to standardize restricted access to the provider / web3. If this looser approach is taken, dapps could still be informed if a user has no dapp browser installed or if a user rejects provider access, but dapps won’t be able to access anything beyond an error. This approach solves most UX concerns because existing flows that rely on knowledge of dapp browser installation are still possible, but has a major drawback in that it allows malicious sites to know if a certain IP address uses Ethereum.
While the original intention of the proposal was to provide complete privacy to stop the influx of targeted phishing and ad campaigns, maybe it’s sufficient to only restrict access to the provider / web3 and any useful information beyond knowing a user has a dapp browser.
Option 3: Do nothing
Another option is to maintain current behavior and continue injecting Web3 instances into every page a user navigates to. Dapps could continue to either use this environment-defined provider library or grab the provider from the Web3 instance and use it with their own library. This poses no UX issues at all since it’s the flow we have today, but also doesn’t address the major issues of 1) namespace collision from global injection, 2) the privacy issues of every site knowing about Ethereum use, or 3) every site being able to spam the user with web3 transactions.

I personally feel that we should find the best UX flow that satisfies option 1 above for the safety of Ethereum users. Any site knowing if a user is an Ethereum user (and in some cases their address) is like any site knowing the fiat bank a user may use (and in some cases their account number.) Still, I agree that current UX flows above are less than ideal (though the constant reminder as mocked up doesn’t seem too horrible), and I also don’t think a goal of total privacy should impede user adoption.

Author: danfinlay
Date: 2018-08-15T22:50:59.410Z

The wording “Login” seems like the frustrating part there. Maybe using something like “Get started” is a better UX, by better representing the app state.

Author: ricburton
Date: 2018-08-18T18:28:48.599Z

14%20PM3360×2100 947 KB
Just wanted to share some different states we have been adding for Brave, Chrome and Safari.
Helping people figure out why they need to use certain tools is a big hurdle.
I like the idea of connecting to something. Facebook Connect popularised that idea.

Author: dustinvs
Date: 2018-08-23T01:17:47.992Z

Another point of interest - maybe the level of web3 provider visibility should be a configurable option - maybe with the default being the low-fingerprint option discussed earlier?  Best of both worlds approach.

Author: danfinlay
Date: 2018-08-23T04:18:06.722Z

I agree this approach would be a best of both worlds. It may be an option for other clients, but as a browser extension, MetaMask does not have an opportunity to synchronously access global user configuration before a page loads. This may be a target for change amongst browser vendors, but is our current reality.

Author: bitpshr
Date: 2018-08-30T14:16:19.301Z

Cross-posting this here for anyone not following the technical 1102 thread (an updated 1102 proposal that should alleviate most UX concerns discussed so far ):




EIP-1102: Opt-in provider access EIPs


    After successful community iteration with additional browser teams and dapp developers alike, EIP-1102 has been formally updated to reflect the latest thinking on user-approved provider exposure: 
Browsers expose a provider populated with no accounts by default. Before initiating any RPC request that requires an account, like eth_sendTransaction, dapps must request a full provider by calling a new provider method, provider#enable. This method triggers the user interface that allows the user to a…

Author: angilly
Date: 2018-09-17T23:16:39.816Z

Hello Ethereum Friends. I’ve been lurking on this thread for a few weeks now. Solid gold. I appreciate each and every one of you.
One thing that’s been bugging me is the potential confusion between “connecting your wallet” and “logging into metamask”. As I understand it by looking at Metamask’s source code, private keys are encrypted at rest and unlocked when a user logs in w/ their password. Post EIP-1102, Metamask will still be using a password-encrypted private key store. This means that simply clicking “Connect” in the provider access request screen will not be enough to give a dapp full access to the wallet. If that’s true, I’m unsure as to how they will manage this unlocking. We’re going to have to ask users to connect their wallet, then we’re gonna have to have text on our screens saying “looks like metamask is locked! go login!”
Am I missing something here?
Thanks!

Author: danfinlay
Date: 2018-09-18T00:02:50.351Z

angilly:

Am I missing something here?


Yes, under the latest proposal, calling ethereum.connect() will prompt the user to log-in, and when that call’s promise is returned, the user’s account should be available if the user connected.
That means while today you have to say “You’re unlocked, go unlock!”, under EIP 1102, you’ll be able to display a “Log in” button, which prompts the user to select an account, (and potentially eventually other specific challenges), and then makes the resulting account available to the App.

Author: angilly
Date: 2018-09-18T01:57:57.912Z

Ok so maybe I’m conflating this eip with metamask specifics too much. In a medium post by the metamask team, the request provider access screen did not have any place to type in a password.
Is the spirit of the spec that if they want to ask for a password to unlock a locally encrypted key store, it would be done in that request provider access screen?

Author: danfinlay
Date: 2018-09-18T07:55:38.392Z

Yeah, I think the spirit is that after calling ethereum.enable(), the wallet responsibly and with little friction gets the user to a point where they’re ready to use your app. That might involve unlocking, or if already unlocked, it might just be an account selection.

Author: angilly
Date: 2018-09-18T17:34:24.945Z

Ok thanks Dan. That helps a lot.
One last thing: I’m looking at the EIP on GitHub, and you mean ethereum.enable() not ethereum.connect(), right?

Author: danfinlay
Date: 2018-09-18T19:46:44.533Z

Yes, sorry, my mistake. Correcting/editing the post.

Author: joshpitzalis
Date: 2018-10-30T05:58:59.986Z

Please point me in the right direction if this is the wrong thread for this question. I have a UX issue after making the ethereum.enable() changes. How do you get the custom image in the new popup? In the article crypto kitties has their little kitty, but in my app I’m just getting an ugly domain name string. This article https://medium.com/metamask/https-medium-com-metamask-breaking-change-injecting-web3-7722797916a8

Author: bitpshr
Date: 2018-11-06T19:52:32.684Z

Hi @joshpitzalis, apologies for letting this slip through the cracks. MetaMask’s current implementation (which is now live in v5.0.0 of the extension) uses a given dapp’s favicon as the image on the approval popup. The actual UX of the popup isn’t codified in the underlying proposal, so there’s no specific API exposed to pass custom images to the popup (at least not at this point.)

Author: joshpitzalis
Date: 2018-11-07T04:22:14.548Z

Yup, that seems to be working. Thank you. I’ll see if I can upload a higher res favicon because its all blurry and pixelated.