-
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 IdP registration and RPs to match on a "type" #1
Comments
Would there be some list of types to consider, or would type be more of an arbitrary string? Ideally the IDP registration allows almost any IDP to show up in an RP that supports them, but with this proposal we may cause some unneeded fragmentation where each IDP could have their own 'type' which makes registration work closer to the existing FedCM flow where you need to know the IDP ahead of time. |
I would not hardcode the list, since you don't want to maintain a registry of these and really it's in the spirit of being open to just use an arbitrary string. Maybe it's more like "protocol" than "type"? Some other flavors of OAuth that come to mind off the top of my head:
In addition to there being slight differences in the actual protocols between these, there are also very different user expectations about what is possible when logging in with an IdP of these types. For example, there are tools and services you can add to your Home Assistant installation, which only make sense in the Home Assistant context. So I'd like websites to be able to make a button like this which asks the browser for the user's Home Assistant installation: It's more about avoiding a dead end user experience, since if I click "add to home assistant" and then log in with my Fediverse account, the site won't be able to do anything with the Fediverse account if the login even succeeds at all. There's another version of this which is in the enterprise space. If I visit a SaaS app, they often already have an option to sign in as an individual user, but also to use company SSO. Right now the user experience for that is pretty bad, either having the user enter their work email and doing discovery on the domain, or asking the user to enter their enterprise org subdomain. Instead, I'd like to be able to provide a "SSO" button which asks the browser for their "enterprise" IdP, which sounds a lot like another one of these types. (This is slightly different than the "open world" version since RPs and IdPs do have pre-established relationships in this context, but the list of supported IdPs at any given SaaS app is too big to put into the FedCM API call, not to mention is usually private information.) |
This is great! Love it. Thank you! I'm sympathetic to the type registry question, on both sides. I'll defer that to people who know these ecosystems better, but I'm glad it's being discussed. |
If we made the |
Right, lots of prior art with that too! XML namespaces, JSON-LD contexts, NSIDs, etc. My main question isn't what the namespace is, though, it's how do we coordinate it. Ie is the fediverse type Regardless, I know there's a ton of experience and prior art on managing this kind of taxonomy namespace, whether with or without registry, plain text or DNS or other, etc, so I'd definitely hope to lean on existing best practices and knowledge. |
@aaronpk just a heads up, there's a TONNE of changes coming to Mastodon's OAuth 2 IdP setup, and I'm working to support standardised OAuth 2 dynamic client registration (currently You can see everything I've been working on related to this here: https://github.com/mastodon/mastodon/pulls?q=is%3Apr+author%3AThisIsMissEm+sort%3Aupdated-desc |
Using a URL for the type would be fine. We'd still need to get RPs/IdPs in these clusters to agree on the URL. But that is a good candidate for being defined in a FedCM profile. For example I could easily see adding a FedCM section to the IndieAuth spec that defines the string to use here, then anyone reading that spec would know what to use. And when it's not a spec, but something like Home Assistant, they could just define it in their API docs. |
I fully agree with the premise here. I would just like to note that I've implemented various OAuth2 protocols from scratch, including OIDC, and OIDC is simply a joy to work with because it specifies so many details. If you create an OIDC OP or RP, you know it will work with other software. Plain OAuth2 does not enjoy this level of compatibility, since it's not really a protocol but a "protocol framework". So, all that to say, I love the idea of implementers being able to use whatever string they want for the type, but I think maybe there should be a small number of specified types that can be expected to work with a wide variety of implementations. |
This isn't just about the protocol, it's also about the list of acceptable IdPs and RPs. For example, even though two IdPs might support OIDC in the exact same way, the RP might only be able to actually do anything with only one of them. Going back to my original example, let's say hypothetically that both Mastodon and Home Assistant supported the exact same feature set of OIDC. We'd still need a way to have an RP ask for a Home Assistant IdP, and the Mastodon IdP should not show up in the list, because the RP is expecting to be able to do things with Home Assistant that Mastodon doesn't support. Similarly, an enterprise IdP and a university IdP might support the exact same feature set of OIDC, but an RP might only actually work with a university IdP. So this is talking me out of calling the property |
Would |
I think "federation" is too narrowly scoped. It works well for the Research+Education and Open Banking use cases. But the IndieAuth/Mastodon/Home Assistant use cases work with no pre-existing relationship between RPs and IdPs, and no common trust anchors like you would have in a federation. The only thing in common they have is the protocol and what the user expects to get out of it. I also think the relationship between SaaS app and enterprise IdP would not be described as a federation. |
Not sure I'm understanding correctly. Are you talking about Home Assistant features like APIs for doing Home Assistant things? It would be cool for that to be discoverable, but isn't it outside the scope of authentication? Please correct me if I'm misinterpreting. In terms of how to actually implement this, would it make sense to have it be a list of features that need to be supported? That way you can compose them into the features required by your RP, and any IdPs that support all the features you need would be returned. Feels somewhat analogous to OAuth2 scope. |
@npm1 started putting together a prototype (https://chromium-review.googlesource.com/c/chromium/src/+/5546318) of this proposal and we were debating this specific part of the proposal: IdentityProvider.register({
configURL: 'https://authorization-server.com/fedcm/config.php',
type: ['indieauth']
}); What occurred to me while reviewing the code was that if we follow this, the IdP wouldn't be able to change the My suggestion to @npm1 was that we should move, instead, the So, instead of the snippet below, the registration API remains: IdentityProvider.register({
configURL: 'https://authorization-server.com/fedcm/config.php'}); And then we move the {
"accounts_endpoint": "/accounts",
// .. other endpoints ...
// types of protocols this IdP speaks
"type": ["indieauth"]
} WDYT? |
Oh that's a great point, it would be convenient if the IdP could change that without requiring the user confirm it. I think this works fine with the type in the config file instead. |
Yes and no. The problem is if I can't do an OAuth flow because the browser is blocking redirects, then I have to first use FedCM before an OAuth flow will even work. If I have to first use FedCM anyway, then this provides a huge opportunity to smooth over a lot of the UX problems that exist today. Without this proposal, the RP would need to first ask the user to enter their Home Assistant URL (as they currently do today), and then start the FedCM call with the configURL based on what the user entered. I would argue the resulting user experience would be worse than it is today without FedCM. |
Can you clarify what you mean by this? I'm not sure I've ever been in this scenario. |
That's the premise of the whole thing. Eventually the browser's goal is to prevent cross site tracking including redirect-based tracking, not just third-party cookies. The unfortunate coincidence is that federated login flows like OAuth look a lot like cross-site tracking, so those will eventually get blocked too. https://developers.google.com/privacy-sandbox/3pcd/fedcm#why_do_we_need_fedcm
|
@aaronpk is their intent to block all cross domain redirects (whether via 30x Location redirects or via If so that may impact the "interaction required" concept we talked about on Friday, since that would need to do a redirect. |
The "interaction required" proposal (#590) wouldn't be affected because it would happen after the user clicks a button confirming they are trying to sign in, so the browser can un-block the redirects. |
Interesting; somehow I missed that redirects were also on the block |
@aaronpk what about |
I can live with |
Elf: what happens when the RP supports multiple "profiles" and so does the IdP? How do they choose one? |
For what it's worth, |
As long as we allow ourselves time to bikeshed and change the name before I2S, SGTM. |
Hmm I was going to use |
AI generated ideas:
From these, any preferences? I propose going with |
Throwing out some ideas in no particular order, and not even necessarily because I like all the options:
|
Nope, as implemented should be great! |
@anderspitman I haven't had a chance to update mine yet but I just merged your PR to webmention.io! |
Thanks! |
@npm1 I have LastLogin working with webmention.io, but I've run into a problem. My IdP can support multiple types of FedCM flows (currently IndieAuth and direct ID token return), but I don't see a way to figure out which flow a specific client is using. I think maybe the ID assertion endpoint needs a |
One way I could think of to possibly hack around this for now would be to smuggle the type information back in the account IDs return from the accounts endpoint. So for example if the account ID was {
"accounts": [
{
"id": "1234 - IndieAuth",
...
},
{
"id": "1234 - Solid OIDC",
...
}
]
} Then parse it out at the ID assertion endpoint. Pretty hacky though, and exposes implementation details the user probably shouldn't need to be aware of. EDIT: Actually, this would only be visible to the user if I put it in the |
Yea that was feedback I was kinda expecting heh :) I will work to add |
In the case where both the IdP and RP support multiple match types, would the browser just send the first option in the list to the IdP ID assertion endpoint? |
Or maybe all that match? It is not like the user has made a specific choice in terms of which "protocol" to use, and the RP has already said that they support "one of these", so I guess the IdP could pick arbitrarily (rather than the browser picking arbitrarily?)? |
As an IdP, I would like a little more control over which protocol is used. It can be a bit awkward to pass lists in query params though. Is there even a standard way to do that? |
I'm partially thinking out loud here, but let me see I understand you correctly. Here is one example of what the RP would request: const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: "any", // NOTE(self): maybe we can infer that configURL: any when type is provided?
type: "indieauth",
}, {
configURL: "any",
type: "solid",
}, {
configURL: "any",
type: "oauth",
}]
}
}); And then, you'd have one IdP that has been registered with the following {
"types": ["indieauth", "solid"]
} In this case, this IdP could be used either as an Does that match your intuition so far? |
It seems right now the call is rejected right away when passing multiple "any" as it is considered repeated. We can either relax this to allow multiple "any" or we can change |
@samuelgoto yeah that's basically what I'm thinking. @npm1 my instincts tell me it would be better to keep the extra flexibility of listing multiple "any" entries. At one point (see https://github.com/fedidcg/FedCM/issues/585#issuecomment-2125929920) I would have considered this very important, but I think it's less necessary since I gave up on w3c-fedid/FedCM#595. Still, maybe there could be some other utility in being able to have different client IDs for each entry. |
Ok! I think this is not currently supported, although I found crbug.com/347715555 while testing. Also filed crbug.com/347742955 and crbug.com/347740420 based on the discussions here. |
I'm wondering if we should accept an undefined Currently, webmention.io is broken because we now require both that the JS requires a On the other hand, it is not like the RP would actually be able to open a response without having a convention agreement with the IdP, so maybe type does need to be required. I'm thinking that maybe we could come up with a good default for "undefined type" that serves as a lowest common denominator (e.g. sharing a JSON response with the user's attributes) between RPs and IdPs. |
I'm not sure it's realistic to assume an undefined
webmention.io now sends |
What I meant above is that when you specify a |
By "it is broken" I mean that we (chrome) made a backwards incompatible change to the API (which we reserve the right to do - but avoid - while it is behind a flag), and in that process, we accidentally broke webmention.io. What I'm asking, which you seem to be confirming, is whether the breakage (requiring I just now added So, all in all, I think we are all good now :) @anderspitman there is a chance you'll have to update lastlogin too to add |
Ok, so, as far as I'm concerned, asides from bikesheding what to call this attribute, I think the formulation we have in chrome canaries right now seems to match what we discussed in this thread in a way that satisfies this issue. We should probably keep this issue open until this isn't merged into the spec (or learn from others trying that this doesn't work), but from a "do we know how to fix this problem" perspective, I think we have something that works well. |
@samuelgoto I believe LastLogin staging (https://lastlogin.net) is already good to go. |
This seems similar to the OpenID4VP spec patch: https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-openid4vp-profile-for-the-w. They use 'protocol', but maybe both 'type' (a granular version) and protocol (SAML, OIDC/OAuth) could be used. I guess type implies protocol, but in the simplest case I'd just want to know how to decode the request. |
…/issues/585 to handle a new scenario
Right now if you send
I don't think this case should raise an exception, since it is the same scenario in which there are no IdPs registered at all. The RP asked for IdPs of a certain type, there were none, so nothing can proceed. This is true whether or not there are IdPs of other types registered. (Also the error message implies only a single IdP can be registered which is also misleading) |
What should happen if not an exception? Currently an exception is thrown in all failure cases, like when the user cancels the request by closing the dialog, right?
Fair enough, we can improve the console error message |
Well there's a difference between an error after something has attempted to happen and nothing being possible at all. In particular, I might want to send the user through some path if they encounter a FedCM error after for example clicking their account. But if there are no IdPs available, I want to do nothing. So I need to be able to distinguish between these different error cases. Right now it is all just a generic exception. |
Hmm ok. We probably do not want to let the RP know right away whether the user has registered an IDP of a given type, for privacy reasons. If we allowed this, it may provide a fingerprinting vector to an attacker (although it would become visible the first time there is a registered provider of the types requested). But we do allow the RP to know when there was an error after clicking the account. In this case, a different type of error is thrown. It is not yet merged in the spec but hopefully soon, see w3c-fedid/FedCM#498 |
IdP registration opens up a whole new world of possibilities. However that world is very large. For the bubbles of RPs/IdPs that aren't explicit OpenID Federations, there are still bubbles defined by which protocols the RP/IdP pair can speak, even though they don't have preexisting relationships or any trust roots. For example, webmention.io expects to be able to speak IndieAuth through FedCM, and wouldn't work if you had registered a SAML IdP in the browser.
Concretely, if a user had registered a SAML provider as an IdP in the browser, it would lead to a dead end if they landed on webmention.io and the account popped up in the chooser.
The solution could be as simple as allowing arbitrary strings in a "type" property, and letting IdPs register as being able to handle that type in the register call:
Then RPs could ask for IdPs with a matching type:
This would avoid IdPs showing up in the list when they would be unable to complete an exchange with an RP.
The text was updated successfully, but these errors were encountered: