test_webauthn_get_assertion.html (10309B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <head> 4 <title>Tests for GetAssertion for W3C Web Authentication</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script type="text/javascript" src="u2futil.js"></script> 7 <script type="text/javascript" src="pkijs/common.js"></script> 8 <script type="text/javascript" src="pkijs/asn1.js"></script> 9 <script type="text/javascript" src="pkijs/x509_schema.js"></script> 10 <script type="text/javascript" src="pkijs/x509_simpl.js"></script> 11 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 12 </head> 13 <body> 14 15 <h1>Tests for GetAssertion for W3C Web Authentication</h1> 16 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a> 17 18 <script class="testbody" type="text/javascript"> 19 "use strict"; 20 21 let authenticatorId = null; 22 add_task(async () => { 23 authenticatorId = await addVirtualAuthenticator(); 24 }); 25 26 is(navigator.authentication, undefined, "navigator.authentication does not exist any longer"); 27 isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist"); 28 isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist"); 29 isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist"); 30 31 let gAssertionChallenge = new Uint8Array(16); 32 window.crypto.getRandomValues(gAssertionChallenge); 33 34 let unknownCredType = {type: "Magic", id: base64ToBytes("AAA=")}; 35 let unknownCred = {type: "public-key", id: base64ToBytes("AAA=")}; 36 let validCred = null; 37 38 add_task(test_setup_valid_credential); 39 add_task(test_with_credential); 40 add_task(test_unexpected_option); 41 add_task(test_unexpected_option_with_credential); 42 add_task(test_unexpected_transport); 43 add_task(test_unknown_credential_type); 44 add_task(test_unknown_credential); 45 add_task(test_too_many_credentials); 46 add_task(test_unexpected_option_unknown_credential_type); 47 add_task(test_empty_credential_list); 48 add_task(test_credential_protection_policy_uv_optional_with_list); 49 add_task(test_credential_protection_policy_uv_required); 50 51 function requestGetAssertion(params) { 52 return navigator.credentials.get(params); 53 } 54 55 function arrivingHereIsGood(aResult) { 56 ok(true, "Good result! Received a: " + aResult); 57 } 58 59 function arrivingHereIsBad(aResult) { 60 ok(false, "Bad result! Received a: " + aResult); 61 } 62 63 function expectNotAllowedError(aResult) { 64 ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult); 65 } 66 67 function expectInvalidStateError(aResult) { 68 ok(aResult.toString().startsWith("InvalidStateError"), "Expecting a InvalidStateError, got " + aResult); 69 } 70 71 function expectTypeError(aResult) { 72 ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError, got " + aResult); 73 } 74 75 function expectSecurityError(aResult) { 76 ok(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError, got " + aResult); 77 } 78 79 function expectAbortError(aResult) { 80 is(aResult.code, DOMException.ABORT_ERR, "Expecting an AbortError"); 81 } 82 83 // Set up a valid credential 84 async function test_setup_valid_credential() { 85 let publicKey = { 86 rp: {id: document.domain, name: "none"}, 87 user: {id: new Uint8Array(), name: "none", displayName: "none"}, 88 challenge: crypto.getRandomValues(new Uint8Array(16)), 89 pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], 90 }; 91 92 return navigator.credentials.create({publicKey}) 93 .then(res => validCred = {type: "public-key", id: res.rawId} ); 94 } 95 96 // Test with a valid credential 97 async function test_with_credential() { 98 let publicKey = { 99 challenge: gAssertionChallenge, 100 allowCredentials: [validCred] 101 }; 102 103 await requestGetAssertion({publicKey}) 104 .then(arrivingHereIsGood) 105 .catch(arrivingHereIsBad); 106 } 107 108 // Test with an unexpected option. That won't stop anything, and we'll 109 // fail with NotAllowed just as if we had no valid credentials -- which 110 // we don't. 111 async function test_unexpected_option() { 112 let publicKey = { 113 challenge: gAssertionChallenge, 114 unknownValue: "hi" 115 }; 116 117 await requestGetAssertion({publicKey}) 118 .then(arrivingHereIsBad) 119 .catch(expectNotAllowedError); 120 } 121 122 // Test with an unexpected option but a valid credential 123 async function test_unexpected_option_with_credential() { 124 let publicKey = { 125 challenge: gAssertionChallenge, 126 unknownValue: "hi", 127 allowCredentials: [validCred] 128 }; 129 130 await requestGetAssertion({publicKey}) 131 .then(arrivingHereIsGood) 132 .catch(arrivingHereIsBad); 133 } 134 135 // Test with an unexpected transport on a valid credential 136 async function test_unexpected_transport() { 137 let cred = validCred; 138 cred.transports = ["unknown", "usb"]; 139 140 let publicKey = { 141 challenge: gAssertionChallenge, 142 unknownValue: "hi", 143 allowCredentials: [cred] 144 }; 145 146 await requestGetAssertion({publicKey}) 147 .then(arrivingHereIsGood) 148 .catch(arrivingHereIsBad); 149 } 150 151 // Test with an unknown credential type 152 async function test_unknown_credential_type() { 153 let publicKey = { 154 challenge: gAssertionChallenge, 155 allowCredentials: [unknownCredType] 156 }; 157 158 await requestGetAssertion({publicKey}) 159 .then(arrivingHereIsBad) 160 .catch(expectNotAllowedError); 161 } 162 163 // Test with an unknown credential 164 async function test_unknown_credential() { 165 let publicKey = { 166 challenge: gAssertionChallenge, 167 allowCredentials: [unknownCred] 168 }; 169 170 await requestGetAssertion({publicKey}) 171 .then(arrivingHereIsBad) 172 .catch(expectNotAllowedError); 173 } 174 175 // Test with too many credentials 176 async function test_too_many_credentials() { 177 let tooManyCredentials = Array(21).fill(validCred); 178 let publicKey = { 179 challenge: gAssertionChallenge, 180 allowCredentials: tooManyCredentials, 181 }; 182 183 await requestGetAssertion({publicKey}) 184 .then(arrivingHereIsBad) 185 .catch(expectSecurityError); 186 } 187 188 // Test with an unexpected option and an unknown credential type 189 async function test_unexpected_option_unknown_credential_type() { 190 let publicKey = { 191 challenge: gAssertionChallenge, 192 unknownValue: "hi", 193 allowCredentials: [unknownCredType] 194 }; 195 196 await requestGetAssertion({publicKey}) 197 .then(arrivingHereIsBad) 198 .catch(expectNotAllowedError); 199 } 200 201 // Test with an empty credential list 202 async function test_empty_credential_list() { 203 let publicKey = { 204 challenge: gAssertionChallenge, 205 allowCredentials: [] 206 }; 207 208 await requestGetAssertion({publicKey}) 209 .then(arrivingHereIsBad) 210 .catch(expectNotAllowedError); 211 } 212 213 async function test_credential_protection_policy_uv_optional_with_list() { 214 let publicKey = { 215 rp: {id: document.domain, name: "none"}, 216 user: {id: new Uint8Array(), name: "none", displayName: "none"}, 217 challenge: crypto.getRandomValues(new Uint8Array(16)), 218 authenticatorSelection: { residentKey: "required"}, 219 pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], 220 extensions: { credentialProtectionPolicy: "userVerificationOptionalWithCredentialIDList" }, 221 }; 222 223 let protectedCred = null; 224 await navigator.credentials.create({publicKey}) 225 .then(res => protectedCred = {type: "public-key", id: res.rawId} ); 226 227 publicKey = { 228 challenge: gAssertionChallenge, 229 allowCredentials: [protectedCred], 230 userVerification: "discouraged" 231 }; 232 233 // User verification is optional for this request. So it should succeed 234 // both with and without user verification as long as the credential ID 235 // is provided in allowCredentials. 236 setUserVerified(authenticatorId, true) 237 await requestGetAssertion({publicKey}) 238 .then(arrivingHereIsGood) 239 .catch(arrivingHereIsBad); 240 241 setUserVerified(authenticatorId, false) 242 await requestGetAssertion({publicKey}) 243 .then(arrivingHereIsGood) 244 .catch(arrivingHereIsBad); 245 246 // User verification is required if the credential ID is not provided in 247 // allowCredentials. 248 publicKey = { 249 challenge: gAssertionChallenge, 250 allowCredentials: [], 251 userVerification: "discouraged" 252 }; 253 await requestGetAssertion({publicKey}) 254 .then(arrivingHereIsBad) 255 .catch(arrivingHereIsGood); 256 257 setUserVerified(authenticatorId, true) 258 await requestGetAssertion({publicKey}) 259 .then(arrivingHereIsGood) 260 .catch(arrivingHereIsBad); 261 } 262 263 async function test_credential_protection_policy_uv_required() { 264 let publicKey = { 265 rp: {id: document.domain, name: "none"}, 266 user: {id: new Uint8Array(), name: "none", displayName: "none"}, 267 challenge: crypto.getRandomValues(new Uint8Array(16)), 268 pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}], 269 extensions: { credentialProtectionPolicy: "userVerificationRequired" }, 270 }; 271 272 let protectedCred = null; 273 await navigator.credentials.create({publicKey}) 274 .then(res => protectedCred = {type: "public-key", id: res.rawId} ); 275 276 publicKey = { 277 challenge: gAssertionChallenge, 278 allowCredentials: [protectedCred], 279 userVerification: "discouraged" 280 }; 281 282 // User verification is required; this should succeed. 283 setUserVerified(authenticatorId, true) 284 await requestGetAssertion({publicKey}) 285 .then(arrivingHereIsGood) 286 .catch(arrivingHereIsBad); 287 288 // The same request should fail without user verification. 289 setUserVerified(authenticatorId, false) 290 await requestGetAssertion({publicKey}) 291 .then(arrivingHereIsBad) 292 .catch(arrivingHereIsGood); 293 294 setUserVerified(authenticatorId, true) 295 } 296 </script> 297 298 </body> 299 </html>