<html>
<script>
function parseAuthenticatorFlags(flags) {
return {
up: !!(flags & 1 << 0),
uv: !!(flags & 1 << 2),
be: !!(flags & 1 << 3),
bs: !!(flags & 1 << 4),
at: !!(flags & 1 << 6),
ed: !!(flags & 1 << 7),
};
}
async function registerCredential(options = {}) {
options = Object.assign({
authenticatorSelection: {
requireResidentKey: false,
},
rp: {
id: "chromedriver.test",
name: "ChromeDriver Test",
},
challenge: Uint8Array.from("challenge"),
pubKeyCredParams: [
{type: "public-key", alg: -7},
],
user: {
name: "name",
displayName: "displayName",
id: Uint8Array.from([1]),
},
}, options);
try {
const credential = await navigator.credentials.create({publicKey: options});
return {
status: "OK",
credential: {
id: credential.id,
rawId: Array.from(new Uint8Array(credential.rawId)),
transports: credential.response.getTransports(),
authenticatorData: btoa(String.fromCharCode.apply(
null, new Uint8Array(credential.response.getAuthenticatorData()))),
flags: parseAuthenticatorFlags(
new Uint8Array(credential.response.getAuthenticatorData())[32]),
},
extensions: credential.getClientExtensionResults(),
};
} catch (error) {
return {status: error.toString()};
}
}
async function getCredential(credential, options = {}) {
options = Object.assign({
challenge: Uint8Array.from("Winter is Coming"),
rpId: "chromedriver.test",
allowCredentials: [credential],
userVerification: "preferred",
}, options);
try {
const attestation = await navigator.credentials.get({publicKey: options});
let result = {
status: "OK",
attestation,
extensions: attestation.getClientExtensionResults(),
};
if (attestation.getClientExtensionResults()?.largeBlob?.blob) {
result.blob = new TextDecoder().decode(
attestation.getClientExtensionResults().largeBlob.blob);
}
if (attestation.response?.authenticatorData) {
result.flags = parseAuthenticatorFlags(
new Uint8Array(attestation.response.authenticatorData)[32]);
}
return result;
} catch (error) {
return {status: error.toString()};
}
}
</script>
</html>