EIP-1102: Opt-in provider access

Something I think was a mistake in the early designs of Ethereum was combining Ethereum network access and signing tool/credential store. I would love to take this opportunity to split the two.

A browser plug-in may provide both signing interface and Ethereum network interface, but the dapp should see them as two separate things, not a single thing.

As a dapp user, I may use some public node like Infura or a semi-private node like QuikNode for getting data from the blockchain and submitting signed transactions to the blockchain. I may then use a ledger or MetaMask for signing things.

If we take this approach, then there would be no “upgrading” your connection to full access. The Ethereum network provider would not know (or at least claim to not know) anything about your accounts/credentials and it would have no ability to sign anything. The connected signing tool on the other hand would have privacy protecting features and not give up any information (even that it exists) until the user okays it.

4 Likes

Hi @rmeissner, thanks for your feedback. An additional EIP could definitely specify that an object should be passed to the enable method that specifies things like a specific wallet ID, a specific account type, a specific network, etc. This may be one path to solving the “multiple installed providers” situation you mentioned, but I think it’s probably beyond the scope of this initial EIP as you suggested. Your concerns around multiple providers being injected at once are interesting; exposure protocol aside, you’re right, this is a growing issue in the ecosystem.

Also, a provider implementation can expose any non-standard method (like isMetaMask) in either read-only mode or full mode if they desire; for reference, MetaMask plans to expose the isMetaMask method in read-only mode so dapps can still react accordingly even before user-approved full access.

Thanks again for your feedback.

1 Like

@MicahZoltu I agree that an ultimate separation of blockchain access and transaction signing would be very beneficial, and I think it’s a future we’re all working towards. This requires a fairly large technical shift in dapp browser architecture since most rely on exposing an augmented provider that intercepts certain RPC calls to populate accounts and to show approval UIs. We’re actively researching patterns to better separate signing interfaces from network interfaces, and thus the provider itself, but the ecosystem (and especially the user-facing dapp ecosystem) just isn’t there yet. I don’t feel that a proposal intended to standardize provider exposure and improve user privacy should determine the new paradigm for the separation of blockchain access and signers (though I’m very interested in continuing to research this more.)

At its core, this proposal directly strengthens user privacy by hiding user accounts and preventing unsolicited transaction requests on untrusted sites.

2 Likes

My understanding (which may be mistaken) is that this proposed change is a breaking change for all dapps, which is why it feels like a good opportunity to move over to a split interface.

Am I wrong that this is a breaking change for dapps?

(posted from a friend’s computer originally, reposting from my account)

Yes, the current (and most likely final) form of the proposal is technically a breaking change in that dapps must request a fully-enabled provider before initiating account-requiring RPC requests. But this amounts to a single additional API call; and while I see the value in the long-term goal of separating network access from signing capability, the magnitude and intent of this particular breaking change doesn’t seem to be a suitable platform for addressing this. In my mind, standardizing and restricting currently-unrestricted provider access doesn’t seem to be a valid opportunity to rethink how transaction signing works in browsers altogether.

I appreciate the feedback and hope to share ideas around the topic of network-signer separation in a new investigatory topic soon.

Hello again :slight_smile: I’m really liking the new spec! Seems very smooth. Only point of feedback would be maybe adding a field to the provider. Something like provider#readonly, which is just a bool value.

With that the dApp wouldn’t need to ask for permission (I know the browser would cache it so you don’t have to always ask permission) if the user had already granted permission and continue on with whatever flow the dapp has.

1 Like

I like the latest draft of the proposal, it simplifies the implementation considerably. I have a question about when to expect browser implementations.

As a developer, I’ve started a draft implementation of this proposal for our dApps that are in development. The cut-off date appears to be in November, but when can we expect to see the major browsers start incorporating this proposal for testing purposes?

I was hoping to see an implementation of this in Mint Browser (ie. window.ethereum doesn’t exist).

Hi, congrats about this great EIP, really good job done here.

So, I have read a couple of times, and correct me if I am wrong, the main reason of this EIP is improving the user privacy and maintain user experience in a safer way. The approach followed basically allows the user to connect to “ethereum” exposing some “private” information, having in the meantime a limited provider access (the reasoning for that has been well explained few comments above). In addition, interesting discussions on this thread (leaving aside the UX conversation) have been if this EIP should contain or not a mechanism for allowing the user to obtain this full access provider using a certain wallet, and also, a couple of indications about how to improve the protocol (relying on events).

Following on the previous discussion, despite I really understand your point to keep it as simpler, effective, less intrusive, reducing at max the necessary changes to adapt dapps, I also think this EIP should provide a solution for handling multiple wallets, especially if the scope of this EIP is targeted to chrome-extensions. Or at least define how we should proceed and then stick to it.

Some reasoning and spare ideas:

  • Right now having “race” conditions between providers is not just not cool, seems to be kind of weird.
  • Modify the whole process of connecting to ethereum but leaving in a weak (in the sense of not knowing “who” has provided you full access) mode the initial part does not look right
  • Adding/defining a mechanism when having 1+ web3 providers is not a big deal right now, but defining a new EIP it is.
  • Dapp browsers can easily ignore the listeners.
  • One logic assumption would be if two extensions are loaded, let the user choose

Following the solutions proposed in this thread, the event-driven solution (having a way to identify the provider who fired the success event) seems to be one of the best solutions, we can create a pool (implement the event mechanism as a simple carrier state transfer) of providers easily on the frontend (we could decide if that pool should be done by wallet providers or by ourselves in the frontend) and then, apply some extensible architecture over them: like a chain of responsibility pattern or a simpler Mapper pattern. In that way:

  • We can create continue with the typical open to extension-close to modification way: responsibility is in one small class no big impact if changes are needed, events do not need a response and can work in a clean way.
  • We can choose easily provider
  • We know easily which available providers we have
  • We have less cohesive architect solutions: not compromising implementation on providers’ code, keeping them optimistic, we still code “against” more abstract solution: not specifying the id on the call when login, having third-party integrations less intrusive (events are more independent and simpler than postMessage-open-opener way)

What do you guys think? Is that something you are willing to reconsider?

3 Likes

hey @benzap you can already try it in latest Status.im nightly build https://status-im.github.io/nightly/
Open Status, create account and login, go to profile tab, tap Advanced and enable Dev mode , then enable web3 opt-in option and open your Dapp, feel free to contact me if you have any questions.

2 Likes

Hi @benzap. In addition to the Status.im nightly build that @andrey mentioned, you can also test your dapp against MetaMask by using one of the latest builds from this pull request. We also added mock 1102 support that will be available in the next MetaMask release; this means dapps can begin to call provider.enable() to update their initialization flows prior to the MetaMask 1102 release date of November 2nd, 2018.

1 Like

Hi @apanizo. I agree that the issue of multiple extensions injecting (and thus overwriting) providers and Web3 instances is getting harder to ignore, especially with the growing number of extension-based wallets and signers. The issue is complex: who should decide which is the “correct” provider to use, the dapp or the user? For example, if a user has wallets A, B, and C installed as extensions and visits a dapp, should the dapp or the user choose which provider (and thus which wallet) to use for signing transactions? Since this EIP no longer changes provider injection (e.g. a provider is still injected at page load) and instead only restricts account access, I’m not sure how we could easily solve the multiple-provider issue in this proposal.

Still, the issue is a serious one. One possible solution would be a separate EIP that standardizes a <meta> tag that dapps should include. The presence of this meta tag would tell dapp browsers to inject a provider, and some attribute on the <meta> tag could indicate which provider should be injected. Something like:

<meta name="ethereum" providerID="metamask">

I think this is a complex problem that’s outside the scope of this proposal in its current form, but the <meta> tag pattern is one possible solution if dapps (and not users) should decide which provider and wallet to use.

2 Likes

@bitpshr @apanizo I think this is a pretty valid concern too! My opinion is that users should get to choose which provider they want. Maybe there can be some sort of mechanism where the EIP defines how providers inject themselves, but also how dapps consume them and display that info to users? I see it getting complex quickly, as maybe a user wants to change their provider for that dapp in the future… each dapp would need to implement that UI, or a fallback for just choosing one. Or maybe it can be twofold. If dapps want to control the provider, they use the meta tag. If dapps want to allow users to choose, they implement the UI. Thoughts?

Hey, is there plan to finalize this EIP ?

If so, it would be good to add a challenge payload option so the application can authenticate the address and be sure that the wallet really have the privateKey it claims to have.

There is a proposal described here : Automatic Authentication Signature

Basically the eth_requestAccount call would look like :

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "eth_requestAccounts",
  "params": ["0x55f55f5e5e6e7e867e"]
}

I would make the payload unrestricted so any data could be specified here.

To prevent application from using it to sign arbitrary messages, the payload is prepended with Automatic Signature before being signed.

Note that in the proposal mentioned above, I also propose to add a new json method eth_autoSign that would remove the need to add that facility in the eth_requestAccount method (since in that case authentication could be done any time afterward).
Nevertheless I would still argue that having it in eth_requestAccount is a good idea since it remove the need to make another call. It will also increase the likelihood of having such authentication mechanism available for apps without having to wait for the auto_sign proposal to be accepted

Note that we can make it backward compatible with existing app by making the challenge payload optional.

2 Likes

Hey,

while dapps can requestAccounts they currently cannot provide a UI for users to disable access (logout) without implementing it their own way (in an unreliable manner).

This feature is useful for applications that want to provide access choice for different wallets, built-in vs web-based wallet like portis, bitski…, as it would allow the application to disconnect from the built-in wallet, giving them back choice.

You can imagine the flow this way

if (isBuiltInWalletEnabled()) {
  use builtin wallet
} else if(iswebWalletLoggedIn()) {
  use web wallet
} else {
  offerChoice()
}

where the users could go back to the choice by closing access to the built-in accounts (if connected this way) or via the web wallet logout method (if connected this way).

While this is currently achievable by storing a cookie or a value in localStorage to remember the last used wallet and let user forget it, it is unreliable as it relies on cookie/local storage.

I propose thus

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "eth_closeAccounts"
}

that would reset account access for that particular application

1 Like

I think this EIP as it stands is too restrictive for a standard. A standard should standardize the set of things that benefit from being standard, and leave the remaining things up to individual applications. This standard currently asserts the following:

  • Browsers MUST expose a provider at window.ethereum .
  • Browsers MUST NOT populate the provider with user accounts by default.
  • Browsers MUST define an eth_requestAccounts RPC method.
  • Browsers MUST show an account access approval UI when eth_requestAccounts is called.
  • Browsers MUST populate the provider with accounts if account access is approved.
  • Browsers MUST resolve the Promise returned by eth_requestAccounts if account access is approved.
  • Browsers MUST NOT populate the provider with accounts if account access is rejected.
  • Browsers MUST reject the Promise returned by eth_requestAccounts with an Error if account access is rejected.

However, many of these are things that aren’t necessary for as standard, and different tools may desire to make different decisions on them because they target a different demographic, or for UX reasons, or some other legitimate choice being made by a particular application.

I propose change to the following:

  • Browsers MUST expose a provider at window.ethereum .
  • Browsers MUST define an eth_requestAccounts RPC method.
  • Browsers MAY wait for a user interaction before resolving/rejecting the eth_requestAccounts promise.
  • Browsers MUST include at least one account if the eth_requestAccounts promise is resolved.

These changes make it so this EIP doesn’t attempt to prescribe how signers should work/behave, but it does define how the interaction between the dapp and the signer needs to flow. Dapps that build against this standard will be work with any signer that is privacy protecting, and they will also work with any signer that is not privacy protecting, or which chooses to protect privacy in a different way.

Some examples of signers that would work with these changes but not the current draft specification:

  1. A signer that doesn’t protect user privacy. For some users/use cases, this makes sense. For example, I have an account I use as my “global unique identifier” and I give it out to anyone who asks for it. I don’t want to have to click a button to “login” to every dapp I interface with, I never reject with this account.
  2. A signer that uses an attached hardware device.
  3. A signer that has a whitelist of approved sites, thus doesn’t prompt the user for each interaction.
  4. A signer that provides every dapp a unique address (by domain) and manages assets in a permanently hidden/private account which then transfers assets (possibly through a mixer) to the individual dapp accounts as needed.
  5. A signer that presents dapps with a fake address on initial login, but then may change that address later if the user decides to reveal their true identity.
  6. A signer that spoofs being some other user when interacting with the dapp.

Apologies for the delayed responses @wighawag and @MicahZoltu, I’ve been heads-down on another project. I think both of your suggested proposal modifications make sense and would be happy to review PRs that modify the specification.

2 Likes

Are there any plans to move this to Last Call and eventually final? I’m writing a browser extension provider and would like to follow the latest standards, but I’m pretty against coding against draft specifications.

If it is going to move to Last Call, it probably should be updated to match changes in stuff like EIP-1193 (no more .send, instead it is .request). Was .enable ever part of a spec that made it to final? If not, then consider removing the whole section on Provider#enable as it is just deprecating a thing that never technically existed (as far as specs are concerned).

1 Like

In trying to implement this, I have realized that the lack of explicit error messaging makes it impossible to reliably implement a dapp that uses this while supporting older Ethereum browsers. If you are working with a browser that does not implement this, then you will be unable to differentiate between “this method failed because it doesn’t exist” and “this method failed because the user denied access”.

I think without the ability to ask the provider for capabilities, we cannot have methods that act as gatekeepers unless we start prescribing error results (e.g., assert in the spec that an error for not approved is shaped exactly like X).

Perhaps “unapproved” should return an empty array instead? This way if the method doesn’t exist it will hard fail and the dapp can fallback to eth_accounts or ethereum.enable and assume that the provider doesn’t implement this specification, and if it does exist and returns an empty array then it will let the dapp know “the provider supports this method but has returned no accounts that the dapp has access to” and the dapp can then behave appropriately in that situation.


(added below because Discorse won’t let me reply 3 times in a row)

I think this specification is overly prescriptive. One can easily imagine a provider that does want to give access to the blockchain (e.g., eth_getBlockByNumber) but doesn’t want to give access to the user’s account. Such a provider may even support eth_sendTransaction and eth_call by injecting the user’s account into the requests before forwarding them on to the signer or backing Ethereum client so the user’s address may never be exposed to the dapp (some dapps can work without ever knowing the user’s account, and it will be up to the dapp to decide if it can function without that information).

In general, I think that provider specifications should not specify provider behavior and instead should focus on specifying the interactions between dapp and provider. In this case, the specification for eth_requestAccounts can describe the shape of the request and response but I don’t think we should be specifying what the provider may be doing behind the scenes.

1 Like

Thanks for the feedback on this Micah. I recently became co-author of this EIP since bitpshr is no longer actively working on it. Your points are well taken, and you can expect many of them to be incorporated in a forthcoming significant update of 1102.

I can already note that:

  • eth_requestAccounts is staying; ethereum.enable will be removed from 1102 entirely, albeit perhaps mentioned in a comment for historical context.
  • 1102 will require 1193
  • 1102 will specify that the 4001 - User Rejected Request error should be returned if the user rejects the request. That error is defined in 1193.