-
Notifications
You must be signed in to change notification settings - Fork 95
Description
This is a proposal to solve some of the use cases from issue #333
The Problem
FedCM makes a credentialed fetch to IdPs to gather the user’s accounts before prompting the user to select one of those accounts and then gather the user’s explicit permission to share the selected account’s details with the RP. Because of that credentialed request, FedCM has to make sure that the relying party (RP) cannot collude with the IdP in a way that would allow the user to be tracked before user permission.
Early on, an attack was identified, where the RP could insert its location in the credentialed fetch URL using the JS API:
const cred = await navigator.credentials.get({
identity: {
providers: [{
url: `https://idp.example/${window.location.href}`
}]
}
});
So, we introduced a .well-known file that forced the IdP to enumerate the valid configURLs that the IdP supports (as a list of “provider_urls” in the .well-known-file), so that it wouldn’t be possible to collude:
{
// This array size is kept small (currently at 1), so that there is not enough
// entropy to distinguish relying parties.
"provider_urls": ["https://idp.example/config.json"]
}
The JS API still requires the RP to specify the desired configURL to use, and FedCM ensures that the configURL specified in the JS API call matches one of the configURLs listed in the .well-known file:
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: `https://idp.example/config.json`,
...
}]
}
});
That solution worked generally well for a while until IdPs needed more than 1 configURLs (eg., to support multiple test and production configurations): every extra URL we allow in the providers_url array introduces an extra bit that IdPs and RPs could use to collude with each other.