-
Notifications
You must be signed in to change notification settings - Fork 73
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
Iframe-origin in the FedCM UX is sometimes not meaningful to users #449
Comments
For this proposal, let top frame origin be https://top-frame.example/, RP iframe origin be https://iframe.example and IDP origin be https://idp.example. top-frame.example embeds iframe.example with proper permissions policy that allows the iframe to call FedCM API. Matched clientsAny application that uses OAuth 2.0 must have authorization credentials i.e. a client ID which identifies the application to the IdP server. When a top frame has the same client ID as the iframe (RP) that calls FedCM API, the top frame is considered a matched client to the RP. In this case showing both the top frame domain and iframe domain can unnecessarily confuse users without gaining privacy/security benefits. Given that the top frame domain is the one that users see in the URL bar, omitting the iframe domain could lead to better UX. Note that “client ID” is just one possible way to tell whether the top frame is a matched client to the RP iframe, IdPs may have other mechanisms to check it. e.g. same-site frames could also be a factor to some IdPs. How to use matched clientsThe proposal is to use this as an indication for whether we should only show two domains (top frame and IdP) or show all three domains (top frame, iframe and IdP). How to determine matched clientsThe browser currently sends the iframe origin as the
This would provide the IdP sufficient information to check whether the clientID matches not only the Origin header (which the IdP should always do) and hence the child frame origin, but also the top frame origin. e.g. when an RP registered two different origins or domains for themselves, they should be issued the same client ID by the IdP if those domains are for the same RP. Then the IdP can look up the two origins to check if they belong to the same RP. Then in the client metadata fetch response, the IDP would specify an optional boolean parameter
And the browser can use Security and privacy considerationsTechnically speaking this proposal provides a new way for an embedded iframe to learn the origin of the top frame. In particular, an iframe could call FedCM with their own fake IdP that receives both the iframe origin and the top frame origin. However, for a cross-origin iframe to call FedCM API, by design the top frame must allow it explicitly by specifying the permissions policy “identity-credentials-get”. It is already possible today in some browsers for an iframe to learn the top frame’s origin via ancestorOrigins. While Firefox has concerns about Another new entropy this proposal adds is that it technically provides a way for anyone to query the association between two origins with a specific client id using curl. e.g. https://foo.example/ registered themselves to an IdP with From Chrome privacy’s perspective, we believe that showing less confusing UIs could help users to make more meaningful decisions when prompted to continue with FedCM. Technically, the IdP can lie about the new boolean. However, omitting the iframe domain when it’s not supposed to could put the IdP at risk because it’s the iframe who receives the token with sensitive information. For legitimate IdPs this is definitely not in their interest. For bad acting IdPs, they have to collude with the top frame to explicitly use the permissions policy to use FedCM, but in case of collusion, the bad actor does not need to use an iframe at all. Interoperability and compatibility considerationsAs noted in the beginning, this issue may not be browser-agnostic because it’s a string issue on the browser UI. For browsers who don’t have this issue, the proposal is completely optional and backwards compatible. For browsers who share the same issue, we believe that the proposal is designed in an interoperable manner. Considered alternativesCheck matched client from the browser sideInstead of the browser sending both the top frame origin and iframe origin to the IdP, the IdP can return a list of origins that are “matched” in the client metadata fetch response. Then the browser can try matching the top frame origin from that list to see if it’s matched. However, there are some drawbacks of this alternative:
Using different permissions policiesWe could introduce two different permissions policies for FedCM in cross-origin iframes: “identity-credentials-get-include-iframe-domain” and “identity-credentials-get-omit-iframe-domain” to give the control to the top frame. However there are some drawbacks:
|
@martinthomson @cboozar @bvandersloot-mozilla
|
To me, it seems confusing to say, 'the clientID matches not only the Origin header...', the client_id can be any string, not necessarily related to an origin. From the later text, it seems client_id is used to locate registered origins related to a client (something equivalent to what Google stores about OAuth2 clients, namely; 'Authorised JavaScript origins'). Maybe that could be clarified in the text (if I am not wrong about it). I would not imagine every OAuth2 (or OIDC etc) authorization server would store an equivalent to 'Authorised JavaScript origins'. I do not think it is part of any OAuth2/OIDC registration spec? This would mean this would need to be specified as a FedCM registration extension for it to be widely used. |
Totally agree. We deliberately chose the phrase "client matches top" just to give IdPs more flexibility to determine "match". It does not necessarily get narrowed down to using "client ID". e.g. client ID may not needed at all in the process because IdP can look up the two origins and determine if the browser can skip showing one of them. |
On the call (notes), a suggestion was made to consider using First Party Sets (FPS) to solve this problem. That is, the user agent would check whether the iframe and the top-level embedder are members of the same FPS to determine whether to show two or three domains in the UI. The benefit of this would be that it would not require introducing a new API. With FPS now shipping in Chrome, Chrome could use FPS as the solution. We took the AI to ask FPS folks what they think and the consensus seems to be leaning towards not using FPS for the following reasons:
Tagging @johannhof @krgovind in case they want to share their thoughts from the FPS side! |
Thanks for summarizing, @npm1! I agree with your assessment. Interoperability should definitely be a consideration here. The only other proposed integration of FPS on the platform today is with the Since it appears that RPs already register their list of related sites with their trusted IDPs; I believe the purpose that FPS serves for the cross-site cookie access use-case (i.e. provide a platform mechanism for site authors to declare collections of related sites) is already superseded by that existing mechanism. It makes sense to leverage that. |
(This all assumes cross-site cookie blocking or isolation.) I'm happy with the conclusion about FPS, though I had a shorter path to reach it :) I think that the model this should use is the one we adopted for permissions policy, which this API already uses. That is, if a top-level context wants to delegate permission, then it can do so. But the effect of that is that they are responsible for the effects of that. So maybe this is really api.mallacoota.example.net asking rather than example.com, but the user doesn't need to care about that distinction. The information is transferring to the example.com partition of browser state and that is what really matters, not who they contract with to manage a given component of their site. The challenge then is the accountability at the IdP end. The IdP will report access from some obscure site, which isn't ideal. So, we can tell them the origin from the top-level context. Then they can report that. We can make the automated availability of that datum a non-negotiable part of the contract when the top-level site allows the use of this API in a given frame. There is no privacy risk there because sites can already arrange to make that information available if they chose to. The proposed design pushes that work back on sites, which is annoying for them and provides no privacy advantage. So my suggestion is that we decorate these fetches as follows (precise spelling TBN):
You might notice that this has more general applicability. We don't do this now, so we probably shouldn't start without sites asking us to, but we can definitely do that here. (This idea of matched clients using client ID makes no sense to me. That two sites might have the same client ID with a given IdP is not information that a browser can - or should - be making decisions based on.) |
I generally agree with Martin that using the permission delegation pattern (i.e. showing only the top-level) here is a good default for FedCM. In most cases it's most intuitive for the user and most correct from a privacy perspective, as delegation ensures collaboration between the top-level and the embed. But I can also see the point that this is confusing to users in some situations. However, both FPS and the client ID idea seem a bit too... indirect for my taste, deriving this kind of UI based on tangential relationships between sites can be hit-and-miss. It seems like the embedded frame should have enough context to decide whether to show this UI or not on its own, no? Is there some way we can delegate this decision to the API caller, like an argument or a configuration somewhere? The additional header comment seems reasonable as well but I haven't spent a lot of time thinking about it :) |
Thanks for the feedback, @martinthomson! I do agree that it is a bit awkward for the user agent to trust the IDP with the task of attesting that two origins are the same client. That said, having a Permissions Policy be the solution for this is not something we would be supportive of because it is possible for an attacker to grant itself permissions via the HTML injection attack. This was one of our motivations for this feature, as well as for displaying three origins by default instead of two. That said, @RByers suggested that perhaps we can just change the solution slightly so that JavaScript must be called in order for the embedder to grant permission. That is, we'd have a JS call that the embedder needs to call to grant its iframe permission to use FedCM. This could be in addition to or in replacement of the existing API:
What do you think? We're also waiting for @yi-gu to come back from vacation as he's been driving this API and will have thoughts :) |
HTML injection is why we have CSP. I'm not convinced that that motivates poor UX. This permission delegation attack (with script access, many things are possible) is real, but I don't think that it is our business to come up with a solution to it here. |
Some clarifications to make sure that folks are on the same page: The security issueIt's true that CSP or strict CSP can disable Javascript access for an HTML injection attacker. However, it does not forfeit the ability to run Javascript in a cross-origin iframe. e.g. an attacker can inject The victimsThe main victims in this type of attack are users and IdPs as oppose to the embedder site. e.g. a well recognized website got attacked. Without a proper browser UI, e.g. omitting the iframe domain "evil.example", a user will see "Sign in to well-recognized-website.example with idp.example". Since the user is visiting the website and trusts both the top frame and the IdP, it's likely that they will click the "Continue" button on the FedCM UI. The consequence of that action is that the sensitive data (e.g. an id token) will be shared with the attacker without user/IdP knowing it. Considered solutionsOption 1: Multiple permission policiesThis was the first solution that came to us for this Github issue. e.g. the top frame could use Option 2: Enforce header policyWe could ask websites that want to support FedCM in cross-origin iframes to use the header: There are some concerns:
Option 3 Enforce Permissions Policy via JavaScriptAs mentioned in the last comment, we can support FedCM in cross-origin iframes if and only if the permissions policy is set by Javascript (which is protected by CSP in case of HTML injection). Some common concerns shared with the previous option:
Option 4: no dependency on the website (this proposal)Note that all the options listed above are similar in a way that they all require the top frame to do the right thing (using proper policy/header/JavaScript) while the top frame may not even be the RP that receives the token. On the other hand, the cost of them NOT doing the right thing would be paid by users and IdPs. e.g. if UA always shows 3 domains (top frame, iframe, IdP), users will be confused; if UA omits iframe domain improperly (due to top frame's mistake), users may grant permission unintentionally and IdP would leak the sensitive user information unexpectedly. That's why we proposed to solve this problem from UA level instead of the website level. Because UA knows about the origin that the user is visiting and the origin that calls FedCM, it can provide the information accurately to the potential victim IdP such that the IdP could speak up to protect their users. Some extra notes:
|
Option 5: open an issue on the permissions policy repository and solve the problem for everyone and for every feature for which this might be is a problem. A CSP directive is my preferred approach. |
Thanks @martinthomson, FWIW I agree 100% with your perspective here. Yi has looped me into the discussion with our security teams and we'll follow up here once we have a conclusion from that. |
Hi folks. To report back, here are the updated proposal after some further discussions:
At the moment we propose to keep the FedCM API as-is and leave the exact UI to browsers. Given that the policy Closing this issue for now and feel free to reopen it if you have further concerns or questions. |
Some websites delegate authentication to a cross-origin iframe that they own. e.g. ebay.com embeds ebaystatic.com where FedCM API is invoked from. Showing the iframe domain unnecessarily confuses users because they trust eBay (the RP) and are not familiar with ebaystatic.com (the domain). e.g. a user will likely be confused when they see the following UI while visiting ebay.com
The text was updated successfully, but these errors were encountered: