1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
<!DOCTYPE html>
<meta charset="utf-8">
<title>WebAuthn credential.create() in a cross-origin iframe tests</title>
<meta name="timeout" content="long">
<link rel="help" href="https://w3c.github.io/webauthn/#publickey-credentials-create-feature">
<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";
const targetOrigin = "https://{{hosts[alt][www]}}:{{ports[https][0]}}";
// 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>
|