-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow multiple IDPs to be used #2
Comments
@cbiesinger has put out a proposal on how to go about this here. |
We want to start tackling this problem by supporting multiple identity providers (IdPs) specified through an array in a single <script>
const cred = await navigator.credentials.get({
identity: {
providers: [
{
configUrl: "https://idp1.com/FOO.json",
clientId: "123",
},
{
configUrl: "https://idp2.com/login/BAR.json",
clientId: "456",
}
]
}
});
</script> We have also received feedback from other browser vendors that supporting multiple IdPs by combining multiple Here is a sample mock of what we want to achieve in the long term: The ‘array within Later, we also intend to enable multi-get FedCM dialogs. However, there are still many open questions such as how to group the multiple calls, how to handle aborts (e.g. what happens if a single |
Re-using Also, I don't understand how the snippet for the second after onload case works because I don't know what |
Indeed, an alternative solution we considered was using a
The initialize methods would do the work required to determine that FedCM is ok to call on this page, as well as to fetch any required parameters in order to call FedCM, like |
One solution to both of these would be to require a user activation requirement on
Why would it require an
Sure, I get that they are called synchronously from the same task. What I don't understand is how these multiple calls coordinate into a single dialog. Especially since in this example |
This would break the use case to show the prompt on initial page load. It might introduce incentives for IDPs to add page-wide listeners and show the UI on any user interaction, regardless of whether it is actually a sign in button or not.
It would if IDPs register eagerly, i.e. for the initial page load use case. They'd need to be unregistered once the user clicks on an IDP-specific sign in button.
Await would block any further execution within that function from happening sync, but it would not block the caller right? Example:
Prints
|
I'm not sure it is positive to continue supporting that use case. This especially depends on the UI treatment of this, i.e. a full door-hanger on load is very intrusive.
Is this worse than showing the UI on load?
Alternatively, allow arguments in the
🤦♂️ Yes, of course. It still feels strange to me that two consecutive statements would be dependent on each other in this way. This also raises some weird questions like what happens if |
Yeah, I agree that this is an unusual API ... I think that the desire to integrate well with the JS SDKs is what's making us consider the extra awkwardness for the benefit of making that better. If you haven't already, it is worth taking a closer look at how the major IdPs expose in their SDKs. Examples: https://developers.facebook.com/docs/facebook-login/web/
Yeah, good point, we should write down the alternatives we considered (and the ones that are still under consideration) and their trade-offs. @tttzach any chance you can share in this thread the various options we considered?
I think that the most important observation to make here is that the "coordination into a single dialog" in this proposal is made by the RP, not the JS SDKs. That is, the following block is an event listener that the RP controls and uses to coordinate across functions that are exposed by the JS SDKs. function onButtonClick() {
// deliberate calls these in parallel, as opposed to calling await,
// to allow the IdPs to all call get() without blocking each other.
FB.login(); // internally, calls await on navigator.credentials.get()
google.accounts.id.prompt(); // internally, calls await on navigator.credentials.get()
// both of these get executed and, at the end of it, the prompt shows -- before the task registered
// when the navigator.credentials.get() call was made will
// execute after the control gets passed back to the event loop.
} So, with this proposal, the following wouldn't be a concern, because the RP coordinates the calls exposed by the JS SDKs.
|
Yeah, in agreement that the current formulation is more intrusive than it should be, but I think that the use case that is serves is an important one to support: a website should be able to tell the browser that it allows users to sign-in to it declaratively upfront (i.e. without user interaction). We have been experimenting with a few other variations controlling the "volume" of the UX" (e.g. based on intent). Here is an example of "quieter" UX that I think would strike a good balance between discovery (that you can login to this website) and intrusion: |
Fair. Ideally we should aim to strike the right balance between non-intrusiveness and minimal user friction. It's hard.
It could be more disruptive if it shows up once you already thought the page was loaded instead of at the very beginning.
I wouldn't want to have a parameter that allows IDPs to exclusively show themselves in the FedCM UI. But need to think more about it.
Oh yes sorry that this was not clear enough in the comment, but right now any
Hmm that would be very disruptive to a user (unlikely to fly) since the page would become frozen. I don't think an IDP would try that. In any case we wait for IDPs until either onload (cannot stop other embedded scripts from running before that) or the end of the task (cannot force the existing task to prematurely end), so this would not work. |
Agreed :)
This is where my race condition sensor goes off, if only because I don't see a clear definition of how the dialog timing is treated in the spec. select an account is in the sequential path of the main call to This may just be cleared up with revisions for w3c-fedid/FedCM#260. |
At least for the single IDP case, I attempted to handle this in w3c/webappsec-credential-management#207. That will need to change for the multi IDP case though, as you point out. |
I guess something like an init function is inevitable to allow for RP controls if the get calls should largely be done from IDP SDKs. I don't even see how the simple IDP priority should be handled otherwise - making this depended on timing of SDK loading order (first get call wins) does not seem like a good idea. |
If you are thinking about adversarial IDPs, then having |
I was thinking of an init function called by the RP, but this could obviously be misused in case an adversarial IDP has on-site JS-Code running. But I was not really thinking about adversarial IDP / non-cooperation, but keeping things usable for RPs. 'Implicit' assumptions about call orders to various SDKs mapping to business needs may quickly become confusing (as this might just be one of them) |
Hi. Q: What happens in the case where there are many 1000's of IdPs that a user may potentially search against for the right one and then subsequently sign-in from? As a ecosystem with >5000 live IdPs worldwide the select an account experience / aka Discovery experience being discussed so far appears to be quite challenging. Insight and guidance on where to assess the experience on this welcomed. |
Hmm yea in theory a user would only have account on a very few number of the IDPs but sending 5000 requests from a single page would result in a very slow experience. If the user searches and selects an IDP from the large list, then this is not an issue. Once the user has selected an IDP, you can invoke FedCM with that IDP. Do you have concerns with the flow where the user has to first choose their IDP? |
Yes, i do have concerns given the offered UX stories so far (e.g. the quieter UX above). Existing Discovery UX can be used in front of FedCM like you describe however one would be concerned about implied / purchased / monetized / monopolized ranking of certain IdPs over others given how integrated it will be and first occurrence could dramatically skew functionality. IE show google id in chrome, mozilla persona in firefox, and microsoft's in Edge (despite being chrome) THEN others. Additionally, (and a case of me not able to exercise FedCM enough) the notion of presence of identity in the browser across tabs. I'm fine to take it as homework to read more BUT the notion of identity in the quiet UX means I'll likely have multiple signed in personas (e.g. a work one, a school one, a personal one for twitter, for github, for facebook) and they will all be available across all tabs. If so, what are the features for appropriate access to said credential(s) if I need or have a way to sign in with two different IdPs to the same site? Again, I'll take it as homework for me and welcome being pointed to the appropriate place where to read and/or exercise the implementation for such use cases. |
@teamktown We have no short/medium-term plans to offer a "global" list of IDPs. It is unlikely that RPs would want this anyway, how do they know whether to trust that random IDP has actually verified who the email address belongs to? For now we just want to allow RPs who support multiple IDPs to show them all in the same dialog. WRT the quiet UI, I don't understand what you mean with "notion of presence of identity in the browser across tabs". That UI mock is essentially just a different way to show the FedCM dialog -- the RP calls navigator.credentials.get(), we make the requests to the IDP endpoints, and show the name we get in the URL bar. Presumably the browser would show a somewhat different UI if you are signed in to multiple accounts. We have not really explored this UI very deeply yet. |
Thanks for the above comments @cbiesinger and apologies for the delay in reply.
I am trying to highlight that yes, RPs do want^h^h^h^h need this and not just a few, but hundreds to thousands of them. The discovery interface/experience for signing on is a critical aspect for R&E federations worldwide. eduGAIN represents 3600+ RPs (Service Providers) and they need an adequate experience on discovery for one's home IdP. The IdPs are spread across 80+ countries and represent a significant user population who use browsers for SSO access I'm still ramping up on the technical bits on the FedCM so maybe I'm co-mingling the quiet UI and tabs improperly as you point out. Still, as you can see by the above numbers, polling idp endpoints to the tune of 1000's per browser window and even tab, is not a scalable pattern and welcome dialogue on how this is to be scalably addressed. If there's a place to point me for this aspect of the UX for this, let me know.. |
We chatted with Ben to brainstorm ideas for multi IDP, here are the notes: https://docs.google.com/document/d/1t0QuWnjalv2NsLIr0FEcYpEV30Hp-s9KZblsQjsLZqs/edit?resourcekey=0-RvSqpV4ViFpGaXYBnKYQLw Our team is aligned about proposal 4 hitting the right balances, so I plan to write another doc explaining it more clearly. I will post that once it's done! |
I think some of the "polling to 1000s IdPs" problem can get addressed by the IdP Sign-in Status API, if we included metadata about the user there, e.g.: IdentityProvider.login({
accounts: [{
name: "Sam Goto",
email: "[email protected]",
picture: "..."
}
}]);
I'm thinking that maybe we'll need to come up with a different registration mechanism. E.g. IdentityProvider.login({
federation: "eduGAIN" /** maybe this needs to be signed somehow? **/,
accounts: [{
name: "Sam Goto",
email: "[email protected]",
picture: "..."
}}]
); Which then allows the RPs to request "identities from a specific federation", e.g. navigator.credentials.get({
identity: {
providers: "eduGAIN"
}
}); And the browser would be able to match the string "eduGAIN" between the
I wouldn't get too attached about the "quiet UI": I'm sure you won't be able to fit 1000 IdPs there. We can build larger UXes based on cardinality and user intention / gestures. |
@npm1 - thank you for the gdoc !
While some of these references go way back, the state of things has not changed a lot -- discovery is challenging to do well and supportive of the users needs. To @samuelgoto above on his comments
The comments above on the API trickle through to rolling up all idps into one 'label' -- it's hard, it needs more insight to be assistive to the user to avoid the pitfall of inappropriately masking/dropping things or making sign-on more difficult than it should be. |
User agent UI is not something that is generally specified. It is up to each user agent how they want to surface their UI. But I'll keep this in mind for the doc I'm working on, to include more visual aspects.
The CG has been working on https://github.com/fedidcg/use-case-library. These are not specific to multi IDP scenario though so I can take a look at the linked resources.
I don't know that FedCM could replace all existing discovery mechanisms. I would want to know which ones currently do not work well or are rely on third party cookies as those would be the most urgent ones to have an API for. |
@bvandersloot-mozilla it is arguably a bit weird to also use |
I agree it is a little weird, but it makes some sense. It is effectively saying "get an identity credential using the providers you already know about, but with this ordering hint, and show a prompt at a deferred time". I also think that all calls to get() should return a promise that may resolve to an IdentityCredential. A selected IdentityCredential would be resolved if the client is in the list of providers for that call or there is no list of providers. So the RP and chosen IDP would get the Credential. |
I think it would be highly beneficial to have a few concrete examples for the cases. These I guess the point is that it should work in any scenario + you can use the get call for additional business logic using the providerOrder and further potential extensions of this (scope ..., sign-in or sing-up) |
Yea that is part of why I think the ordering |
@asr-enid :
Exactly. s/IDP/IDP-script-callsite/g.
Single-IDP, gesture: Login with Facebook button on a page that a user clicks to activate @npm1 : I think it might be reasonable to have the credential sent to multiple gets in the case of multiple-IDP and user-interaction. You might want the registration I'd be fine to change semantics so that an ordering-specific |
Here is the doc I had promised with a little more detail about the proposal born out of the meeting a few weeks ago. I haven't given a lot of thought to the ordering. Having it be specified via a https://docs.google.com/document/d/171zldBKTqts0zKtCMSMv-eexGmXpTdzh5IiPYKZSTOQ/edit# |
Just to report back here, I presented the above proposal to the Google Identity Services team and it made me think that perhaps the API making explicit separation of the user interaction use case vs non-interaction is perhaps not worth it? Their feedback was "We wouldn't know whether there is user interaction at the time our API is called, so we'd just try to invoke the API in user interaction mode [this assumes that when such invocation occurs, it degrades to a delayed/non-interaction if there is actually no user interaction]." So I'm now thinking perhaps we need to rethink? |
This was discussed in the call today: notes. Just wanted to add here some thoughts/ideas that were surfaced during the call:
|
My current thinking is that we should go with option 2 from the doc:
Based on the above points, I believe option 2 accompanied with a separate method for IDP ordering would strike the right tradeoffs: it would enable sufficient RP control for those who have strong opinions on which IDP they'd prefer, but it would also enable hands-off RPs to successfully use FedCM by just embedding IDP SDKs. Let me know what you think! |
I think there is probably a way to write the spec that doesn't include referencing the specifics of the
Given this, I think that is probably the way forward. How about instead of "the |
Seems your reply cut off suddenly, but agree that perhaps we can give some leeway to the user agent instead of specifying precisely when the UI should be shown.
All of these suggestions sound good to me. Having the bar 'show at least after onload' achieves the goal of enabling all IDPs to register while preserving flexibility on the timing. This coupled with RP provided ordering seems like a good path forward. I like how this is shaping up! |
Ignore that fragment- my editing skills are poor. I incorporated that point into the below quote
👍
|
Some updates for the record (this has been discussed in FedID CG calls):
|
I gave this a quick test in my testbed using 2 IdPs. Outcomes below:
|
I ensured to disable the button mode feature, and I no longer get that specific popup. My only issue now would be. If I am logged out of both, it asks me which to sign in with (which is fine, although now I am confused with the button flow). But once I have selected one to use, when I try to initiate FedCM again the choice is gone, and it just uses what I last choose (somehow). |
I did find some problem with that flag. I filed https://issues.chromium.org/issues/324102291 which might be what you encountered (button-like behavior despite not using the button mode in the get() call).
Yes, that is indeed how it works. In the widget mode, you only get a login url in the mismatch case. In addition, once you get that mismatch the IDPs have their login status set to logged out. So only the IDP you login to will have their status changed to login. If you go try FedCM again right away you will only see that IDP since its status is logged in whereas the other has status set to logged out. |
Want to provide a concrete update on the Chrome side. We are planning to do an Origin Trial for the specific version of the problem where we allow a single |
When a RP supports multiple IdPs , eg: choice 1,2, 3 ... N , if the user has active sessions at IdP 1 but has an account at IdP3 that the browser is not aware of, the user should not only be presented IdP 1 but also see that there are other options so that they can discover that they could use IdP 3. |
We have the 'use a different account' feature, it is currently in the button mode OT but I can see it potentially being used in widget mode as well when we have to show some UI anyways. I think that would address your issue. |
Discussed at TPAC 2024 https://github.com/fedidcg/meetings/blob/main/2024/2024-09-24-TPAC-notes.md#multi-idp-to-stage-2 Proposal advanced to Stage 2 |
Currently the spec does not because it follows closely the implementation, but it should not be hard to fix this. Basically: iterate over all the providers, and perform all of those fetches. Wait for all before producing a UI which contains all of them.
The text was updated successfully, but these errors were encountered: