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

On Sat, Oct 5, 2013 at 7:08 PM, Giuseppe Pascale <giuseppep@opera.com> wrote:
> On Fri, Oct 4, 2013 at 7:18 PM, Rich Tibbett <richt@opera.com> wrote:
>>
>> >>
>> >> 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).
>>
>
> It has been pointed out before that "device" in UPnP terminology doesn't
> mean one physical device. Actually a "device" in UPnP is somewhat closer to
> our definition of "service", e.g. a "Media Server" in UPnP is a device, and
> includes the following services: "ConnectionManager", "ContentDirectory",
> "AVTransport", "ScheduledRecording".

I think this is slightly tangential but let's discuss.

My position on this is that a web page can request the four services
above in a single call to getNetworkServices, assuming they intend to
interact with all four services. Otherwise, we the API supports access
minimisation, where a web page could request just "ContentDirectory"
and "ScheduledRecording" to fulfil its use cases.

At the UX level, the user would be authorizing one 'device' and all
requested services belonging to that device would be shared.

>
> I think a web app will be interested in talking to a "Media Server" and NOT
> to a subset of functionalities of a Media Server services (functions).  I
> think this goes back to the old discussion about UPnP services VS UPnP
> devices: does it make sense to expose single UPnP services rather than UPnP
> devices? I don't remember if we concluded on that, maybe we should do it
> before we change the spec.

I like the concept of grouping device services together but sharing
those sub-components could be done on a need-to-know basis as per the
current spec.

>
> Going back to the original issue, my comment above is not that relevant
> anymore if we go for the "alternative" proposal (as I also suggest). It's
> still important to define though what to do with UPnP devices: if only some
> services support CORS (i.e. the tentative preflight requests on their
> control URL is successful) what should the UA do? Should it be exposed to a
> web application or not? Should we even allow search for single UPnP
> services, or only for devices?

Well these are additional issues we will then need to discuss and
resolve. Right now we minimize access only to the services requested
from a web page and no more.

I think some people see changing from service access to
grouped-service (aka 'device') access as a trivial change. It really
is not.

>
>
>> >> ---
>> >>
>> >> 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.
>>
>
> A comment from implementer would be valuable here. I've got the impression
> that the effort required to change your services to "opt-in" is the same as
> to change your service to support CORS. If so, better to go for a cleaner
> solution

Yes. It would be the same as implementing standard CORS on a networked
service which is much cleaner.

>
>
>>
>> >
>> > 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.
>>
>
> not sure I understand: wouldn't the UA issue this preflight request to make
> sure the service is CIRS enabled before exposing it to the user/webapp?

Yes and that's an important point here. Successful preflight checks
would be a prerequisite for offering network service(s) up for sharing
to a user and subsequently a web page.

Also (and this may just be a note for me here), the spec also needs to
keep the 'preflight result cache' fresh. i.e. honor
'Access-Control-Max-Age' response headers and add clauses to re-issue
preflight requests towards network services when access control cache
entries expire.

>
>>
>> >
>> > 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.
>>
>
> Maybe you can try to write something in the spec on this (you could start
> with an informative section (SHOULD) and we can discuss if to make it a MUST

I think that's a good idea.

>
>
>>
>> >
>> >> ---
>> >>
>> >> 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.
>
>
> yes, this is my thought as well. Anyway the best thing would be to write a
> proposal and discuss it with relevant standardization bodies.

Sure. Of course, this is quite a clean solution so anyone implementing
CORS on their UPnP/Zeroconf/DIAL network services control endpoints
should qualify for web sharing under this API.

>
>>
>> Perhaps the original alternative proposal is better since it
>> requires no changes at the discovery protocol level.
>
>
> yes, and the fallback to support for "legacy" devices would be to basically
> allow cross-domain requests regardless of the services supporting CORS.

Exactly.

Some good clarification questions in there. Thanks.

Received on Monday, 7 October 2013 00:45:32 UTC