W3C home > Mailing lists > Public > public-webauthn@w3.org > August 2022

Re: [webauthn] Cross-origin credential creation in iframes (#1656)

From: Stephen McGruer via GitHub <sysbot+gh@w3.org>
Date: Thu, 18 Aug 2022 16:14:33 +0000
To: public-webauthn@w3.org
Message-ID: <issue_comment.created-1219682589-1660839271-sysbot+gh@w3.org>
_TL;DR - the Web Payments WG would like to propose allowing credential creation in a cross-origin iframe, as long as the iframe has both a publickey-credentials-create permission policy and a user activation (e.g., click)._

Hi folks,

On behalf of the Web Payments Working Group, I am reaching out to reopen the discussion around allowing credential creation in a cross-origin iframe. (More accurately, in a browsing context that is not same-origin with its ancestors).

To be clear from the start (since this has been a confusing point), the intention is to allow for the following setup:

1. The top-level frame is https://merchant.example/
1. The top-level frame embeds an iframe to https://psp.example/.
1. Within the https://psp.example/ iframe, psp.example takes the user through some authentication flow (to their own standards), e.g., username/password.
1. Once psp.example is happy they have authenticated the user to their liking, they wish to create a WebAuthn credential for the user in order to provide a smoother experience in the future.
    1. JavaScript code within the https://psp.example/ iframe calls `navigator.credentials.create({publicKey:...})`, which (after the usual flow) creates a credential **for psp.example**.

There is no creation of a credential for another origin.

(Note that the above example implies a Payment Service Provider (PSP) being involved; one could equally imagine a bank doing similar, e.g. replace psp.example with bank.example).

We have heard from many payment industry folks, both on this issue and in the WPWG, that enrolling users within an embedded flow is important to them. In the payments world, not breaking the ongoing payment is critical to a good user experience, and so there is a delicate balance to walk when trying to improve for a future good experience (that is, by enrolling the user's authenticator device).

From this thread and [its precursor](https://github.com/w3c/webauthn/issues/1336), we have heard the following concerns:

1. There is an existing tracking concern with cross-origin get(), in which a tracker may track a user that is visiting another top-level website by initiating navigator.credentials.get() from a cross-origin iframe, and trick the user into completing it.
    1. This concern already exists today, but we acknowledge it is made worse by allowing create() in a cross-origin iframe, as the user would no longer need to have visited the tracker in a top-level frame previously (in order to enroll the credential) - the tracker could begin the attack directly from an iframe.
    1. For this, our proposal (see below) includes an additional requirement of having a user activation (e.g., click) when creating a credential in a cross-origin iframe. This does not fully defeat the attack, but does raise the bar to a level we hope is acceptable.
1. That regulations may have requirements around the gathering of personally identifiable information and obtaining user consent for such.
    1. With respect, we do not believe this is relevant to the technical ability to add this feature to the specification. Each company that uses this feature would be (as always) responsible for ensuring that they meet regulatory requirements.
    1. There is also nothing that stops the embedded content from informing the user and collecting user consent. They can render privacy policy links, user consent dialogs, etc, all in the embedded iframe.
1. That credentials shouldn't be creatable for a different origin than the current one.
    1. We completely agree. That is not this proposal, nor what this issue was ever about - we believe that was a mistaken understanding.

## The Proposal

Allow the creation of a WebAuthn credential in a frame in which sameOriginWithAncestors is false, **if and only if**:

1. The frame has a publickey-credentials-create permission policy set on it, **AND**
1. The frame has a user activation

The first of these requirements protects the top-level frame against malicious iframes. The second of these requirements attempts to protect the user against a compromised or collaborating top-level frame allowing an iframe to try and trick the user.

Draft PRs adding this support can be found at [#1](https://github.com/stephenmcgruer/webauthn/pull/1) and [#2](https://github.com/stephenmcgruer/webappsec-credential-management/pull/1), though we encourage their use only as a clarity aid rather than a finished product.

It may also be reasonable for the client or authenticator device to make it clearer to the user that the credential creation is happening in an embedded context. For example, the client may have text like "rp.example, embedded in merchant.example, wants to verify your identity". We think that the WebAuthn specification allows for clients to do this already if they wish, but if not we would be happy to see WebAuthn (or FIDO) expanded to allow this.

## FAQ

**What if I (an RP) don't want to create credentials in an iframe?**

Firstly, and to be clear again - this proposal is only allowing the RP to initiate credential creation inside an RP-origin iframe, so it is the RP's code that is choosing to call create().

If the RP is concerned about themselves doing so 'accidentally', e.g. if a website puts the RP inside an iframe when they are not expecting it, they have three options:

1. Serve their content with an [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) header of either DENY or SAMEORIGIN, which will stop their content from being embedded this way.
1. Attempt to detect whether they are in a cross-origin iframe via JavaScript before calling create(). (There are a variety of ways to do this checking, and I don't want to endorse any particular option as the 'correct' way!)
1. After creation of the credential, check the `crossOrigin` member of the returned [collectedClientData](https://w3c.github.io/webauthn/#dictdef-collectedclientdata). This will be `true` if the create() call was within a cross-origin iframe.
    1. Note that this is an after-the-fact check, and so may still have had consequences, e.g. if the RP was creating a discoverable credential (it may have overridden a previously existing credential on the authenticator device).

GitHub Notification of comment by stephenmcgruer
Please view or discuss this issue at https://github.com/w3c/webauthn/issues/1656#issuecomment-1219682589 using your GitHub account

Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Thursday, 18 August 2022 16:14:35 UTC

This archive was generated by hypermail 2.4.0 : Thursday, 18 August 2022 16:14:37 UTC