summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webauthn/createcredential-cross-origin-iframe.https.sub.html
blob: ecf99f68a2b4688391ebaf4bd4be1aa79ba342df (plain)
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>