chromium/third_party/blink/web_tests/external/wpt/webauthn/createcredential-resident-key.https.html

<!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>