Re: [discovery] Adding CORS to NSD API - proposal and issues

On Sat, Oct 5, 2013 at 2:14 AM, Giuseppe Pascale <giuseppep@opera.com> wrote:
>
> On Thu, Oct 3, 2013 at 1:22 PM, Rich Tibbett <richt@opera.com> wrote:
>>
>> ---
>>
>> Current Proposal:
>>
>> To provide access only to CORS-enabled networked services it would be
>> good to have a way to detect CORS support during network service
>> discovery processes themselves; before those networked services are
>> offered up to users and before they are shared with web pages. A
>> networked service that does not provide cross-site request
>> communication would be relatively useless and is a situation we are
>> trying to avoid.
>>
>
> Question: is the assumption that support for CORS == discovery opt-in (i.e.
> a device/service wants to be exposed to the web) correct? Can a device
> support CORS but NOT be willing to be exposed to the web?

Primarily CORs is a mechanism that allows JavaScript to issue network
requests that break implicit same-origin policy restrictions enforced
by all web browsers. So if your HTTP service endpoints indicates
support for CORS then you are permitting access to it from JavaScript
embedded on web pages residing in different origins.

>
>
>>
>> The NSD API spec currently details the network service discovery
>> processes for three mechanisms: SSDP (UPnP), mDNS+DNS-SD and DIAL and
>> the method for each of these mechanisms to indicate a networked
>> service supports CORS could be as follows:
>>
>> - For SSDP, a <service> node contained within a UPnP Device Descriptor
>> File must provide a <corsEnabled> sub-element whose value must be set
>> to '1', 'yes', 'y' or 'true'. Otherwise, the <service> is said not to
>> support CORS and is therefore not accessible to web pages (except if
>> the service type is whitelisted by the user or user agent).
>>
>> [...]
>>
>>
>> - For DIAL, the discovery message response must contain a
>> 'Access-Control-Allow-Origin' HTTP header and the value of this header
>> must be '*'. Otherwise, the DIAL service is said not to support CORS
>> and is therefore not accessible to web pages (except if the DIAL
>> service type is whitelisted by the user or user agent).
>>
>
> since DIAL is based on SSDP, why using two different mechanisms for DIAL and
> "regular" SSDP? In particular, why not using an header in both cases? Would
> make the process lighter, as you don't have to parse xml files. Such header
> could either be the CORS header or an extra header (based on the answer to
> my question further up)

Presumably we want CORS opt-in to be on a service-by-service basis
rather than on a devices level (which would otherwise expose _all_
services belonging to that device to web pages).

UPnP provides a device descriptor that describes multiple network
services (and, optionally, embedded device descriptors that describe
yet more network services). DIAL does not advertise services in the
device descriptor file in the same way. A DIAL discovery message
always represents exactly one network service, hence the ability for
us to indicate CORS opt-in at the HTTP level of the discovery
messaging itself (since that does not apply to a range of network
services as we get in standard SSDP discovery).

>
>> We should also offer an override mechanism for users and/or user
>> agents to create a network services whitelist - enabling access to
>> non-CORS-enabled networked services also. Implementation of such a
>> network services whitelist remains at an implementer's discretion.
>
>
> This should solve some of the concerns about support for legacy, isn't it?

Yes. That is the primary intention of a network services whitelist.

>
>>
>>
>> In case any of the conditions above occur, a network service could be
>> accessed from web pages via the the Network Service Discovery API
>> (subject to all the conditions therein).
>
>
> Of course user is still asked for approval isn't it? (that a device wants to
> be exposed doesn't mean that the user want it to be exposed)

Yes. That condition remains unaffected: users still need to opt-in to
sharing with individual web pages.

>
>>
>>
>> ---
>>
>> Current Proposal Issues:
>>
>> The main problem with this approach is that dissonance has now been
>> introduced between a.) the indicating of support for CORS during the
>> discovery process and b.) _actual_ support for CORS in subsequent
>> service interactions. i.e. If a networked service indicates it
>> supports CORS during the discovery process and then subsequently fails
>> to provide 'Access-Control-Allow-Origin: *' in all subsequent HTTP
>> responses or the networked service doesn't implement the ability to
>> respond to CORS preflight requests correctly (among other potential
>> CORS-related pitfalls) then the process of communicating with a
>> networked service fails and the service is broken for all meaningful
>> purposes (I can't communicate with a discovered process from a web
>> page).
>>
>> One solution to this issue may be to require networked services to
>> opt-in to cross-site requests during their discovery processes (as
>> proposed above) but then for the user agent to 'simulate' CORS support
>> for that networked service's URL endpoint. This is similar to the way
>> the API is currently drafted, by adding service URLs to a URL
>> whitelist that requires the user agent to treat service URLs as if
>> they supported CORS without the service itself needing to support CORS
>> directly.
>>
>
> I don't think we should do this, unless there is a use case behind it. We
> shouldn't do it to workaround a potential bug, especially for something that
> is new!

But it does fulfil the requirement that services opt-in to web sharing
without then also mandating those network services to also implement
CORS at the messaging level. Then maybe requiring CORS implementation
at the messaging level in all network services is overkill considering
those services have already opted-in to web sharing at the discovery
level.

>
>>
>> The new part in this process is that networked services need to opt-in
>> to cross-site requests during discovery (via the mechanisms above)
>> rather than the user agent providing that access for all networked
>> services by default (as per the previously specced approach). That
>> seems to meet the objectives of this exercise without introducing any
>> potential dissonance between the service discovery process and the
>> service communication process.
>>
>> Minor point: If we do agree to go with this idea instead then it may
>> make more sense to rename 'corsEnabled' to 'xsEnabled' in the
>> discovery processes above.
>>
>> So the process essentially becomes CORS-like (where services need to
>> opt-in to cross-site sharing) but the result is 'simulated CORS'
>> (where the user agent acts as if CORS is enabled for URLS belonging to
>> shared networked services).
>>
>
> I don't think I like us "duplicating" what CORS already provides. So maybe
> is better to go for the alternative proposal below ... (more comments
> inline)
>
>>
>> -------
>>
>> Alternative Proposal:
>>
>> During the current drafting an alternative proposal came up and it may
>> be worth mentioning here.
>>
>> Instead of introducing the dissonance discussed above we could instead
>> rely on issuing tentative preflight requests [3] to networked service
>> endpoint URLs once the network service discovery process has been
>> completed as normal (without services needing to opt-in at the
>> discovery stage). This approach has the benefit of actually ensuring
>> CORS is properly supported since we are feature-detecting CORS
>> directly on actual network service URLs rather than trusting a
>> corsEnabled directive during discovery that assues us that CORS is
>> supported on any corresponding network service URLs.
>>
>
> So this means a service will be exposed to a web app IFF:
>
> - the service end point is CORS Enabled
> - the user as approved sharing that service, correct?

Yes. Of course the tricky bit is finding a way for the service to
indicate that it is CORS enabled _before_ the user is asked to share
the service with a web page and before any service messaging has taken
place which is the main topic of this thread.

>
> BTW could be a good idea to also include a "blacklist" of services that
> shall never be exposed (like routers)

We could do this and it would have no impact on the current API itself.

Since all network service access is essentially 'keyed' on its
respective, well-known service type token then we could certainly
disallow certain service types from ever connecting with web pages.

>
>> ---
>>
>> Alternative Proposal Issues:
>>
>> The major problem with adopting this alternative approach is that the
>> root of a networked service endpoint URL is not always configured to
>> return 200 OK responses (some networked services may provide access
>> only in sub-directories or non-standard root locations which can
>> differ per network service type). CORS preflight requests abort if the
>> HTTP response is not 200 OK, in which case this approach would fail to
>> capture legitimate CORS-enabled networked services during this
>> process.
>>
>
> not sure I get this, can you give a concrete example?

If a network service's control URL is resolved during the discovery
process to be http://192.168.1.2:3333/myservice and we then want to
tentatively check if CORS is enabled then the user agent would then
immediately issue a tentative CORS preflight request to that URL (A
HTTP OPTIONS request to the root service endpoint URL as described in
[3]). That service MUST respond with a 200 OK from that URL with a
'Access-Control-Allow-Origin: *' response header provided for that
service to be considered CORS-enabled and therefore for that service
to be accessible to web pages (pending prior user authorization via
browser chrome before any sharing taking place of course).

My initial concern was whether _all_ service root URLs would be set up
to respond to that tentative CORS preflight request or whether some
service endpoints are only configured to work on sub-paths of that
root URL. e.g. if my service only responds to CORS requests at
http://192.168.1.2:3333/myservice/mymethod then it would fail the CORS
preflight check and not be offered up to users to share with web
pages.

On second thoughts that may be a non-issue since we do not have any
legacy CORS support in any of the network services we are looking at
sharing. Perhaps the original alternative proposal is better since it
requires no changes at the discovery protocol level.

>
> /g
>
>> ---
>>
>> [1]
>> http://lists.w3.org/Archives/Public/public-device-apis/2013Sep/0040.html
>>
>> [2] http://tools.ietf.org/html/rfc6763#section-6
>>
>> [3] http://www.w3.org/TR/cors/#preflight-request
>>
>

Received on Friday, 4 October 2013 17:18:38 UTC