Skip to content

Commit

Permalink
webauthn: move create credential tests for residentKey/credProps to WPT
Browse files Browse the repository at this point in the history
Bug: 1117630
Change-Id: I2fa4d73b7a4cfe5e7f19fd835cb32e1bb4926d2f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2508878
Reviewed-by: Nina Satragno <nsatragno@chromium.org>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#825930}
  • Loading branch information
kreichgauer authored and Hexcles committed Nov 11, 2020
1 parent c18d662 commit 745dadd
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 19 deletions.
178 changes: 178 additions & 0 deletions webauthn/createcredential-resident-key.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<!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"]) {
virtualAuthenticatorTest(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>
63 changes: 44 additions & 19 deletions webauthn/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,31 +550,56 @@ function validateAuthenticatorAssertionResponse(assert) {
// TODO: parseAuthenticatorData() and make sure flags are correct
}

function defaultAuthenticatorArgs() {
return {
protocol: 'ctap1/u2f',
transport: 'usb',
hasResidentKey: false,
hasUserVerification: false,
isUserVerified: false,
};
}

function standardSetup(cb, options = {}) {
// Setup an automated testing environment if available.
let authenticatorArgs = {
protocol: "ctap1/u2f",
transport: "usb",
hasResidentKey: false,
hasUserVerification: false,
isUserVerified: false,
};
extendObject(authenticatorArgs, options);
window.test_driver.add_virtual_authenticator(authenticatorArgs).then(authenticator => {
// Setup an automated testing environment if available.
let authenticatorArgs = Object.assign(defaultAuthenticatorArgs(), options);
window.test_driver.add_virtual_authenticator(authenticatorArgs)
.then(authenticator => {
cb();
// XXX add a subtest to clean up the virtual authenticator since
// testharness does not support waiting for promises on cleanup.
promise_test(() => window.test_driver.remove_virtual_authenticator(authenticator),
"Clean up the test environment");
}).catch(error => {
if (error !== "error: Action add_virtual_authenticator not implemented") {
throw error;
promise_test(
() =>
window.test_driver.remove_virtual_authenticator(authenticator),
'Clean up the test environment');
})
.catch(error => {
if (error !==
'error: Action add_virtual_authenticator not implemented') {
throw error;
}
// The protocol is not available. Continue manually.
cb();
});
});
}

/* JSHINT */
/* globals promise_rejects_dom, promise_rejects_js, assert_class_string, assert_equals, assert_idl_attribute, assert_readonly, promise_test */
/* exported standardSetup, CreateCredentialsTest, GetCredentialsTest */
// virtualAuthenticatorTest runs |testCb| in a promise_test with a virtual
// authenticator set up before and destroyed after the test, if the virtual
// testing API is available. In manual tests, setup and teardown is skipped.
function virtualAuthenticatorTest(
testCb, options = {}, name = 'Virtual Authenticator Test') {
let authenticatorArgs = Object.assign(defaultAuthenticatorArgs(), options);
promise_test(async t => {
try {
let authenticator =
await window.test_driver.add_virtual_authenticator(authenticatorArgs);
t.add_cleanup(
() => window.test_driver.remove_virtual_authenticator(authenticator));
} catch (error) {
if (error !== 'error: Action add_virtual_authenticator not implemented') {
throw error;
}
}
testCb(t);
}, name);
}

0 comments on commit 745dadd

Please sign in to comment.