matrix-doc/proposals/2974-widgets-re-exchange-ca...

7.5 KiB

MSC2974: Widgets: Re-exchange capabilities

Currently widgets are only able to exchange capabilities during their initialization. This can be limiting to some widgets which don't generally require a given capability until much later in the widget's lifecycle.

This proposal attempts to support these sorts of long-lived widgets by still requiring the early exchange of capabilities and by altering the specification to allow mid-session capabilities.

For reference, the capabilities exchange is one of the first request/response pairs sent over the widget API during the widget's initialization. Once the widget has loaded, the client asks the widget which capabilities it wants - the widget is then expected to reply with said capabilities request. Normally a widget would not be aware of what capabilities it was approved for (upon receipt of the widget's request for capabilities the client is meant to prompt the user for confirmation), however under MSC2871 the widget is more aware of what capabilities it ended up being approved for. After the capabilities exchange happens, the widget is generally ready to be communicated with normally - this is the start of a successful "session".

Proposal

The line "Clients MUST NOT re-negotiate capabilities after the session has been established." is removed from the specification and instead replaced by the mechanism defined by this proposal.

After a session has been established, a widget can request additional capabilities with a newly proposed request_capabilities fromWidget action over the widget API. The shape of this request looks very much like what the widget would have already sent back to request the initial set of capabilities:

{
  "api": "fromWidget",
  "requestId": "AAABBB",
  "widgetId": "CCCDDD",
  "action": "request_capabilities",
  "data": {
    "capabilities": ["m.always_on_screen", "com.example.cap"]
  }
}

The client should only prompt the user to approve any additional capabilities that have not been approved already. The client should only respond with the standardized error response if the widget is being rate limited or some other programming error has occurred. The client responds to the widget's request with an acknowledgement (empty response object) to avoid the standardized timeout causing problems with communication.

After the client has prompted the user to approve/deny the additional capabilities, it uses the same communication structure established by MSC2871 to send over the total list of requested and approved capabilities throughout the session. For example, if the widget started the session by requesting com.example.cap.1 and was approved, then when the widget was later approved for com.example.cap.2 the client would inform the widget that it was approved for both 1 and 2.

This MSC does not currently allow clients to decline capabilities which were already approved. There does not appear to be a use case for this at the moment, and the client retains control over ending the session if it believes the widget is abusive/malicious (widgets cannot end a session, but a client can under the current spec).

As a result, clients should not reconfirm already-approved capabilities with the user. The client might still show the already-approved capabilities to give additional context to the user.

If the widget has made a mistake and requested no new capabilities then the user should not be prompted and the widget should be reminded of it's capabilities using MSC2871. This implies that the original request_capabilities request is also successful and does not result in an error response. The widget can still be rate limited for making repeated mistakes.

Much like the initial capabilities exchange, the client is permitted to approve capabilities which "make sense" for the widget without informing the user. Such examples include conference call widgets which ask to remain on screen: the client can (and probably should) auto-approve this capability. Widgets which expect their capabilities to be automatically approved are generally encouraged to make the request while the session is being established rather than with a secondary capabilities request, however. Typically widgets which would have their capabilities auto-approved will not need to add extra traffic to the session and can instead get the request out of the way early.

For the purposes of MSCs and functionality which require behaviour if the capabilities were approved (such as sending events from client to widget), this MSC implies that the defined behaviour starts once the widget is approved for the relevant capabilities. For example, if the widget starts by asking for all message events sent to it and later requests room name state events to be sent too, both would be sent to the widget (assuming the user approved both requests).

Potential issues

This could result in excessive popups to users as widgets request the bare minimum as they need it. Widgets are encouraged to avoid being rate limited by requesting capabilities in bulk where possible. Widgets should note that clients might be more strict on rate limits when user interaction is involved to ensure that the user experience is not damaged by a widget.

Repeated permissions prompts may help promote a user experience where end users do not read the capabilities being requested and automatically approve them, such as is common with presenting terms of service to typical users. Generally speaking, the first permissions prompt will be read by users as a sort of "wait a minute, what is going on" response however secondary prompts may result in the user clicking the 'Approve All' button. Clients are encouraged to perform user testing and alter their design as needed to avoid this scenario.

Alternatives

The widget could request a whole other session to be established, however this is overly disruptive to the communications channel that the client and widget will have established. Similarly, widgets could present dialogs to the user to request that the user reload the widget to establish a new session. It is believed that these are overly disruptive to the user experience.

Security considerations

As already mentioned, typical rate limit issues arise when arbitrary widgets can request information from the user, particularly in popup form.

Also as already mentioned, users may be inclined to approve secondary requests without reviewing the actual request. This could lead to a widget appearing innocent by requesting very few capabilities and following that up later with many more capabilities. Clients are encouraged to try and avoid this.

A third risk is that the widget might repeatedly request declined capabilities until it annoys the user into accepting them. This sort of behaviour should result in a rate limit response or the client continually denying the widget's capabilities request on behalf of the widget.

Unstable prefix

Until this MSC is in a release version of the specification, implementations should use org.matrix.msc2974 in the supported_versions request/response to detect support. The action becomes org.matrix.msc2974.request_capabilities under this convention - the capabilities return defined by MSC2871 is unchanged.