public-key-credential-to-json.https.window.js (4451B)
1 // META: script=/resources/testdriver.js 2 // META: script=/resources/testdriver-vendor.js 3 // META: script=/resources/utils.js 4 // META: script=helpers.js 5 6 function assertObjectKeysEq(a, b) { 7 let a_keys = new Set(Object.keys(a)); 8 let b_keys = new Set(Object.keys(b)); 9 assert_true( 10 a_keys.length == b_keys.length && [...a_keys].every(k => b_keys.has(k)), 11 `keys differ: ${a_keys} != ${b_keys}`); 12 } 13 14 // Returns the JSON encoding for `value`. If `value` is a function, `optParent` 15 // is the object to which execution should be bound. 16 function convertValue(value, optParent) { 17 switch (typeof value) { 18 case 'undefined': 19 case 'boolean': 20 case 'number': 21 case 'bigint': 22 case 'string': 23 case 'symbol': 24 return value; 25 case 'function': 26 return value.apply(optParent); 27 case 'object': 28 if (value.__proto__.constructor === Object) { 29 var result = {}; 30 Object.entries(value).map((k, v) => { 31 result[k] = convertValue(k, v); 32 }); 33 return result; 34 } 35 if (value instanceof Array) { 36 return value.map(convertValue); 37 } 38 if (value instanceof ArrayBuffer) { 39 return base64urlEncode(new Uint8Array(value)); 40 } 41 throw `can't convert value ${value} in ${parent}`; 42 default: 43 throw `${value} has unexpected type`; 44 } 45 } 46 47 // Conversion spec for a single attribute. 48 // @typedef {Object} ConvertParam 49 // @property {string} name - The name of the attribute to convert from 50 // @property {string=} target - The name of the attribute to convert to, if 51 // different from `name` 52 // @property {function=} func - Method to convert this property. Defaults to 53 // convertValue(). 54 55 // Returns the JSON object for `obj`. 56 // 57 // @param obj 58 // @param {Array<(string|ConvertParam)>} keys - The names of parameters in 59 // `obj` to convert, or instances of ConvertParam for complex cases. 60 function convertObject(obj, params) { 61 let result = {}; 62 params.forEach((param) => { 63 switch (typeof (param)) { 64 case 'string': 65 assert_true(param in obj, `missing ${param}`); 66 if (obj[param] !== null) { 67 result[param] = convertValue(obj[param], obj); 68 } 69 break; 70 case 'object': 71 assert_true(param.name in obj, `missing ${param.name}`); 72 const val = obj[param.name]; 73 const target_key = param.target || param.name; 74 const convert_func = param.func || convertValue; 75 try { 76 result[target_key] = 77 convert_func(((typeof val) == 'function' ? val.apply(obj) : val)); 78 } catch (e) { 79 throw `failed to convert ${param.name}: ${e}` 80 } 81 break; 82 default: 83 throw `invalid key ${param}`; 84 } 85 }); 86 return result; 87 } 88 89 // Converts an AuthenticatorResponse instance into a JSON object. 90 // @param {!AuthenticatorResponse} 91 function authenticatorResponseToJson(response) { 92 assert_true( 93 (response instanceof AuthenticatorAttestationResponse) || 94 (response instanceof AuthenticatorAssertionResponse)); 95 const isAttestation = (response instanceof AuthenticatorAttestationResponse); 96 const keys = 97 (isAttestation ? 98 [ 99 'clientDataJSON', 'attestationObject', 100 {name: 'getAuthenticatorData', target: 'authenticatorData'}, 101 {name: 'getPublicKey', target: 'publicKey'}, 102 {name: 'getPublicKeyAlgorithm', target: 'publicKeyAlgorithm'}, 103 {name: 'getTransports', target: 'transports'} 104 ] : 105 ['clientDataJSON', 'authenticatorData', 'signature', 'userHandle']); 106 return convertObject(response, keys); 107 } 108 109 // Converts a PublicKeyCredential instance to a JSON object. 110 // @param {!PublicKeyCredential} 111 function publicKeyCredentialToJson(cred) { 112 const keys = [ 113 'id', 'rawId', {name: 'response', func: authenticatorResponseToJson}, 114 'authenticatorAttachment', 115 {name: 'getClientExtensionResults', target: 'clientExtensionResults'}, 116 'type' 117 ]; 118 return convertObject(cred, keys); 119 } 120 121 virtualAuthenticatorPromiseTest( 122 async t => { 123 let credential = await createCredential(); 124 assertJsonEquals( 125 credential.toJSON(), publicKeyCredentialToJson(credential)); 126 127 let assertion = await assertCredential(credential); 128 assertJsonEquals( 129 assertion.toJSON(), publicKeyCredentialToJson(assertion)); 130 }, 131 { 132 protocol: 'ctap2_1', 133 transport: 'usb', 134 }, 135 'toJSON()');