Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>WebAuthn credential.create() in a cross-origin iframe tests</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src=helpers.js></script>
<body></body>
<script>
standardSetup(function() {
"use strict";
// Returns a |Promise| that gets resolved with |event.data| when |window|
// receives a "message" event whose |event.data.type| matches the string
// |message_data_type|.
function getMessageData(message_data_type) {
return new Promise(resolve => {
function waitAndRemove(e) {
if (!e.data || e.data.type != message_data_type)
return;
window.removeEventListener("message", waitAndRemove);
resolve(e.data);
}
window.addEventListener("message", waitAndRemove);
});
}
// Creates an iframe with the given `src` and (optional) allow attribute.
// Waits for the iframe to load, based on receiving a "subframe-loaded"
// message from the iframe.
async function createIframe(test, src, allow) {
const iframeElement = document.createElement("iframe");
document.body.appendChild(iframeElement);
test.add_cleanup(() => {
iframeElement.remove();
});
if (allow !== undefined) {
iframeElement.allow = allow;
}
const loadedPromise = getMessageData("subframe-loaded");
iframeElement.src = src;
await loadedPromise;
return iframeElement;
}
promise_test(async (test) => {
const src = `${targetOrigin}/webauthn/resources/webauthn-subframe.sub.html`;
const iframe = await createIframe(test, src);
const resultPromise = getMessageData("result");
iframe.contentWindow.postMessage({type: "create-credential"}, {targetOrigin: targetOrigin});
const data = await resultPromise;
assert_equals(data.result, "failure");
assert_equals(data.error.name, "NotAllowedError");
}, "create() in cross-origin iframe fails without permissions policy");
promise_test(async (test) => {
const src = `${targetOrigin}/webauthn/resources/webauthn-subframe.sub.html`;
const iframe = await createIframe(test, src, "publickey-credentials-create");
const resultPromise = getMessageData("result");
iframe.contentWindow.postMessage({type: "create-credential", addUserActivation: false}, {targetOrigin: targetOrigin});
const data = await resultPromise;
assert_equals(data.result, "failure");
assert_equals(data.error.name, "NotAllowedError");
}, "create() in cross-origin iframe fails with permissions policy but no user activation");
promise_test(async (test) => {
const src = `${targetOrigin}/webauthn/resources/webauthn-subframe.sub.html`;
const iframe = await createIframe(test, src, "publickey-credentials-create");
const resultPromise = getMessageData("result");
iframe.contentWindow.postMessage({type: "create-credential", addUserActivation: true}, {targetOrigin: targetOrigin});
const data = await resultPromise;
assert_equals(data.result, "success", `Expected success but got error: "${data.errorMessage}"`);
}, "create() in cross-origin iframe succeeds with permissions policy and user activation");
promise_test(async (test) => {
const src = `${targetOrigin}/webauthn/resources/webauthn-subframe.sub.html`;
const iframe = await createIframe(test, src, "publickey-credentials-create");
// For this call, we have a user activation in this main frame, but not
// in the iframe. That shouldn't be sufficient - the user activation has
// to be on the iframe itself.
await test_driver.bless("create credential, main frame activation");
const resultPromise = getMessageData("result");
iframe.contentWindow.postMessage({type: "create-credential", addUserActivation: false}, {targetOrigin: targetOrigin});
const data = await resultPromise;
assert_equals(data.result, "failure");
assert_equals(data.error.name, "NotAllowedError");
}, "create() in cross-origin iframe requires user activation on the iframe, not the main frame");
});
</script>