<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>navigator.credentials.create() test with residentKey and credProps</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src=helpers.js></script>
<script>
"use strict";
const credPropsTests = [
{
name: "U2F",
authenticatorArgs: {
protocol: "ctap1/u2f",
},
expected: {
discouraged: {
success: true,
hasRk: true,
rk: false,
},
preferred: {
success: true,
hasRk: true,
rk: false,
},
required: {
success: false,
},
},
},
{
name: "CTAP 2.0 without resident key support",
authenticatorArgs: {
protocol: "ctap2",
hasResidentKey: false,
hasUserVerification: true,
isUserVerified: true,
},
expected: {
discouraged: {
success: true,
hasRk: true,
rk: false,
},
preferred: {
success: true,
hasRk: true,
rk: false,
},
required: {
success: false,
},
},
},
{
name: "CTAP 2.0 with resident key support",
authenticatorArgs: {
protocol: "ctap2",
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
expected: {
discouraged: {
success: true,
// CTAP2.0 authenticators may treat all credentials as discoverable,
// thus Chrome omits 'rk' in this case.
hasRk: false,
},
preferred: {
success: true,
hasRk: true,
rk: true,
},
required: {
success: true,
hasRk: true,
rk: true,
},
},
},
{
name: "CTAP 2.1 without resident key support",
authenticatorArgs: {
protocol: "ctap2_1",
hasResidentKey: false,
hasUserVerification: true,
isUserVerified: true,
},
expected: {
discouraged: {
success: true,
hasRk: true,
rk: false,
},
preferred: {
success: true,
hasRk: true,
rk: false,
},
required: {
success: false,
},
},
},
{
name: "CTAP 2.1 with resident key support",
authenticatorArgs: {
protocol: "ctap2_1",
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
expected: {
discouraged: {
success: true,
hasRk: true,
rk: false,
},
preferred: {
success: true,
hasRk: true,
rk: true,
},
required: {
success: true,
hasRk: true,
rk: true,
},
},
},
];
for (const fixture of credPropsTests) {
for (const rkRequirement of ["discouraged", "preferred", "required"]) {
virtualAuthenticatorPromiseTest(async t => {
const promise = createCredential({
options: {
publicKey: {
authenticatorSelection: {
residentKey: rkRequirement,
},
extensions: {
credProps: true,
},
},
},
});
assert_true(rkRequirement in fixture.expected);
const expected = fixture.expected[rkRequirement];
assert_true('success' in expected);
if (!expected.success) {
return promise_rejects_dom(t, "NotAllowedError", promise);
}
const cred = await promise;
assert_true('credProps' in cred.getClientExtensionResults());
const credProps = cred.getClientExtensionResults().credProps;
assert_equals('rk' in credProps, expected.hasRk, "hasRk");
if (expected.hasRk) {
assert_equals(credProps.rk, expected.rk, "rk");
}
}, fixture.authenticatorArgs, fixture.name
+ ": navigator.credentials.create() with credProps extension, rk="
+ rkRequirement);
}
}
</script>
</head>
<body></body>
</html>