diff options
Diffstat (limited to 'dom/webauthn/tests/test_webauthn_authenticator_transports.html')
-rw-r--r-- | dom/webauthn/tests/test_webauthn_authenticator_transports.html | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/dom/webauthn/tests/test_webauthn_authenticator_transports.html b/dom/webauthn/tests/test_webauthn_authenticator_transports.html new file mode 100644 index 0000000000..0d6e6d3055 --- /dev/null +++ b/dom/webauthn/tests/test_webauthn_authenticator_transports.html @@ -0,0 +1,165 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<head> + <title>W3C Web Authentication - Authenticator Transports</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="u2futil.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + + <h1>W3C Web Authentication - Authenticator Transports</h1> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a> + + <script class="testbody" type="text/javascript"> + "use strict"; + + add_task(async () => { + await addVirtualAuthenticator(); + }); + + function arrivingHereIsGood(aResult) { + ok(true, "Good result! Received a: " + aResult); + } + + function arrivingHereIsBad(aResult) { + ok(false, "Bad result! Received a: " + aResult); + } + + function expectNotAllowedError(aResult) { + ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult); + } + + function expectInvalidStateError(aResult) { + ok(aResult.toString().startsWith("InvalidStateError"), "Expecting a InvalidStateError, got " + aResult); + } + + // Store the credential and transports of the first successful make credential + // operation so we can use them to get assertions later. + let gCredential; + let gTransports; + + // Start a new MakeCredential() request. + function requestMakeCredential(excludeCredentials) { + let publicKey = { + rp: {id: document.domain, name: "none"}, + user: {id: new Uint8Array(), name: "none", displayName: "none"}, + challenge: crypto.getRandomValues(new Uint8Array(16)), + timeout: 5000, // the minimum timeout is actually 15 seconds + pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], + excludeCredentials + }; + + return navigator.credentials.create({publicKey}); + } + + // Start a new GetAssertion() request. + function requestGetAssertion(allowCredentials) { + let publicKey = { + challenge: crypto.getRandomValues(new Uint8Array(16)), + timeout: 5000, // the minimum timeout is actually 15 seconds + rpId: document.domain, + allowCredentials + }; + + return navigator.credentials.get({publicKey}); + } + + // Test make credential behavior. + add_task(async function test_make_credential() { + // Make a credential. + await requestMakeCredential([]) + // Save the credential for later. + .then(res => { + gCredential = res.rawId; + gTransports = res.response.getTransports(); + }) + .then(arrivingHereIsGood) + .catch(arrivingHereIsBad); + + // gTransports should be "a sequence of zero or more unique DOMStrings in lexicographical order." + for (let i = 0; i < gTransports.length - 1; i++) { + if (gTransports[i] >= gTransports[i+1]) { + ok(false, "getTransports() should return a sorted list"); + } + } + + // Pass a random credential to exclude. + await requestMakeCredential([{ + type: "public-key", + id: crypto.getRandomValues(new Uint8Array(16)), + transports: gTransports, + }]).then(arrivingHereIsGood) + .catch(arrivingHereIsBad); + + // Pass gCredential with transport=usb. + // The credential already exists, and the softoken consents to create, + // so the error is InvalidState and not NotAllowed. + await requestMakeCredential([{ + type: "public-key", + id: gCredential, + transports: ["usb"], + }]).then(arrivingHereIsBad) + .catch(expectInvalidStateError); + + // Pass gCredential with transport=nfc. + // The softoken pretends to support all transports. + // Also, as above, the credential exists and the token indicates consent. + await requestMakeCredential([{ + type: "public-key", + id: gCredential, + transports: ["nfc"], + }]).then(arrivingHereIsBad) + .catch(expectInvalidStateError); + + // Pass gCredential with an empty transports list. + // As above, the token indicates consent, so expect InvalidStateError. + await requestMakeCredential([{ + type: "public-key", + id: gCredential, + transports: [], + }]).then(arrivingHereIsBad) + .catch(expectInvalidStateError); + }); + + // Test get assertion behavior. + add_task(async function test_get_assertion() { + // Request an assertion for gCredential. + await requestGetAssertion([{ + type: "public-key", + id: gCredential, + transports: gTransports, + }]).then(arrivingHereIsGood) + .catch(arrivingHereIsBad); + + // Request an assertion for a random credential. This should be + // indistinguishable from the user denying consent for a known + // credential, so expect a NotAllowedError. + await requestGetAssertion([{ + type: "public-key", + id: crypto.getRandomValues(new Uint8Array(16)), + transports: ["usb"], + }]).then(arrivingHereIsBad) + .catch(expectNotAllowedError); + + // Request an assertion for gCredential with transport=nfc. + // The softoken pretends to support all transports. + await requestGetAssertion([{ + type: "public-key", + id: gCredential, + transports: ["nfc"], + }]).then(arrivingHereIsGood) + .catch(arrivingHereIsBad); + + // Request an assertion for gCredential with an empty transports list. + await requestGetAssertion([{ + type: "public-key", + id: gCredential, + transports: [], + }]).then(arrivingHereIsGood) + .catch(arrivingHereIsBad); + }); + </script> + +</body> +</html> |