In the W3C WebDriver spec, where should an intermediary node's authentication travel in a new-session request?
answer
- who is asking, versus what is asked for
- beside capabilities, not inside them
- an argument to the command itself
- the spec's own example names two members
- top-level parameters are forwarded onward
basics
~20 sThe specification recommends sending it as top-level parameters beside capabilities, not inside them, because authentication is an argument to the New Session command rather than a browser feature. Its own example shows user and password at the top level.
solid answer
~50 sThe W3C WebDriver specification says that when an intermediary node needs information unrelated to user-agent features, "it is recommended that this information be passed as top-level parameters, and not as part of the requested capabilities". Its worked example is a new-session body carrying `"user"` and `"password"` as siblings of `"capabilities"`, and the reasoning it gives is that authentication is an argument to the New Session command itself rather than something about the browser you want. One consequence is easy to miss: the specification also states that an intermediary node **must forward** custom top-level parameters to subsequent remote-end nodes, so a credential sent this way travels down a chain rather than stopping at the first hop. The specification separately permits an intermediary's own namespaced extension capabilities instead, which is a different subject with its own naming rules.
code
json · 10 lines{
"user": "statements-portal-ci",
"password": "<supplied at run time, never committed>",
"capabilities": {
"alwaysMatch": {
"browserName": "firefox",
"platformName": "linux"
}
}
}go deeper
Be ready to say that the account credential goes beside the capabilities rather than inside them, and to explain the simple reason: capabilities describe the browser, not the caller.
Be ready to quote the reasoning, that authentication is an argument to the New Session command itself, and to name the three containers a credential can actually arrive in on a real service.
Be ready to reason about the forwarding rule when a request crosses more than one intermediary, and to say what that implies about which nodes on a path can read the credential.
Be ready to weigh the convenience of the address form against the exposure it creates, and to say what an organisation should standardise on when different services accept different containers.
## What the specification actually says The W3C WebDriver specification defines two roles that matter here. An **endpoint node** is the thing that actually runs a browser. An **intermediary node** sits in front of one or more endpoint nodes and may route a new-session request onward. A hosted browser fleet is an intermediary node, and so is a self-run router in front of a pool of machines; structurally they are the same role. The specification then addresses the obvious question — where does an intermediary's own configuration go? — with a recommendation stated in the New Session section: > If the intermediary node requires additional information unrelated to user agent features, it is recommended that > this information be passed as top-level parameters, and not as part of the requested capabilities. It illustrates that with a worked example of a new-session request body whose members are `"user"`, `"password"` and `"capabilities"`, side by side. The accompanying note is explicit about the reasoning: authentication "is an argument to the New Session command itself and not the user agent's capabilities", so it belongs beside them, not inside them. ## Why not inside capabilities Capabilities describe the browser you are asking for and the browser you got. That is a coherent, narrow job: - **They are negotiated.** The remote end matches what you asked for against what it can provide, and returns what it settled on. A credential has nothing to negotiate. - **They are echoed back.** Whatever the session ends up with is reported in the session's own capabilities, which is a poor place for a secret to live. - **They describe a user agent.** An account name is not a property of a browser, and putting it there conflates a billing relationship with a rendering engine. Keeping authentication at the top level keeps each container doing one job, and it makes the request readable: this is who is asking, and this is what is being asked for. ## The forwarding rule that follows There is a second sentence people miss, and it has real consequences: > An intermediary node must forward custom, top-level parameters (i.e. non-capabilities) to subsequent remote end > nodes. So a top-level parameter is not consumed at the first hop. It is passed along. That is deliberate — a chain of intermediaries may all need the same out-of-band information — but it means a credential sent this way is visible to every node on the path, not just to the service you thought you were talking to. Contrast this with what the specification says about an intermediary's own extension capabilities, which it says **must not** be forwarded to the endpoint node. The two containers behave in opposite directions, and knowing which is which is the whole point of the distinction. ## The three places a credential can sit For the credit-union statements portal suite pointed at a remote fleet, an account credential can reach the service in three distinct ways: 1. **Inside the endpoint address**, as the `user:password@` user-info component. This is the form Ggr's quick start publishes, from a project unmaintained by its own README, and it is widespread. It is convenient and it makes the whole address a secret. 2. **As top-level parameters** beside `capabilities` in the new-session body, which is what the specification recommends and what its own example shows. 3. **As the intermediary's own namespaced extension capabilities** — prefixed keys sitting directly in `alwaysMatch`. The specification permits this too, precisely because an intermediary cannot forward its own extension capabilities to an endpoint node; its worked example puts prefixed credential keys beside `platformName`, not inside a nested options object. That nested shape is a vendor convention the specification does not describe here. Which of the three a given service accepts is that service's choice. The specification recommends; it does not compel, and no client can make a server read a parameter it does not look for. ## What this means for a suite - **Read the server's own documentation for which form it accepts.** A recommendation in a specification is not a guarantee of support. - **Prefer the form that keeps the secret out of the address**, because a value that is not part of a URL cannot be logged by something that logs URLs. - **Remember that a top-level parameter travels onward.** If the request crosses several intermediaries, all of them see it. - **Do not invent a shape.** If a service documents one of the three, use that one; sending a credential in a container the server ignores fails as an authorisation error with no useful message. - **Keep the account identity out of assertions.** It is request metadata, not a property of the browser under test, and a test that reads it back is testing the plumbing. ## A note on why this looks over-engineered It is fair to ask why a browser-automation specification has an opinion about authentication at all. The answer is that the moment a request can be routed, there are two audiences for it: the browser, and whatever decided which browser. Capabilities were designed for the first audience. Everything the second audience needs — who is asking, which account, which entitlement — had nowhere to go until the specification gave it a place. The top-level parameter is that place, and the forwarding rule is what makes it usable across a chain rather than only at a single hop.
- Does an intermediary keep a top-level parameter to itself, or pass it on?It must pass it on. The specification states that an intermediary node must forward custom, top-level parameters — that is, non-capabilities — to subsequent remote-end nodes. That is the opposite of what it says about an intermediary's own extension capabilities, which must not be forwarded to the endpoint node. So a credential sent at the top level is seen by every node on the path, which is worth knowing before you send one.
- If the specification recommends this form, why do so many services still want the credential in the address?Because the address form predates the recommendation and needs nothing from the client library. Any HTTP client understands `user:password@`, so a service can accept it without the client knowing anything special. The top-level form needs the client to build a request body shape it may not expose. Convenience won; the cost is that the endpoint address becomes a secret.
- Why is a session's returned capabilities a poor place for an account credential?Because capabilities are echoed. The remote end reports what the session was actually created with, so anything placed there is likely to come back in the reply and from there into logs, reports and debugging output. Capabilities are designed to describe a browser and be readable; a credential wants the opposite treatment, which is why the specification puts authentication beside them instead.
saying these in an interview costs you the question
- Puts the account credential inside capabilities because everything else goes there
- Thinks the specification requires rather than recommends the top-level form
- Assumes an intermediary consumes a top-level parameter instead of forwarding it
- Believes any server will read a credential sent in any container
- Confuses capability negotiation with authenticating the caller