| 'use strict'; |
| |
| // A minimal HTML document that loads this very file. This can be |
| // document.write()'en to nested documents to include test input/outputs. |
| const HTML_WITH_TEST_INPUTS = "<script src='/credentialmanager/resources/test-inputs.js'></script>"; |
| |
| // Constructs a script that loads this very script file, and runs |code| once |
| // loaded. This can be window.eval()'ed in nested documents to include test |
| // input/outputs (and then run the |code| under test). |
| function getScriptThatLoadsTestInputsAndRuns(code) { |
| return "var script = document.createElement('script');" |
| + "script.src = '/credentialmanager/resources/test-inputs.js';" |
| + "script.onload = _ => {" + code + "};" |
| + "document.head.appendChild(script);" |
| } |
| |
| // Common mock values for the mockAuthenticator. |
| var CHALLENGE = new TextEncoder().encode("climb a mountain"); |
| |
| var PUBLIC_KEY_RP = { |
| id: "subdomain.example.test", |
| name: "Acme" |
| }; |
| |
| var PUBLIC_KEY_USER = { |
| id: new TextEncoder().encode("1098237235409872"), |
| name: "avery.a.jones@example.com", |
| displayName: "Avery A. Jones", |
| icon: "https://pics.acme.com/00/p/aBjjjpqPb.png" |
| }; |
| |
| var PUBLIC_KEY_PARAMETERS = [{ |
| type: "public-key", |
| alg: -7, |
| },]; |
| |
| var AUTHENTICATOR_SELECTION_CRITERIA = { |
| requireResidentKey: false, |
| userVerification: "preferred", |
| }; |
| |
| var MAKE_CREDENTIAL_OPTIONS = { |
| challenge: CHALLENGE, |
| rp: PUBLIC_KEY_RP, |
| user: PUBLIC_KEY_USER, |
| pubKeyCredParams: PUBLIC_KEY_PARAMETERS, |
| authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, |
| excludeCredentials: [], |
| }; |
| |
| var ACCEPTABLE_CREDENTIAL_ID = new TextEncoder().encode("acceptableCredential"); |
| |
| var ACCEPTABLE_CREDENTIAL = { |
| type: "public-key", |
| id: ACCEPTABLE_CREDENTIAL_ID, |
| transports: ["usb", "nfc", "ble"] |
| }; |
| |
| var GET_CREDENTIAL_OPTIONS = { |
| challenge: CHALLENGE, |
| rpId: "subdomain.example.test", |
| allowCredentials: [ACCEPTABLE_CREDENTIAL], |
| userVerification: "preferred", |
| }; |
| |
| var RAW_ID = new TextEncoder("utf-8").encode("rawId"); |
| var ID = btoa("rawId"); |
| var CLIENT_DATA_JSON = new TextEncoder("utf-8").encode("clientDataJSON"); |
| var ATTESTATION_OBJECT = new TextEncoder("utf-8").encode("attestationObject"); |
| var AUTHENTICATOR_DATA = new TextEncoder("utf-8").encode("authenticatorData"); |
| var SIGNATURE = new TextEncoder("utf-8").encode("signature"); |
| var CABLE_REGISTRATION = { |
| versions: [1], |
| rpPublicKey: new TextEncoder("utf-8").encode("SixteenByteRpKey"), |
| }; |
| |
| var CABLE_AUTHENTICATION = { |
| version: 1, |
| clientEid: new TextEncoder("utf-8").encode("SixteenByteClEid"), |
| authenticatorEid: new TextEncoder("utf-8").encode("SixteenByteAuEid"), |
| sessionPreKey: new TextEncoder("utf-8").encode('x'.repeat(32)), |
| }; |
| |
| var CREATE_CREDENTIALS = |
| "navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS})" |
| + ".then(c => window.parent.postMessage(String(c), '*'))"; |
| + ".catch(e => window.parent.postMessage(String(e), '*'));"; |
| |
| var GET_CREDENTIAL = "navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS})" |
| + ".then(c => window.parent.postMessage(String(c), '*'))"; |
| + ".catch(e => window.parent.postMessage(String(e), '*'));"; |
| |
| function encloseInScriptTag(code) { |
| return "<script>" + code + "</scr" + "ipt>"; |
| } |
| |
| function deepCopy(value) { |
| if ([Number, String, Boolean, Uint8Array].includes(value.constructor)) |
| return value; |
| |
| let copy = (value.constructor == Array) ? [] : {}; |
| for (let key of Object.keys(value)) |
| copy[key] = deepCopy(value[key]); |
| return copy; |
| } |
| |
| // Verifies if |r| is the valid response to credentials.create(publicKey). |
| function assertValidMakeCredentialResponse(r) { |
| assert_equals(r.id, ID, 'id'); |
| assert_true(r.rawId instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.rawId), |
| RAW_ID, "rawId returned is the same"); |
| assert_true(r.response instanceof AuthenticatorAttestationResponse); |
| assert_true(r.response.clientDataJSON instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.response.clientDataJSON), |
| CLIENT_DATA_JSON, "clientDataJSON returned is the same"); |
| assert_true(r.response.attestationObject instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.response.attestationObject), |
| ATTESTATION_OBJECT, "attestationObject returned is the same"); |
| assert_false('authenticatorData' in r.response); |
| assert_false('signature' in r.response); |
| } |
| |
| // Verifies if |r| is the valid response to credentials.get(publicKey). |
| function assertValidGetCredentialResponse(r) { |
| assert_equals(r.id, ID, 'id'); |
| assert_true(r.rawId instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.rawId), |
| RAW_ID, "rawId returned is the same"); |
| |
| // The call returned an AssertionResponse, meaning it has |
| // authenticatorData and signature and does not have an attestationObject. |
| assert_true(r.response instanceof AuthenticatorAssertionResponse); |
| assert_true(r.response.clientDataJSON instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.response.clientDataJSON), |
| CLIENT_DATA_JSON, "clientDataJSON returned is the same"); |
| assert_true(r.response.authenticatorData instanceof ArrayBuffer); |
| assert_true(r.response.signature instanceof ArrayBuffer); |
| assert_array_equals(new Uint8Array(r.response.authenticatorData), |
| AUTHENTICATOR_DATA, "authenticator_data returned is the same"); |
| assert_array_equals(new Uint8Array(r.response.signature), |
| SIGNATURE, "signature returned is the same"); |
| assert_false('attestationObject' in r.response); |
| } |