#655: Capability Delegation

Visit on Github.

Opened Jun 30, 2021

Ya ya yawm TAG!

I'm requesting a TAG review of Capability Delegation.

"Capability delegation" means allowing a frame to relinquish its ability to call a restricted API and transfer the ability to another (sub)frame it trusts. The focus here is a dynamic delegation mechanism which exposes the capability to the target frame in a time-constrained manner (unlike <iframe allow=...> attribute which is not time-constrained).

Further details:

  • I have reviewed the TAG's Web Platform Design Principles
  • Relevant time constraints or deadlines:
  • The group where the work on this specification is currently being done: WICG
  • The group where standardization of this work is intended to be done: WHATWG and Web Payments
  • Major unresolved issues with or opposition to this specification: None so far
  • This work is being funded by: Google Chrome

You should also know that our previous TAG request to delegate user activation raised valid concerns about being too generic, so we limited the scope of delegation here to a particular API. More details can be found in this section in the design doc.

We'd prefer the TAG provide feedback as: 🐛 open issues in our GitHub repo for each point of feedback

Discussions

Comment by @mustaqahmed Aug 9, 2021 (See Github)

We are hoping to start a Chrome Origin Trial with Stripe as a partner by the end of August. We would really appreciate a feedback here to prepare for that, even if it is just a preliminary feedback. Thanks!

Comment by @hadleybeeman Aug 17, 2021 (See Github)

Hi @mustaqahmed. We are looking at this in our TAG breakout.

We were wondering: Can advertisers ask top-level sites to give them this permission, and get more control than they have now? We already have the potential for a similar issue when advertisers ask the top-level site to run their ad script, but would your proposed API make the situation more confusing for users?

Comment by @flackr Aug 19, 2021 (See Github)

Hi @hadleybeeman. It's true that advertisers could now ask top-level sites to delegate them a capability instead of just requiring their ad script to run (which gives them arbitrary permissions). However, the ability of top-level sites to delegate the capability is ephemeral both in when it can be done and how long it can be used.

  1. It can only be done when the top-level site has user activation (e.g. click). This means the ad-frame could not expect to have the capability at any arbitrary time which would make it difficult to enforce (i.e. the ad-frame wouldn't know whether it doesn't have the capability because the host site didn't grant it, or because the host site didn't get an activation for it yet).
  2. The capability itself is very short-lived. When granted the ad-frame can only use it for a very short window of time.

Additionally, the specific capability is explicitly granted so it is easier to audit than ad-script.

Discussed Sep 20, 2021 (See Github)

Dan: 8 days ago work going on on the spec

Ken: payment integration...

Sangwhan: I see what they're trying to solve, this makes sense. Doesn't seem compatible with.... the capability delegation protocol and capabilities should probably be aligned with what we have in permission policy

Ken: yeah, what capabilities is this going to apply to?

Sangwhan: right now it's payment request

Ken: and fullscreen

Sangwhan: it's in the example and they've been thinking about it but current origin trial is just for payment request. The use case is fine. Seems a little bit unaligned with permission policy. It should be delegating a permission based on a user activation and request? If you're delegating an iframe to be able to do getusermedia based on the parent being granted getusermedia... should that be possible or should that be a separate permission? if you do getusermedia request on an iframe you're going to get a permission request on a different origin than what the user is looking at.. that's weird.

Dan: i was tracking down multi implementer support angle.. Chrome status page says positive feedback from Mozilla but when I followed that link it goes to a mozilla standards position where Anne says "I'm not 100% sure I understand this correctly" but does say agree it seems useful... but I think this is more.. positive engagement.

Sangwhan: not affirmative

Dan: yeah

Sangwhan: a bunch of unanswered questions, the fact that user activiation doesn't pass through iframes correctly at least from a scripting perspective is problematic. it is a user activation but in certain cases it doesn't work from an end user perpsective which is confusing. User activation gating is our problem not their problem as an end user. i have to think about this more. I can see the utility, definitely. There's a problem that needs to be solved, just don't know if the proposed api is the right way to approach it.

Dan: leaves comment. Come back to it at plenary.

Comment by @torgo Sep 21, 2021 (See Github)

Hi @mustaqahmed @flackr we're discussing in this week's TAG breakouts. is there anything further on multi-implementer support? I note a link to the Mozilla Standards Position and the feedback seems like positive engagement...

Comment by @mustaqahmed Sep 22, 2021 (See Github)

We are not aware of any implementation plan by other browsers, but we're actively involved in working through the design with Mozilla (see the issues in our repository).

We would appreciate any feedback/comment from TAG, even if they are preliminary.

Discussed Oct 25, 2021 (See Github)

Peter: this one we're happy with.

Rossen: right. here the thing is you want to be able to grab a capability and propogate it down to an iframe... the way you do this is for any nested iframe you can request to have a capability delegated. For example giving it the ability to handle payments. Making e.g. Stripe work in an iframe as a payment handler. Removing friction in payment is a key factor. Great use case. This delegates down feature capabilities. All the privacy control features as part of webappsec permissions policy. Feature wise it makes sense. By delegating the capability you delegate it to anything inside that iframe. They can further delegate it to someone else. Don't know if it's preventable. The other thing that jumped out: as you read their doc - the privacy & security section - they're claiming that the capability doesn't allow provisions to sensors. Not true - it does allow camera, gyroscope, etc... you can delegate device access through that feature. I've asked them to document that in their security & privacy section.

Peter: some background - the capabilities includes the user activation state... they did delegate the capability of user activation... that way we're not baking in the user activation.

Hadley: what's the difference?

Peter: not just the permission. some things require user activation. You could delegate the permission but not have the user activation state. becuase the parent frame got the user activation state.

Hadley: is it possible for a webapp with access to camera and microphone and had an iframe for advertisers - is it possible the advertiser would get access without me being aware?

Rossen: yes although they could that today....

Dan: some possibility here - getusermedia for example in a peer to peer webrtc session..

Peter: we could restrict the capability to delegate to a subset of capabilities.

Rossen: i would be more worried about webusb or webshare...

Peter: parent frame... Payment processing...

Rossen: the exploit path is to impersonate myfavstore.com - i fool you into thinking you're buying a new headset. ... if I already fooled you on the top level document if I give it to a subframe it doesn't really matter. The payment capability is decent. the scenario is defendable. When it comes to device capability we need to tighten down. Maybe we can tighten the allow list to only a subset of what's listed in permissions policy.

Dan: i think that makes sense - don't open the floodgates to all the capabilities...

Hadley: i second that.

Rossen: I like that. In that case my proposal is to keep the issue open and feed that back and see if they're ok with that.

Peter: their explainer mentions a few use cases - i don't think they want to expose everything.

Rossen: it's in the spec itself. in Section 3.

Hadley: Adding that comment sounds good to me.

Comment by @atanassov Oct 26, 2021 (See Github)

The general capability is useful and in its current form it establishes a clean control pattern into the main document. One nit that stood out for me is that through the current list of feature-identifiers you can get access to device sensors (camera, geolocation etc.), provided the users has given access already. Can you confirm that is true and if so, can you amend the security&privacy section to state that?

Comment by @atanassov Oct 27, 2021 (See Github)

Under further review and reading through the entire list of standardized features, we are concerned about making all features available for delegation. More specifically, if a top level document is granted camera, usb, web-share etc. permission, it shouldn't be able to delegate without additional user consent.

Our recommendation is to specify an allow subset of features, namely payments and fullscreen (from what I can tell are current use cases) and be explicit about it in your spec.

Comment by @mustaqahmed Oct 27, 2021 (See Github)

Under further review and reading through the entire list of standardized features, we are concerned about making all features available for delegation. More specifically, if a top level document is granted camera, usb, web-share etc. permission, it shouldn't be able to delegate without additional user consent.

That's a valid point, thanks for highlighting this.

This proposal is not meant to cover the delegation of "all features". Instead, it just defines an interface for delegation, which can used by individual feature-owners in future if they decide to make the feature available for delegation.

To further emphasize this perspective, our monkey-patch to Payment Request spec (developed in consultation with that spec's owners) is just one specific example we added for sake of the completeness the Capability Delegation proposal. Without such a concrete example, it is impossible to convey the details of delegation.

Each individual feature-owner would run a separate review process when proposing a change to corresponding feature's spec in future. For example, if the camera spec-owners decide to allow delegating this feature in future, they would need to define the delegated behavior of this feature. Such a definition would require a detailed spec change on their side, hence would call for a feature-specific review.

Our recommendation is to specify an allow subset of features, namely payments and fullscreen (from what I can tell are current use cases) and be explicit about it in your spec.

That's a great recommendation, thanks. It seems we can easily incorporate this "allowed subset" idea by conveying the success/failure status of the postMessage() call that initiates a delegation. For example, we can throw an exception if developers try to delegate a capability not available for delegation.

I will start updating the proposal in a few days and ping this thread when done. In the meantime, if anyone finds any problems with this, please let me know.

Comment by @domenic Oct 27, 2021 (See Github)

Under further review and reading through the entire list of standardized features, we are concerned about making all features available for delegation. More specifically, if a top level document is granted camera, usb, web-share etc. permission, it shouldn't be able to delegate without additional user consent.

Can you say more as to why?

Currently, if an outer page wants to delegate a capability an inner page, they can do so through hacky ad-hoc protocols: i.e., just proxy the API over postMessage(). For example, if a subframe wants camera permission, it would do something like window.top.postMessage("give me camera", "*") and the top page would have an event handler like

window.onmessage = e => {
  if (e.data === "give me camera") {
    requestCameraPermissionInThisTopFrame();
    const cameraData = getCameraData();
    e.source.postMessage({ cameraData }, "*");
    // perhaps repeat every 16 ms if they want video
  }
};

To my eye, capability delegation just provides a standardized mechanism for doing this, without requiring manual coding. So it seems like it should be usable for any API.

If this is not true, and I've misunderstood the explainer, then that'd be helpful information for the explainer to include :).

Comment by @annevk Oct 28, 2021 (See Github)

I'm also confused now and I agree with @domenic that all of this is already possible if the parties cooperate (which sending a message implies; though it should be stricter on origins, filed https://github.com/WICG/capability-delegation/issues/17 on that). Here's what I thought the idea was:

  1. Permissions Policy is used to delegate the permission, but it doesn't delegate the user activation. The user would still have to click in the frame if the API required user activation.
  2. Capability Delegation is used to delegate the permission and user activation.

There's no need that I can see for 2 to be restricted to a subset of APIs and I think we should make it work for all the things that require user activation today and are part of Permissions Policy. (And we should make the specification architecture reflect that better as it currently requires a lot of language for each individual API that can be better abstracted.)

Comment by @shhnjk Oct 28, 2021 (See Github)

I logically don't understand why we are in model where we have to pass permission from top frame to child frame, if child frame is the one who actually want to use the permission.

If this spec is trying to solve the user activation, why can't we just tie user activation with API usage? For example, parent frame wants to delegate user activation for payment, it'll postMessage like:

button1.onclick = () => win1.postMessage("msg", {activate: "payment"});

And then child frame will be able to consume user activation only for Payment Request API.

  1. Permissions Policy is used to delegate the permission, but it doesn't delegate the user activation. The user would still have to click in the frame if the API required user activation.

Permission Policy is not used to delegate permissions. Permission Policy allows a site to declare which permissions are allowed to be requested/used. Permission Delegation is a browser implementation and it's not a Web Standard.

Comment by @annevk Oct 29, 2021 (See Github)

The status of the delegated permission can be "prompt", in which case the user would indeed be asked first. Or it might be granted automatically, as is the case with fullscreen. It depends.

Comment by @atanassov Dec 7, 2021 (See Github)

@cynthia and I reviewed the proposal one more time during our Madripoor vf2f. @mustaqahmed, thank you for acknowledging my feedback about specifying an allow list of standard features, instead of the current normative spec text which implies all standard features.

With these proposed spec changes we are happy to close the review. Thank you for working with us and being receptive to our feedback. We look forward to see more progress done with the WHATWG. Good luck.