| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>WebAuthn credential.get() in a nested frame</title> |
| <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="/resources/common-inputs.js"></script> |
| <script src=helpers.js></script> |
| |
| <body></body> |
| <script> |
| |
| standardSetup(async function () { |
| "use strict"; |
| |
| let credential; |
| function getCredentialScript() { |
| // Convert the credential ID into a string that can be safely embedded |
| // into our get assertion script. |
| // First, turn the buffer into a byte string. |
| const idBytes = String.fromCharCode(...new Uint8Array(credential.rawId)); |
| // Then, encode it into base64 so it can be safely embedded as a string. |
| const id = btoa(idBytes); |
| return ` |
| try { |
| // Reverse the process: decode the embedded string into a byte string. |
| const decoded = atob("${id}"); |
| // Then, copy each byte into a Uint8Array that we can pass to WebAuthn. |
| const id = Uint8Array.from([...decoded].map(c => c.charCodeAt())); |
| navigator.credentials.get({ |
| publicKey: { |
| challenge: Uint8Array.from([]), |
| allowCredentials: [{type: "public-key", id}], |
| userVerification: "discouraged", |
| } |
| }).then(c => window.parent.postMessage("OK", "*")) |
| .catch(e => window.parent.postMessage("Error: " + e.toString(), "*")); |
| } catch(e) { |
| window.parent.postMessage("Error: " + e.toString(), "*"); |
| } |
| `; |
| } |
| promise_test(async t => { |
| credential = await createCredential(); |
| }, "Setup: create a credential to test with"); |
| |
| promise_test(async t => { |
| let frame = document.createElement("iframe"); |
| const loadPromise = new EventWatcher(t, frame, "load").wait_for("load"); |
| document.body.append(frame); |
| await loadPromise; |
| frame.contentWindow.location = "javascript:" + encodeURI(getCredentialScript()); |
| |
| const messageWatcher = new EventWatcher(t, window, "message"); |
| const { data } = await messageWatcher.wait_for("message"); |
| assert_equals(data, "OK"); |
| }, "navigator.credentials.get({publicKey}) in a javascript url should should succeed."); |
| |
| promise_test(async t => { |
| let frame = document.createElement("iframe"); |
| const loadPromise = new EventWatcher(t, frame, "load").wait_for("load"); |
| frame.srcdoc = ""; |
| document.body.append(frame); |
| await loadPromise; |
| frame.contentWindow.eval(getCredentialScript()); |
| |
| const eventWatcher = new EventWatcher(t, window, "message"); |
| const { data } = await eventWatcher.wait_for("message"); |
| assert_equals(data, "OK"); |
| }, "navigator.credentials.get({publicKey}) in srcdoc should succeed."); |
| |
| promise_test(async t => { |
| let frame = document.createElement("iframe"); |
| const loadPromise = new EventWatcher(t, frame, "load").wait_for("load"); |
| frame.src = "about:blank"; |
| document.body.append(frame); |
| await loadPromise; |
| frame.contentDocument.write("<script>" + getCredentialScript() + "<\/script>"); |
| |
| const eventWatcher = new EventWatcher(t, window, "message"); |
| const { data } = await eventWatcher.wait_for("message"); |
| assert_equals(data, "OK"); |
| }, "navigator.credentials.get({publicKey}) in about:blank embedded in a secure context should succeed."); |
| |
| promise_test(async t => { |
| let frame = document.createElement("iframe"); |
| const eventWatcher = new EventWatcher(t, window, "message"); |
| frame.src = "resources/webauthn-subframe.sub.html"; |
| document.body.append(frame); |
| assert_equals((await eventWatcher.wait_for("message")).data.type, "subframe-loaded"); |
| |
| frame.contentWindow.postMessage({ type: "get-credential", addUserActivation: false }); |
| const { data } = await eventWatcher.wait_for("message"); |
| assert_equals(data.result, "success", "Error: " + data.error); |
| }, "navigator.credentials.get({publicKey}) in a same-origin frame should succeed without requiring user activation."); |
| |
| }, { |
| protocol: "ctap2_1", |
| }); |
| </script> |