Skip to content
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

Wallet Selection in CHAPI breaks without 3rd party cookies #374

Open
samuelgoto opened this issue Nov 17, 2022 · 14 comments
Open

Wallet Selection in CHAPI breaks without 3rd party cookies #374

samuelgoto opened this issue Nov 17, 2022 · 14 comments

Comments

@samuelgoto
Copy link
Collaborator

samuelgoto commented Nov 17, 2022

This is a write down of a chat with @msporny and @dmitrizagidulin at XXV IIW.

TL;DR; Wallet selection in CHAPI is built with iframes and third party cookies. This is an exploration if FedCM can help preserve it.

Screen Shot 2022-11-17 at 10 55 40 AM

Context

You can try this yourself [here](CHAPI playground).

Steps to reproduce

  1. The user registers a Wallet
    1. The user goes to a wallet (e.g. https://demo.vereswallet.dev/home) and creates an account [1] and [2].
    2. The wallet calls the CHAPI API to have the wallet installed in CHAPI [3].
    3. The CHAPI polyfill embeds a third party iframe in the wallet frame pointing to a neutral and trusted origin: https://authn.io. [4].
    4. The code running inside the iframe uses local storage to accept the request to install the wallet [4]. In the absence of third party cookies, degrades gracefully with [10])
  2. The user goes to an Issuer
    1. The user goes to their issuer (e.g. an university, e.g. https://playground.chapi.io/issuer) and chooses to store their issuer's credential (e.g. a university diploma) into their wallet [5]
    2. The issuer calls the CHAPI API to have the credential stored into the user's wallet [6]
    3. The CHAPI JS polyfill embeds a third party iframe, again pointing at https://authn.io, [7]
    4. The third party iframe https://authn.io looks at its local third party storage to see what wallets were previously installed [8]. In the absence of third party cookies, degrades gracefully with [10])
    5. The third party iframe https://authn.io displays a list of wallets that were previously installed [8]
    6. The user chooses one of the wallets [8]
    7. The CHAPI JS API sends the credential to the selected wallet, which completes the flow [9]

Expected results

In steps (1.iv) and (2.iv): Clearly, (1.iv) and (2.iv) depend on third party cookies, so CHAPI has to degrade gracefully in its absence. The way CHAPI degrades gracefully in the absence of third party cookies is by opening pop-up windows [10] [11] [12] [13], which is not great because (a) it is a jarring user experience and (b) it reveals to the user a third party involved https://authn.io which was otherwise invisible to the user.

Screenshots

1

Screen Shot 2022-11-17 at 10 10 00 AM

2

Screen Shot 2022-11-17 at 10 10 04 AM

3

Screen Shot 2022-11-17 at 10 10 27 AM

4

Screen Shot 2022-11-17 at 10 10 46 AM

5

Screen Shot 2022-11-17 at 10 11 25 AM

6

Screen Shot 2022-11-17 at 10 11 32 AM

7

Screen Shot 2022-11-17 at 10 55 40 AM

8

Screen Shot 2022-11-17 at 10 56 04 AM

9

Screen Shot 2022-11-17 at 10 13 26 AM

10

Screen Shot 2022-11-17 at 10 10 57 AM

11

Screen Shot 2022-11-17 at 10 11 48 AM

12

Screen Shot 2022-11-17 at 10 11 42 AM

13

Screen Shot 2022-11-17 at 10 13 03 AM

@dlongley
Copy link

dlongley commented Nov 17, 2022

Other important CHAPI features for underlying primitives to consider:

  1. Credential handlers (e.g., wallets) are installed using meta data from a manifest.json file served from the credential handler's site. This allows the wallet provider to express icons and text to display in the chooser and to change their credential handler URL (whilst maintaining the same origin of course) without requiring the user to accept the changes or revisit the site directly.
  2. Relying parties can recommend credential handlers when they call the API (by specifying recommendedHandlerOrigins), which allows a credential handler to be immediately installed if the user chooses one of the recommended options. Again, this is powered via manifest.json.
  3. While CHAPI currently uses the Web Share API to integrate with native app credential handlers, we're exploring allowing manifest.json to announce an App-Claimed URL instead. This would allow native apps to appear in the wallet selection list just like Web-based credential handlers. It also seems that integration with that approach could be simpler for developers than implementing Web Share. Note: Specific protocol handlers have been avoided because they are fraught with a variety of problems with UX, security, and interop.
  4. Credential handlers specify the types of messages that they understand in manifest.json (as the "type" of WebCredential ... this specific design choice was made to "fit in" with the credential management API... see enabledTypes). So, when a request comes in to the CHAPI mediator, it can be matched against credential handlers that could conceivably process them. This keeps CHAPI protocol agnostic and allows for general extensibility without requiring additional changes to CHAPI or its mediator.

@samuelgoto samuelgoto changed the title Wallet Selection breaks in CHAPI without 3rd party cookies Wallet Selection in CHAPI breaks without 3rd party cookies Nov 17, 2022
@samuelgoto
Copy link
Collaborator Author

samuelgoto commented Nov 17, 2022

Ok, a few of us took a pass at trying to understand how CHAPI works, specifically in regards to its dependency on third party cookies.

CHAPI was designed as a polyfill for an API that could move into the browser, so, when we connected with @msporny and @dmitrizagidulin we found a massive amount of intersection and common ground between CHAPI and FedCM: it seemed like it was less of a question of "should we?" but more of question of "how?".

So, FedCM, off the shelf, is insufficient to unbreak CHAPI. So, the first pass that we took was to ask ourselves:

  1. How much would we be able to allow Wallet selection through CHAPI over FedCM with what we currently have?
  2. In what ways would it fall short from what CHAPI needs? Would those extensions conflict with FedCM's goals (e.g. privacy/tracking/security)?
  3. Would it be possible to build CHAPI over FedCM is an entirely backwards compatible way, such that we could keep CHAPI Wallets and Verifiers entirely unchanged?

So, first, terminology:

  • What I think CHAPI calls Wallets, FedCM calls Identity Providers.
  • What I think CHAPI calls Verifiers, FedCM calls Relying Parties.
  • What I think CHAPI calls Profiles in Wallets, FedCM calls Accounts in Identity Providers.

So, off the shelf, if we made every CHAPI Wallet a FedCM Identity Provider (e.g. by having them implement this API), and make CHAPI call the FedCM API during the store algorithm, then, we would be able to provide the selection of Profiles of Wallets in the following way:

const result = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://fedcm-chapi-wallet1.glitch.me/test/fedcm.json",
      // NOTE(goto): this is obviously a massive hack, but gets the job done
      nonce:  JSON.stringify({"@type": "VerificableCredential", "name": "University Diploma"}),
    }, {
      configURL: "https://webid-fcm-idp.glitch.me/test/fedcm.json",
      nonce:  JSON.stringify({"@type": "VerificableCredential", "name": "University Diploma"}),
    }, ]
  }
});

It would lead to the following UX:

Screen Shot 2022-11-17 at 11 14 05 AM

While this is a compelling proof of concept that gave both of us a good amount of confidence, this falls short in at least the following concrete ways:

  1. It requires Wallets to redeploy to expose themselves as a FedCM Identity Provider
  2. You are using nonce to pass the verificable credential, which although ugly, gets the job done
  3. The language in the UX is off: this isn't a "sign-in" moment, but rather a "add to wallet" moment. That's easily fixable with extra parameters (we are planning to do this anyway for things like making the distinction between "signing-in", "signin-up" and "continue").
  4. As opposed to CHAPI, the issuer has to enumerate all of the wallets, because FedCM doesn't support yet BYOIDP.

I think (1), (2) and (3) are easily addressable. So, I think, delta between FedCM and CHAPI is to provide (4) BYOIDP (which I'm personally excited about).

We are working on the IdP Sign-in Status API, which could potentially be used for Wallet registration. We currently don't prompt the user at IdentityProvider.login(), but we could, so that's my intuition on how we would do wallet registration.

My intuition is that inside the CHAPI polyfill that implements the following call:

const result = await CredentialManager.requestPermission();

CHAPI could call the IdentityProvider.login() call with some extra metadata:

IdentityProvider.login({
  accounts: [{
    name: "Sam",
    picture: "https://example.com/profile.png",
    ...
  }]
});

@dlongley
Copy link

@samuelgoto,

Something to be noted about CHAPI is that the messages being passed through the mediator (which you've snuck through via nonce above) are treated as simple JSON (or WebIDL dictionaries). They are not specific to verifiable credentials.

CHAPI is protocol / message agnostic in that way. And I should mention that the messages sent through CHAPI for VCs today are actually usually either "Verifiable Presentation Requests" or Verifiable Presentations (that have 0 or more VCs ... sometimes they just have a DID Authn proof, etc.).

Some flows involve returning a message that indicate that the response to the request will be done out-of-band, which is important for more complex "VC exchanges" or for passing requests off to native apps.

My point here is that any solution to point 2 should also ensure the messages are kept simple and extensible in this manner.

@dlongley
Copy link

@bvandersloot-mozilla,

I wanted to link to a comment I made in another issue where I outlined some issues we have with using the Storage Access API to implement the CHAPI polyfill components... since you brought up the prospect of using that API recently:

credential-handler/credential-handler-polyfill#33 (comment)

@johannhof
Copy link
Member

I'm personally really interested in seeing how FedCM can extend sign-in status to enable these kinds of flows! With that said, I wanted to get some clarity on the concern mentioned in credential-handler/credential-handler-polyfill#33 (comment) regarding required 1P interaction with the SAA. Per my understanding, IdentityProvider.login() would still need to be called in a top-level / 1P context, right?

@dlongley
Copy link

dlongley commented Dec 16, 2022

@johannhof,

Per my understanding, IdentityProvider.login() would still need to be called in a top-level / 1P context, right?

Yes, either that or some variant of that would still happen.

The challenge we experienced when implementing the CHAPI polyfill, which I outlined over here, was around polyfilling the part of the browser that needs to store the sort of registration information that is passed into and / or generated by that login call. When you're writing a polyfill, that info needs to be stored somewhere. And, if you want to handle the use case where a relying party doesn't know who the provider is a priori (aka "bring your own provider"), that "somewhere" needs to be some other origin that is well-known across all relying parties that use the polyfill.

@johannhof
Copy link
Member

Yeah, I think a fundamental challenge that in my impression we don't have a great answer to is the idea that there could be trusted sites that the user had no prior 1P relationship with, as expressed through a site visit/interaction or calling some API in a 1P context.

This 1P relationship seems like a pretty essential anti-abuse barrier, OTOH I think it's not that uncommon to have legitimate use cases missing it at the moment. I'd be interested in @samuelgoto's thoughts on the importance of 1P relationships in FedCM.

@msporny
Copy link

msporny commented Jan 11, 2023

there could be trusted sites that the user had no prior 1P relationship with, as expressed through a site visit/interaction or calling some API in a 1P context.

Could you elaborate on this more, @johannhof -- it's a bit too meta for me to follow. Perhaps a concrete example would help?

@hlflanagan
Copy link
Contributor

@johannhof this is something regularly handled in edu federations by having a federation operator that handles the metadata for IdPs and SPs. Federation members have to contractually agree to certain behaviors and technically use well-formed metadata.

@johannhof
Copy link
Member

there could be trusted sites that the user had no prior 1P relationship with, as expressed through a site visit/interaction or calling some API in a 1P context.

Could you elaborate on this more, @johannhof -- it's a bit too meta for me to follow. Perhaps a concrete example would help?

Yeah, apologies, though I think that this issue is actually a concrete example already. What I mean is that from a user experience perspective it's preferred that https://authn.io/ is never visited as a top-level site. It lives on several sites as an embedded service provider. However, most APIs that we've proposed so far require some degree of top-level (or first-party/1p) visit or interaction in order to be eligible to use them in an embedded (or third-party) context. This is meant to curb abuse from third parties the user has no relationship with, even (or especially) when we show prompts. authn.io is acting in the interest of the user in practice, and has a relationship with them, but that's difficult to establish for the browser without context.

@johannhof
Copy link
Member

@johannhof this is something regularly handled in edu federations by having a federation operator that handles the metadata for IdPs and SPs. Federation members have to contractually agree to certain behaviors and technically use well-formed metadata.

Huh, is there some example/documentation/blog post on how this works in more detail? It sounds like this would be affected by 3rd party cookie deprecation? Can FedCM help with that right now?

@msporny
Copy link

msporny commented Jan 12, 2023

@johannhof wrote:

authn.io is acting in the interest of the user in practice, and has a relationship with them, but that's difficult to establish for the browser without context.

Yes, exactly! Thanks for the elaboration.

@hlflanagan
Copy link
Contributor

@johannhof There's definitely interest in the higher ed federation community as to how FedCM might help the federations and how the federation metadata might help FedCM. Several people in the higher ed community are planning a hackathon FEb 28-March 1 so they can come up with more concrete feedback and recommendations.

As for how this works, this might help for high-level: https://incommon.org/federation/services/. Shibboleth is one of the more common applications to support federation in higher ed, and you can get more detail on how it gets its list of approved IdPs via the documentation here: https://shibboleth.atlassian.net/wiki/spaces/CONCEPT/pages/928645459/Metadata. Federations like InCommon or interfederations like eduGAIN supply that metadata and have policies regarding exactly who is allowed to be on the list.

Does that help?

@samuelgoto
Copy link
Collaborator Author

Just a small update to report back on this issue here, but a couple of things noteworthy occurred:

  • I presented today at the CCG an overview of FedCM and a few options on how to go about this issue (meeting notes and slides).
  • @msporny presented at the FedID CG an overview of CHAPI and how it may relate to FedCM (meeting notes and slides).

There are still more questions than answers, but it was a great way to get two communities a bit closer to one another and to get to know each other!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants