navigator-connect icon indicating copy to clipboard operation
navigator-connect copied to clipboard

Registration of the service worker for a third party service

Open KenjiBaheux opened this issue 11 years ago • 9 comments

I'm looking for a solution to registering a service worker for third party services that don't have any real user destinations that would let them do that (2 examples: analytics, fonts).

If I'm not mistaken, a client website could insert iframes to such services so that they have a chance to register their service worker for future navigator.connect interactions.

I think we should make this easier and cleaner:

Strawman: if there are no Service Worker in control of "https://example.com/?apiKey=...", the user agent would:

  1. fetch "https://example.com/?apiKey=...", with a Service-Worker/script header (the same we use to check for updates to a SW)
  2. The server may respond with the Service Worker for that endpoint.
  3. the user agent would then proceed to register it, provided that it's allowed to (e.g. complies with Access-Control-Allow-Origin).

We also need to way to specify the scope that this Service Worker is in charge of (if it's not limited to the scope of the endpoint). A separate header?

KenjiBaheux avatar Nov 13 '14 00:11 KenjiBaheux

I'm still studying the navigator.connect docs and wondering how a navigator.connect gets setup to manage data in IndexedDB (such as fonts). Please forgive me if I'm not fully understanding the subject...

My non-expert understanding is security considerations prevent iframes from accessing IndexedDB (https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#Security)

Would this prevent using an iframe to start a ServiceWorker that uses IndexedDB?

bstell avatar Nov 13 '14 05:11 bstell

The iframe mention was only in the context of how one could hack a solution to let fonts.example.com register its service worker for "fonts.example.com/v1/" (e.g. by using an iframe to "https://fonts.example.com/v1/register-sw.html").

But we should do better than that.

I read the mozilla bug linked in that page and it seems that Chrome might have a different viewpoint on the issue. I'm not sure what the latest is in that regard but it's irrelevant: a service worker for a given origin (e.g. fonts.example.org) is able to access its data and return what it wants to the client origin without any of the privacy concerns mentioned in the link (SWs live in a different context).

KenjiBaheux avatar Nov 13 '14 06:11 KenjiBaheux

Thx for the info. :-)

I'm still working thru the docs (mostly in the evening once my daughter goes to bed).

I want to understand the current design better before making too many comments.

Is my naive assumption on the right track?

  • "my" page says "connect some other sites ServiceWorker"
    • eg, fire off http://othersite.com/serverworker_1.js
  • that site's software will control what it does; eg, which URLs it services.

Thanks,

Brian

On Wed, Nov 12, 2014 at 10:52 PM, Kenji Baheux [email protected] wrote:

The iframe mention was only in the context of how one could hack a solution to let fonts.example.com register its service worker for " fonts.example.com/v1/" (e.g. by using an iframe to " https://fonts.example.com/v1/register-sw.html").

But we should do better than that.

I read the mozilla bug linked in that page and it seems that Chrome might have a different viewpoint on the issue. I'm not sure what the latest is in that regard but it's irrelevant: a service worker for a given origin (e.g. fonts.example.org) is able to access its data and return what it wants to the client origin without any of the privacy concerns mentioned in the link (SWs live in a different context).

— Reply to this email directly or view it on GitHub https://github.com/mkruisselbrink/navigator-connect/issues/2#issuecomment-62849302 .

bstell avatar Nov 13 '14 18:11 bstell

On Thu, Nov 13, 2014 at 10:35 AM, Brian Stell [email protected] wrote:

Thx for the info. :-)

I'm still working thru the docs (mostly in the evening once my daughter goes to bed).

I want to understand the current design better before making too many comments.

Is my naive assumption on the right track?

  • "my" page says "connect some other sites ServiceWorker"
  • eg, fire off http://othersite.com/serverworker_1.js
  • that site's software will control what it does; eg, which URLs it services.

Not quite, in the current design you don't exactly say "connect to this service worker", but instead "connect to this url", which will connect to whatever service worker has that url in its scope. The location of the service worker script should not be something that clients connecting to a service need to worry about (so in your example it would be navigator.connect('https://othersite.com/some-service'), which could fire off 'https://othersite.com/serviceworker_1.js' if that happened to be the serviceworker installed with a scope that includes that service.

As Kenji pointed out with this issue, this current design has the limitation that the service worker will have to be installed already for a connection to be succesfull. It would be nice if it is possible to connect to a service without having to explicitly install that service first.

I'm not sure how to best do that though, attempting to download the url being connected to and using special HTTP headers to figure out what service worker to install might work, but seems a bit ugly/fragily. One idea I had for this would be to somehow use the manifest for a web application (although it is not yet possible for a manifest to specify service workers to install afaik). And that would still leave the issue of how to go from service url to manifest url.

mkruisselbrink avatar Nov 13 '14 23:11 mkruisselbrink

As promised (to @sicking, @jakearchibald, et. al.), here's an alternative proposal:

What if a lack of a local script to handle a a navigator.connect() attempt instead generated an HTTPS request to the same URL which, only in this circumstance, were allowed to respond with a location and scope for a Service Worker script?

E.g.:

// Connection attempt when no SW is installed to handle the target URL:
var serviceURL = "https://example.com/services/thinger/v1/<entropybits>";
navigator.connect(serviceURL).then(...);

Generates:

GET https://example.com/services/thinger/v1/<entropybits> HTTP/1.1
Host: example.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: */*
User-Agent: ...
...

For which the server can respond with:

HTTP/1.1 200 OK
Date: Wed, 21 Jan 2015 05:05:05 GMT
Server: Apache/2.4.7
Strict-Transport-Security: max-age=31536000; includeSubDomains
Last-Modified: Sun, 09 Mar 2014 05:07:53 GMT
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 0
Service-Worker-Script-Location: /services/thinger/v1/<entropybits>/sw.js
Service-Worker-Script-Scope: /services/thinger/v1/<entropybits>

The browser would then fetch and run the install phase for /services/thinger/v1/<entropybits>/sw.js and resolve the initial promise if/when the SW activates successfully.

Thoughts?

slightlyoff avatar Jan 21 '15 05:01 slightlyoff

@slightlyoff's suggestion works well for navigator.connect(url), but less well if we want <link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'> to auto-use the https://fonts.googleapis.com/ service worker. I'm suspicious that we should accept the Service-Worker-Script-* headers for any resource that doesn't already have a SW.

jyasskin avatar Jan 21 '15 19:01 jyasskin

@jyasskin what's the proposal for the <link> case? I haven't seen that before

jakearchibald avatar Jan 27 '15 03:01 jakearchibald

@jakearchibald The idea that a SW should be able to handle resource requests from a top-level context that it doesn't control came up in https://groups.google.com/d/msg/mozilla.dev.platform/-cNLULs08As/bOyPNzhbMYYJ. It lets you write a SW for a webfont host without requiring that the font's users rewrite their pages.

jyasskin avatar Jan 27 '15 19:01 jyasskin

I don't see the conflict. Why would the https://fonts.googleapis.com/css?family=Open+Sans link not be able to return, amid it's headers:

Service-Worker-Script-Location: /services/font.js
Service-Worker-Script-Scope: /css

(This request could have a body or not.)

rektide avatar Jun 25 '15 15:06 rektide