Skip to content

Enabling IDP Interception in FedCM Request#815

Open
pottis wants to merge 20 commits into
w3c-fedid:mainfrom
pottis:fedcm_idp_intercept_request
Open

Enabling IDP Interception in FedCM Request#815
pottis wants to merge 20 commits into
w3c-fedid:mainfrom
pottis:fedcm_idp_intercept_request

Conversation

@pottis
Copy link
Copy Markdown
Contributor

@pottis pottis commented Feb 28, 2026

The current FedCM specification defines a browser-mediated flow where the browser makes direct HTTP requests to IDP endpoints. This PR implements a foundational capability allowing Identity Providers (IDPs) to intercept and handle FedCM (Federated Credential Management) requests through Service Workers. This feature unlocks advanced security and operational patterns that were previously impossible in the FedCM ecosystem.

Having this feature, it will address some of the key-issue from enterprise identity providers.
Key issues:

  • Multi-domain failover: Route to backup IDP when primary fails
  • Geographic/sovereign routing: Send requests to jurisdiction-specific servers
  • Token caching during outages: Graceful degradation when IDP temporarily unavailable
  • DPoP (Request Signing): Prevent token theft with cryptographic proof-of-possession
  • Legacy system integration: Wrap existing identity services with FedCM interface

Links:
Issue #80

Explainer : https://github.com/pottis/FedCM/blob/4499cd7593e8f39b588ff3a6cca90e7ffd68beb8/explorations/identity_handler.md


Preview | Diff

Comment thread spec/index.bs
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment on lines +1590 to +1591
1. Let |processResponse| be the result of the following steps given a
<a spec=fetch for=/>response</a> |response| and |responseBody|:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I overlooked the incorrectness of <a spec=fetch for=/>response</a> when I wrapped it from line 1590 to 1591. I cannot easily tell what this should be, so I'm not suggesting a correction here ... but I'm flagging the need for that correction. If we can figure it out, I think it can be applied in this PR. If not, this comment should be used to start a new issue.

@pottis pottis marked this pull request as ready for review March 11, 2026 08:19
Comment thread spec/index.bs Outdated
@pottis pottis changed the title Add support for IDP to intercept fedcm request via service worker Enabling IDP Interception in FedCM Request Mar 11, 2026
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
@pottis pottis requested a review from domfarolino April 28, 2026 14:47
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
Comment thread spec/index.bs
<var ignore>processResponseConsumeBody</var> set to the following steps given a
<a spec=fetch for=/>response</a> |response| and |responseBody|:
1. If |responseBody| is null or failure, set |credential| to the result of
[=create an IdentityCredentialError|creating an IdentityCredentialError=] with {}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[=create an IdentityCredentialError|creating an IdentityCredentialError=] with {}
[=create an IdentityCredentialError|creating an IdentityCredentialError=] with «»

See how the Infra Standard defines list literal syntax. I see there are other pre-existing instances of this in this spec already, but let's start incrementally using the right one.

Copy link
Copy Markdown
Contributor Author

@pottis pottis Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue : #829 logged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domfarolino — Please provide a link to "how the Infra Standard defines list literal syntax" so I and other reviewers don't need to spend time searching for it and maybe find the wrong definition. My immediate question is whether the European quotation mark chevrons («») are what is intended, and not doubled angle brackets (<< >>).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread spec/index.bs
from |response| and |responseBody|.
1. [=converted to an IDL value|Convert=] |json| to an {{IdentityAssertionResponse}}, |token|.
1. If one of the previous two steps threw an exception, set |credential| to the result of
[=create an IdentityCredentialError=] with {} and |globalObject|, and return.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here (and any instances below).

Copy link
Copy Markdown
Contributor Author

@pottis pottis Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue : #829 logged.

Comment thread spec/index.bs
|globalObject|.
1. The user agent MAY set |credential|'s {{IdentityCredentialError/error}} based on
|response|'s [=response/status=]. For example, if the [=response/status=] is `500`, it
could set it to "server_error", and if the [=response/status=] is `503`, it could set
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a little unfortunate that this is not standardized. Has there been any discussion about doing that?

Copy link
Copy Markdown
Contributor Author

@pottis pottis Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue : #829 logged.

Comment thread spec/index.bs Outdated
Comment thread spec/index.bs
: {{IdentityRequestEvent/endpoint}}
:: |endpoint|
: {{IdentityRequestEvent/request}}
:: |request|
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Continuation of my other comment, somewhere above)

I'm now realizing for the first time that we don't actually use the target IDP service worker like a normal service worker, where a request is first fetched, and then deep in Fetch, the Service Worker's "handle fetch" algorithm is called with a request that has been heavily processed, its headers set, its client/referrer/origin all resolved, etc.

Here, we're trying to sort of "mock" that by constructing a request, and just immediately firing a functional event inside the service worker passing the very-unprocessed request to the SW directly (i.e., Sec-Fetch-Dest headers were never added). But what good is it to expose this request to script, if it hasn't been processed much yet? Is it the request's URL that script will care about and want to act on?

Was there any discussion about just "fetching" the above request normally, and letting Fetch pass it off to the IDP's service worker (we could easily make it choose a FedCM-specific IDP service worker, instead of the normal one, as we've discussed elsewhere in this PR). That way we could do the normal thing of dispatching a FetchEvent on the service worker, and letting the service worker process the IDP request like any other request.

Maybe this has been discussed before and I'm off base. If so, my bad!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d like to offer a different perspective on the architectural layering here. I remain convinced that leveraging the Fire Functional Event algorithm is the correct path forward for FedCM, rather than extending Handle Fetch.

My primary concern is that allowing browser-initiated, cross-origin requests to piggyback on the Handle Fetch event effectively re-opens the door to Foreign Fetch, which is a feature that was intentionally removed due to significant security and privacy risks. If we extend Handle Fetch to support client: null requests for FedCM, we create a precedent that arbitrary standards can use to bypass the Same-Origin Policy (SOP) via the Service Worker pipeline.

As we discussed previously on service-worker-discuss, the Handle Fetch algorithm should remain strictly dedicated to navigations and subresource fetches within a controlled environment. In contrast, the Fire Functional Event algorithm was designed specifically to allow the User Agent to orchestrate specialized interactions with a Service Worker without blurring these fundamental spec boundaries.

This approach keeps the Service Worker specification focused and simple, while placing the responsibility for defining FedCM-specific request/response semantics where they belong: in the FedCM specification.

I would also very much value hearing @wanderview's thoughts on whether extending Handle Fetch in this manner poses a long-term risk to the Service Worker security model.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't had time to read this PR as its quite long, but the principles you are talking about make sense to me, @yoshisatoyanagisawa. In particular, I think using Fire Functional Event is important to make sure the service worker keep-alive logic, etc, is handled properly. Bypassing that could result in the SW thread being kept alive too long which introduces privacy and abuse risks.

Copy link
Copy Markdown

@domfarolino domfarolino May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposing this design due to a layering concern. I'm raising this because it just doesn't work. The stated intent of firing the functional event in the IDP's Service Worker is so that the IDP can "forward" the identity event's fetch request, but preserve the Sec-Fetch-Dest: webidentity header, so that the IDP's server knows it came form a legitimate UA-constructed webidentity request:

Its value is a browser-constructed {{Request}} object for the [=IDP=]
endpoint. The request has its [=request/destination=] set to "webidentity", which causes the [=user agent=] to set the [:Sec-Fetch-Dest:] [=forbidden request-header=] to webidentity. The
service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}} to preserve the header, which the
[=IDP=] server can use to verify the request originated from the FedCM API.

But this is just not how service workers work. FetchEvent.request.destination will indeed remain webidentity, and I believe the forbidden request headers like Sec-Fetch-Dest will exist, just not be exposed to script since they're sensitive. But when you call fetch() on that request, it immediately constructs a new DOM Request object from the original request, and this does NOT copy over the destination, which means when we go back through the whole network stack with this request Sec-Fetch-Dest will not be preserved. So the current design does not accomplish the stated goals.

(@npm1 raised a similar concern about webidentity in #815 (comment) / https://github.com/w3c-fedid/FedCM/pull/815/changes#r3053129839.)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, its similar to w3c/ServiceWorker#1803

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the fetch destination is limited and uncontrollable from the ServiceWorker script, I think this is the reasonable choice. We might need to ensure the allowed headers are safe to use. Also, I hope the security to review the API.

Copy link
Copy Markdown

@domfarolino domfarolino May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going back to @yoshisatoyanagisawa's response above:

If the IDP can identify the requester is the Service Worker registered by the IDP, it is fine. However, without browser-enforced signals (like forbidden headers), an attacker can easily write attack code to pretend to be the Service Worker to cause CSRF.

The IDP can verify that the requestor is in the IDP's own origin (i.e., its own service worker) via forbidden headers, like Sec-Fetch-Site: same-origin. An attacker cannot write "attack code" to pretend to be the IDP's service worker when contacting the IDP's server, because it cannot forge this header. So here's how I envision it:

Fetches caught by the IDP's service worker would validate that the IdentityRequestEvent's request has a webidentity destination, that the RP could not forge. If the SW checks out the request and deems it "valid", then the SW sends a same-origin request to its own server to get the actual resource. The server checks that Sec-Fetch-Dest === same-origin to be sure that the attacker did not forge the request, and to confirm that it's talking to its own origin.

If there is no browser help to provide a non-forgeable identifier, it might not be so easy to maintain the existing security model.

So yeah, just to be clear I think the existing forbidden headers give us everything we'd need, without warping the processing model of service workers as a special case in this specification. The service worker processing model is how it is for a reason, and I think letting individual specs poke substantial holes in it for one-off use-cases is regrettable and should be avoided, especially when existing primitives line up to form an equivalent solution, which I think is the case here.


Also the whole augmented fetch thing doesn't make sense to me. The draft above references things like "§3.4 below" that don't exist, and definitions like "Allowlist headers section" that aren't filled out. @pottis please scrutinize your AI responses more thoroughly.

Copy link
Copy Markdown
Contributor Author

@pottis pottis May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domfarolino , I intentionally left out those points because I wanted to confirm the approach first. I understand your feedback and will make sure to include all relevant information to help reviewers in the future.

Regarding your comment, "Also the whole augmented fetch thing doesn't make sense to me"—could you please elaborate? There are some limitations with fetch(…) where certain properties get reset when it's called for which i am proposing this approach.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

—could you please elaborate?

I don't know what "dpop proof" is, and I'm not sure how it fits into this proposal. What is the "augmented fetch" trying to accomplish? I'd appreciate an explanation to that before a long algorithm with incomplete definitions. For example: is the goal to preserve webidentity and Sec-Fetch-Dest from the request that the SW intercepted from the RP? If so, then why is any kind of "proof" / key / signature needed, if the existence of the forbidden header is enough? And if you're not trying to preserve webidentity and Sec-Fetch-Dest, then why do we need a special "augmented fetch" anyways, when you can just add your own (cryptographic) headers to the request that the SW forward onto its same-origin server?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I initially thought a new fetch API was necessary for CSRF prevention, but if it can be reliably achieved using existing primitives like Sec-Fetch-Site: same-origin, I agree that we should avoid introducing a new API. Adding a non-normative note to guide developers on how to implement these server-side checks should be sufficient to address the CSRF concerns without adding complexity to the service worker model.

Comment thread spec/index.bs Outdated
Comment thread spec/index.bs Outdated
@pottis pottis requested a review from npm1 April 30, 2026 14:21
@hlflanagan
Copy link
Copy Markdown
Contributor

Discussed during the 5 May 2026 meeting.

Comment thread spec/index.bs
is already converted in. This avoids invoking [=converted to an IDL value=] from the
calling [=in parallel=] context, which has no associated <a for="global object">realm</a>.

1. Let |registration| be the result of running <a spec=service-workers>Match Service Worker
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, arbitrary "Match Service Worker Registration" algorithm caller can look up the registration for FedCM if the storage key and origin matches. Is it intended? i.e. algorithm outside of the FedCM may use the registration or unregister it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought we were keeping a separate partition of FedCM-specific service workers so that we wouldn't collide with pre-existing service worker registrations, and so that other parts of the platform wouldn't collide with FedCM/IDP service workers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am saying this because I thought FedCM ServiceWorker is intend to be isolated from the other ServiceWorkers by having its own mapping, but it looks not.

Copy link
Copy Markdown
Contributor Author

@pottis pottis May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the concerns correctly,
a) Pre-existing IDP service workers (caching/push) are automatically enrolled into FedCM as soon as a listener is added.
b) FedCM service workers can be accessed and unregistered by any caller using Match Service Worker Registration.

To separate general functionality from FedCM-specific behavior, I'm considering adding a field to ServiceWorkerRegistration:
partial dictionary RegistrationOptions { boolean acceptsFedCM = false; };
partial interface ServiceWorkerRegistration { readonly attribute boolean acceptsFedCM; };

With this change, IDP authors would register their service worker as follows:
navigator.serviceWorker.register('/sw.js', { acceptsFedCM: true });

Please share your thoughts, or let me know if you have suggestions for a better approach to achieve isolation.
Note: The current specification prefers the IDP to register the service worker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need a mechanism for this new kind of "acceptsFedCM" service worker to intercept webidentity requests; how would that work? When Fetch fetches webidentity requests, would it just pass a special "key" to https://w3c.github.io/ServiceWorker/#match-service-worker-registration, so that we only match "acceptsFedCM" service workers?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pottis I'm not convinced that adding this field fixes the issue. A proper fix might require ServiceWorkerRegistration to have a state explaining its owners (FedCM, Web, or both), but that involves updating the registration and control logic. I'd like to understand the clear rationale for opting for this complexity over simple isolation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would the alternative "simple isolation" look like to you @yoshisatoyanagisawa? When would Fetch know to trigger the "FedCM service worker" vs others, and how would we know which SW to fetch/install when doing all of this for FedCM?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussing this directly with @pottis, I recognize that I had been operating under the assumption of a previous registration model and overlooked the fact that it had already changed in the current design.

Correcting for that understanding, I believe the API should follow the architectural pattern used by features like the Periodic Background Sync API or the Notification API.

Specifically, I suggest extending ServiceWorkerRegistration with a dedicated interface—for example, registration.identity (an IdentityProviderManager). To enable FedCM interception, developers would be required to explicitly call registration.identity.register(configURL). This creates a one-to-one mapping between the IDP Config URL and the registration, ensuring that functional events are only dispatched to workers that have intentionally opted-in to handle that specific provider. (configURL was used since configURL might be the unique identifier for IdentityProviderConfig.)

This approach addresses the semantic mismatch of using the implicit 'Match Service Worker Registration' algorithm for internal UA requests that lack a controlled client. It also provides a clear lifecycle for unlinking via unregister(configURL) or through the removal of the parent registration.

What are your thoughts on adopting this explicit registration model?

Comment thread spec/index.bs
Comment on lines +1381 to +1382
service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}} to preserve the header, which the
[=IDP=] server can use to verify the request originated from the FedCM API.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}} to preserve the header, which the
[=IDP=] server can use to verify the request originated from the FedCM API.
service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}}
to preserve the header, which the [=IDP=] server can use to verify whether the request
originated from the FedCM API.

@pottis pottis requested review from domfarolino and wanderview May 12, 2026 18:41
Comment thread spec/index.bs
{{Event/isTrusted}} and throws an "{{InvalidStateError}}" {{DOMException}} if it is false,
so only UA-dispatched events (created via [=creating an event=]) can provide responses.

Each {{IdentityRequestEvent}} has a
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit but is it possible for the JavaScript object to have the field like this? (this is something like how to write standard, and not important for the way to implement this.)

In the past, I might have implemented the corresponding structure to deal with the situation like: https://urlpattern.spec.whatwg.org/#urlpattern-associated-url-pattern
However, I hope whom knows web standard will take another look.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify the concern you have @yoshisatoyanagisawa

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we need a corresponding data structure to have a hidden field for the web exposed structure, and I thought we need the corresponding data structure for IdentityRequestEvent to have hidden fields while we do not provide the mapping from the Web exposed to the internal structure if we want the field hidden.
However, if we do not need such a complicated logic to realize the hidden field, it should be fine.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. The way this PR does it and the way that URLPattern does it is basically the same. Objects, including IDL objects, can have two types of "things":

  1. They can have "internal" members, which are denoted in spec prose by either [[InternalSlots]], "associated" structures like you do with URLPattern, or just ordinary non-IDL "members", like https://dom.spec.whatwg.org/#abortsignal-abort-algorithms;
  2. They can have IDL attributes and methods, which are web-exposed.

Both URLPattern and this spec are doing (1) here, and they're the same.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, then let me withdraw my comment. This looks following https://dom.spec.whatwg.org/#abortsignal-dependent style.

Comment thread spec/index.bs

The <dfn for="IdentityRequestEvent" attribute>endpoint</dfn> attribute getter steps are to return the value
to which it was initialized. Its value indicates which [=IDP=] endpoint is being requested. The
service worker uses this to determine whether to handle the request or let the [=user agent=] fall
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be clear, "service worker script" instead of "service worker", right?
"service worker" sounds like that the Service Worker core logic uses this for decision making.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing that out. I had been using SW and the SW script interchangeably, but I'll make sure to clarify the distinction moving forward.

Comment thread spec/index.bs
to which it was initialized. Its value is a browser-constructed {{Request}} object for the [=IDP=]
endpoint. The request has its [=request/destination=] set to "`webidentity`", which causes the
[=user agent=] to set the [:Sec-Fetch-Dest:] [=forbidden request-header=] to `webidentity`. The
service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}} to preserve the header, which the
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to revise this because the fetch from the Service Worker script won't preserve the sec-fetch-destination header. I understand that the dedicated method will be provided for the purpose instead.

Copy link
Copy Markdown
Contributor Author

@pottis pottis May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Seems @domfarolino still not aligned on fetchAuguement on its purpose, once i add proposal API to spec, will update the wording.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given #815 (comment) it looks like we're all aligned that "augmented fetch" and preserving Sec-Fetch-Destination is not a key part of this proposal, and is probably not needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, upon the discussion, I understand we agreed not to provide the additional fetch method. We just leave the developer note to ask them to check sec-fetch-site instead.
Anyway, the phrase should be updated because sec-fetch-dest won't be available.

Comment thread spec/index.bs
{{DOMException}}.
1. [=ExtendableEvent/add lifetime promise=] |response| to [=this=].
1. Set [=this=]'s [=IdentityRequestEvent/respond-with called=] to true.
1. Set [=this=]'s [=Event/stop propagation flag=].
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If other reviewers requested, it should be fine. However, I failed to catch why these flags should be set because events might not be propagated to anybody else.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domfarolino requested to capture the steps.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because the following should throw:

self.onidentityevent = e => {
  e.respondWith(foo);
  e.respondWith(bar); // throws, since respondWith() was already called!
};

To match how FetchEvent works in service workers already: https://w3c.github.io/ServiceWorker/#ref-for-fetchevent-respond-with-entered-flag.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the reply, I checked https://w3c.github.io/ServiceWorker/#fetch-event-respondwith Step 5, and it looks doing something similar.
Then, it is fine to leave as-is.

Comment thread spec/index.bs
it to "temporarily_unavailable".
1. Return.
1. Run |processToken| with |token|.
1. Wait for |credential| to be set.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit but since |credential| was set to null in L1616, the step may not wait anything. You might want to wait here while |credential| is null?

e.g. I saw ServiceWorker has yet another flag to tell the finish condition or watching a specific field like: https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm

Comment thread spec/index.bs
waiting for a [=/service worker=] to become active. See [[#idp-guidance]] for how
[=IDPs=] should register and activate their [=/service worker=] to ensure reliable
interception.
1. Let |result| be null.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit but might be good to mark |result| unset or something non null, then it might be easy for the latter step to recognize the value is set.

Comment thread spec/index.bs
1. [=Upon rejection=] of |respondWithPromise|:
1. The user agent [=reports a warning to the console=] indicating that the
identity handler {{IdentityRequestEvent/respondWith()}} promise was rejected.
1. Set |result| to failure.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may want to return in addition

Comment thread spec/index.bs
and an IDL dictionary type |dictionaryType|,
run the following steps. This returns an instance of |dictionaryType|, null, or failure. A null
result indicates the [=/service worker=] did not handle the request; a failure result indicates
the [=/service worker=] attempted to handle the request but failed.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the failed case, the PR seems to treat it as the failure. Is it really intended?

cf. For the Service Worker Handle Fetch algorithm, it may return the network error, and the fetch specification will trigger the network fallback for the case instead of showing the error page. Therefore, broken ServiceWorker script would just bring the network fallback instead of complete service stop.

Comment thread spec/index.bs
[=IDP=] and [=RP=] implement and enforce appropriate security headers (such as CSP, CORS,
and the mandatory use of the `Sec-Fetch-Dest: webidentity` header). These headers are key to
and the mandatory use of the [:Sec-Fetch-Dest:] header set to `webidentity`). These headers are key to
distinguishing browser-initiated FedCM flows from arbitrary requests.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to add a note for the service worker case.

Comment thread spec/index.bs
browser-constructed {{Request}} with [=request/destination=] set to "`webidentity`". This
causes the [=user agent=] to set the [:Sec-Fetch-Dest:] [=forbidden request-header=] to `webidentity`
on the request, which the [=IDP=] server can use to verify that the request originated from
the FedCM API. The service worker can forward this request via {{WindowOrWorkerGlobalScope/fetch()|fetch(event.request)}}. The
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might need to update this because it actually cannot forward the sec-fetch-dest header.

Comment thread spec/index.bs

### Scope Selection ### {#idp-guidance-scope-selection}

[=IDPs=] are encouraged to register the [=/service worker=] with a scope that
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the FedCM's ServiceWorker is isolated from the regular web ServiceWorkers, but it looks not?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replied in this comment : #815 (comment)

@domfarolino
Copy link
Copy Markdown

Hey @pottis, thanks for working on this and pouring so much effort into it, however I think we should step back a little bit and discuss some things at a higher-level. This PR is close to 400 lines long and we're 300 comments deep, and @samuelgoto and I are noticing that there's no OP1, no explainer, no written design requirements, and the farther we go down a few rabbit holes, the more deep design alterations get proposed.

I think we're all quite motivated to help unblock major partners adopting the FedCM specification, but fundamentally this deep into a pull request is not the best place for us to have such deep design discussions, which is why threads like #815 (comment) are getting a unruly and hard to resolve.

We think it'd be best to step back a bit and try and draft an explainer for this work. This can probably be a distillation of the parts of #80 that stuck, as well as discussion of how this relates to #787, and what resolutions if any came out of previous WG meetings about this feature (since I got pulled into all of this outside and after all of the meetings, as far as I can tell). I'm happy to help out with the explainer too.

Footnotes

  1. As of yesterday there was no OP. Apparently one has been written in the past 24 hours, but claims like "This feature unlocks advanced security and operational patterns that were previously impossible in the FedCM ecosystem." need more elaboration and discussion, among some others.

@hlflanagan
Copy link
Copy Markdown
Contributor

This has been added to the agenda for Tuesday, 19 May 2026. From the email to the lists:

PR #815 proposes a mechanism that would allow Identity Providers to handle certain FedCM requests using a Service Worker-based mechanism. The motivating use cases include request signing / proof-of-possession patterns such as DPoP, operational failover, geographic or jurisdiction-specific routing, caching during outages, and integration with legacy identity systems. The discussion has raised detailed questions across FedCM request processing, Service Worker dispatch, Fetch semantics, privacy, and IDP security expectations. Some of the detailed review appears to depend on higher-level direction from the WG. For example, we should clarify what privacy and security properties need to be accounted for in the IdP Interception proposal. If a FedCM request is handled by an IDP-controlled Service Worker rather than sent directly by the browser, what properties must remain true? For example, what may the handler learn compared with the current browser-direct request path? Is fallback to the ordinary network path always acceptable, or are there cases where the IDP must be able to fail closed?

Speaking as chair, I would like to separate those direction-setting questions from line-by-line spec review. I am not taking a position on the proposal, but I would like to make sure the CG and WG has a shared understanding of the problem and the boundaries so we can make an explicit decision on what needs to be in the PR.

@hlflanagan hlflanagan added the agenda+ Regular CG meeting agenda items label May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agenda+ Regular CG meeting agenda items

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

10 participants