If UX still needs to be ironed out doesn’t that indicate that this EIP is not ready?
@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.
I think this could be mitigated by including a “block future requests from this site” checkbox with the sign-in page.
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.
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.
Hoping you provide some facility a la my comments here:
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.
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.
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
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
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.
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.
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.
This isn’t completely true. Brave provides a fingerprinting protection mode, a feature that we considered at MetaMask, but is actually impossible for extensions:
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
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:
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.
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.
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
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
- Request a provider on page load
- On first action requiring provider, check for it
- If provider undefined, inform user of approval / download requirements
- Request a provider at any time (e.g. after button click)
- Concurrently inform user of connection attempt / download requirements
- 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.
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.
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.
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.
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.
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 ):