feat: present a bearer token on requests to the built-in Infura endpoints - #10252
Draft
cryptodev-2s wants to merge 3 commits into
Draft
cryptodev-2s wants to merge 3 commits into
cryptodev-2s wants to merge 3 commits into
Conversation
Contributor
Author
|
@metamaskbot publish-preview |
Contributor
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Requests to our built-in Infura endpoints should carry a bearer token in the
Authorizationheader. The token identifies the user and can be refreshed at any time, so it has to be resolved per request rather than captured when a network client is built.RpcServicehad no way to do that. It accepts afetchand a staticfetchOptions, andrequesttakes per-call options, but nothing resolves a header value at the moment a request goes out. The obvious workaround is to handRpcServicea wrappedfetchthat mutates the options on the way through, and that does work, but it pays for a header with a transport substitution: a caller who supplies their ownfetchsilently gets a different function than the one they passed, and the wrapper has to make assumptions about the shape ofinit.headersfrom outside the class that owns it.This PR adds the missing capability at the HTTP boundary instead, then uses it.
1. A dynamic header hook on
RpcServiceCalled immediately before each
fetch, inside the Cockatiel policy, so every retry attempt resolves headers again. Precedence isgetRequestHeaders>requestoptions >fetchOptions> defaults. A rejection fails the request attempt; resolveundefinedto proceed without the headers.Two deliberate details:
REQUEST INITIATEDdebug log, which already receives the full fetch options. Anything this hook returns is a good candidate for being sensitive, so injecting afterwards keeps it out of loglevel output.deepmergethe class already uses to fold in the Basic credential derived from URL userinfo. No second assumption about header shape, and no assumption made from outside the class.2.
NetworkController.getInfuraAuthTokenCore owns the gating, the client owns the token.
Core attaches the credential only when
configuration.type === 'infura'and the endpoint is not a failover. That is the security-critical half and it keys on the client type and the failover flag, not on the URL, so it cannot be fooled by an endpoint that merely looks like Infura. A custom endpoint pointing at Infura with somebody else's key gets nothing, failover endpoints get nothing, and underforcedfailover mode there is no Infura endpoint in the chain so nothing is issued at all.The client supplies where the token comes from, which keeps the auth controller and the consent policy out of
network-controller. No new messenger action, no new dependency, nothing breaking. Clients that pass nothing behave exactly as before.Because an
RpcServiceis bound to a singleendpointUrlfixed at construction, a header set for one endpoint cannot reach another. This is also why the hook belongs on the constructor rather than onrequest:RpcServiceChain.requestforwards one options object to every service in the chain, so a credential passed that way would also be sent to the failovers.Client usage
Resolve the token inside the callback, never in a closure around it.
getInfuraAuthTokenis invoked per request; anything read at construction is stale for the life of the client.References
N/A
Checklist