test_webauthn_authenticator_transports.html (5700B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <head> 4 <title>W3C Web Authentication - Authenticator Transports</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script type="text/javascript" src="u2futil.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 8 </head> 9 <body> 10 11 <h1>W3C Web Authentication - Authenticator Transports</h1> 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a> 13 14 <script class="testbody" type="text/javascript"> 15 "use strict"; 16 17 add_task(async () => { 18 await addVirtualAuthenticator(); 19 }); 20 21 function arrivingHereIsGood(aResult) { 22 ok(true, "Good result! Received a: " + aResult); 23 } 24 25 function arrivingHereIsBad(aResult) { 26 ok(false, "Bad result! Received a: " + aResult); 27 } 28 29 function expectNotAllowedError(aResult) { 30 ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult); 31 } 32 33 function expectInvalidStateError(aResult) { 34 ok(aResult.toString().startsWith("InvalidStateError"), "Expecting a InvalidStateError, got " + aResult); 35 } 36 37 // Store the credential and transports of the first successful make credential 38 // operation so we can use them to get assertions later. 39 let gCredential; 40 let gTransports; 41 42 // Start a new MakeCredential() request. 43 function requestMakeCredential(excludeCredentials) { 44 let publicKey = { 45 rp: {id: document.domain, name: "none"}, 46 user: {id: new Uint8Array(), name: "none", displayName: "none"}, 47 challenge: crypto.getRandomValues(new Uint8Array(16)), 48 timeout: 5000, // the minimum timeout is actually 15 seconds 49 pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], 50 excludeCredentials 51 }; 52 53 return navigator.credentials.create({publicKey}); 54 } 55 56 // Start a new GetAssertion() request. 57 function requestGetAssertion(allowCredentials) { 58 let publicKey = { 59 challenge: crypto.getRandomValues(new Uint8Array(16)), 60 timeout: 5000, // the minimum timeout is actually 15 seconds 61 rpId: document.domain, 62 allowCredentials 63 }; 64 65 return navigator.credentials.get({publicKey}); 66 } 67 68 // Test make credential behavior. 69 add_task(async function test_make_credential() { 70 // Make a credential. 71 await requestMakeCredential([]) 72 // Save the credential for later. 73 .then(res => { 74 gCredential = res.rawId; 75 gTransports = res.response.getTransports(); 76 }) 77 .then(arrivingHereIsGood) 78 .catch(arrivingHereIsBad); 79 80 // gTransports should be "a sequence of zero or more unique DOMStrings in lexicographical order." 81 for (let i = 0; i < gTransports.length - 1; i++) { 82 if (gTransports[i] >= gTransports[i+1]) { 83 ok(false, "getTransports() should return a sorted list"); 84 } 85 } 86 87 // Pass a random credential to exclude. 88 await requestMakeCredential([{ 89 type: "public-key", 90 id: crypto.getRandomValues(new Uint8Array(16)), 91 transports: gTransports, 92 }]).then(arrivingHereIsGood) 93 .catch(arrivingHereIsBad); 94 95 // Pass gCredential with transport=usb. 96 // The credential already exists, and the softoken consents to create, 97 // so the error is InvalidState and not NotAllowed. 98 await requestMakeCredential([{ 99 type: "public-key", 100 id: gCredential, 101 transports: ["usb"], 102 }]).then(arrivingHereIsBad) 103 .catch(expectInvalidStateError); 104 105 // Pass gCredential with transport=nfc. 106 // The softoken pretends to support all transports. 107 // Also, as above, the credential exists and the token indicates consent. 108 await requestMakeCredential([{ 109 type: "public-key", 110 id: gCredential, 111 transports: ["nfc"], 112 }]).then(arrivingHereIsBad) 113 .catch(expectInvalidStateError); 114 115 // Pass gCredential with an empty transports list. 116 // As above, the token indicates consent, so expect InvalidStateError. 117 await requestMakeCredential([{ 118 type: "public-key", 119 id: gCredential, 120 transports: [], 121 }]).then(arrivingHereIsBad) 122 .catch(expectInvalidStateError); 123 }); 124 125 // Test get assertion behavior. 126 add_task(async function test_get_assertion() { 127 // Request an assertion for gCredential. 128 await requestGetAssertion([{ 129 type: "public-key", 130 id: gCredential, 131 transports: gTransports, 132 }]).then(arrivingHereIsGood) 133 .catch(arrivingHereIsBad); 134 135 // Request an assertion for a random credential. This should be 136 // indistinguishable from the user denying consent for a known 137 // credential, so expect a NotAllowedError. 138 await requestGetAssertion([{ 139 type: "public-key", 140 id: crypto.getRandomValues(new Uint8Array(16)), 141 transports: ["usb"], 142 }]).then(arrivingHereIsBad) 143 .catch(expectNotAllowedError); 144 145 // Request an assertion for gCredential with transport=nfc. 146 // The softoken pretends to support all transports. 147 await requestGetAssertion([{ 148 type: "public-key", 149 id: gCredential, 150 transports: ["nfc"], 151 }]).then(arrivingHereIsGood) 152 .catch(arrivingHereIsBad); 153 154 // Request an assertion for gCredential with an empty transports list. 155 await requestGetAssertion([{ 156 type: "public-key", 157 id: gCredential, 158 transports: [], 159 }]).then(arrivingHereIsGood) 160 .catch(arrivingHereIsBad); 161 }); 162 </script> 163 164 </body> 165 </html>