NEW262775
opening popup from Web Crypto API promise in click handler should be considered user-initiated
https://bugs.webkit.org/show_bug.cgi?id=262775
Summary opening popup from Web Crypto API promise in click handler should be consider...
tyr.asd
Reported 2023-10-06 03:48:23 PDT
For example, when implementing the PKCE protocol for OAuth2, one wants to use the Web Crypto API to generate the hash for the code challenge (https://datatracker.ietf.org/doc/html/rfc7636#section-4.2). However, Safari does prevent to open a popup window using the generated SHA-256 hash from within the promise returned by the Web Crypto API. Other browsers (e.g. Chrome, Firefox) do allow opening a popup from within the Web Crypto API promise as long as the initial click is user initiated. Example to reproduce: ``` button.onclick = function() { const dummy_verifier = Uint8Array.of(1,2,3); window.crypto.subtle.digest('SHA-256', dummy_verifier).then(hash => { const dummy_challenge = btoa(hash); window.open(`https://example.com?challenge=${dummy_challenge}`); }); } ```
Attachments
Radar WebKit Bug Importer
Comment 1 2023-10-13 03:49:13 PDT
sideshowbarker
Comment 2 2023-11-09 22:15:41 PST
Can you please explain what exactly expected behavior is? Or better yet, can you please post a minimal reproducible example? See https://stackoverflow.com/help/minimal-reproducible-example for some guidance on what needs to be included in a minimal reproducible example (that’s mostly general guidance, not specific to Stack Overflow questions, but applicable to any situation — for example, in an issue like this one — where you want others to try to reproduce some behavior you’ve observed. When I try with the following document: <!doctype html> <button>Press this</button> <script> document.querySelector("button").onclick = function() { const dummy_verifier = Uint8Array.of(1,2,3); window.crypto.subtle.digest('SHA-256', dummy_verifier).then(hash => { const dummy_challenge = btoa(hash); window.open(`https://example.com?challenge=${dummy_challenge}`); }); } </script> …and I serve that document from a local HTTP server — for example, at http://localhost:8000/index.html — and I press the “Press this” button, what I observe in all browsers, including Safari 17.2, is that the browser opens a new window to, e.g., https://example.com/?challenge=W29iamVjdCBBcnJheUJ1ZmZlcl0= That is, the behavior I observe in Safari 17.2 is no different than the behavior I observe in Firefox or Chrome. So is there some other additional behavior that I should be looking for? I mean, is there any behavior other than the new window after I click the button?
tyr.asd
Comment 3 2023-11-10 02:58:49 PST
Yes, the document you posted is exactly the minimal reproducible example I had in mind. Sorry for omitting the HTML boilerplate in my original post. And yes, the expected behavior is that the popup simply opens without being blocked. There's no additional behavior to look out for. I tested this now again with the latest publicly available versions of Safari (17.0 on Mac, as well as 17.1 on iPhone 15), which both have the issue that the popup is blocked. It would be great if this was already fixed between versions 17.0/1 and 17.2. But just to double-check: Was your test on a fresh install with default settings? Did you perhaps had your settings changed at some point to allow popups on the localhost domain, or something like that?
sideshowbarker
Comment 4 2023-11-10 04:08:41 PST
I don’t know what relevant settings I may have that are non-default, but to be clear: Does the popup blocking you’re describing only happen when you try to use window.open with a hash from window.crypto.subtle.digest, or does it also happen in other cases where you try window.open? For example, does the popup blocking in Safari also happen if you try this: <!doctype html> <button>Press this</button> <script> document.querySelector("button").onclick = function() { window.open("https://example.com"); } </script>
tyr.asd
Comment 5 2023-11-10 04:35:28 PST
the blocking does not happen in the simple case where `window.open` is called outside of the promise `.then` method. I have compiled a list of different cases: https://jsfiddle.net/tyrasd/jv12wz93/18/ On Firefox or Chrome, all cases work fine. On Safari, only the first ("direct") case works, while all other cases are blocked.
Note You need to log in before you can comment on or make changes to this bug.