299 lines
10 KiB
HTML
299 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<meta charset=utf-8>
|
|
<head>
|
|
<title>Tests for GetAssertion for W3C Web Authentication</title>
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
<script type="text/javascript" src="u2futil.js"></script>
|
|
<script type="text/javascript" src="pkijs/common.js"></script>
|
|
<script type="text/javascript" src="pkijs/asn1.js"></script>
|
|
<script type="text/javascript" src="pkijs/x509_schema.js"></script>
|
|
<script type="text/javascript" src="pkijs/x509_simpl.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Tests for GetAssertion for W3C Web Authentication</h1>
|
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
|
|
|
|
<script class="testbody" type="text/javascript">
|
|
"use strict";
|
|
|
|
let authenticatorId = null;
|
|
add_task(async () => {
|
|
authenticatorId = await addVirtualAuthenticator();
|
|
});
|
|
|
|
is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
|
|
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
|
|
isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
|
|
isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
|
|
|
|
let gAssertionChallenge = new Uint8Array(16);
|
|
window.crypto.getRandomValues(gAssertionChallenge);
|
|
|
|
let unknownCredType = {type: "Magic", id: base64ToBytes("AAA=")};
|
|
let unknownCred = {type: "public-key", id: base64ToBytes("AAA=")};
|
|
let validCred = null;
|
|
|
|
add_task(test_setup_valid_credential);
|
|
add_task(test_with_credential);
|
|
add_task(test_unexpected_option);
|
|
add_task(test_unexpected_option_with_credential);
|
|
add_task(test_unexpected_transport);
|
|
add_task(test_unknown_credential_type);
|
|
add_task(test_unknown_credential);
|
|
add_task(test_too_many_credentials);
|
|
add_task(test_unexpected_option_unknown_credential_type);
|
|
add_task(test_empty_credential_list);
|
|
add_task(test_credential_protection_policy_uv_optional_with_list);
|
|
add_task(test_credential_protection_policy_uv_required);
|
|
|
|
function requestGetAssertion(params) {
|
|
return navigator.credentials.get(params);
|
|
}
|
|
|
|
function arrivingHereIsGood(aResult) {
|
|
ok(true, "Good result! Received a: " + aResult);
|
|
}
|
|
|
|
function arrivingHereIsBad(aResult) {
|
|
ok(false, "Bad result! Received a: " + aResult);
|
|
}
|
|
|
|
function expectNotAllowedError(aResult) {
|
|
ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult);
|
|
}
|
|
|
|
function expectInvalidStateError(aResult) {
|
|
ok(aResult.toString().startsWith("InvalidStateError"), "Expecting a InvalidStateError, got " + aResult);
|
|
}
|
|
|
|
function expectTypeError(aResult) {
|
|
ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError, got " + aResult);
|
|
}
|
|
|
|
function expectSecurityError(aResult) {
|
|
ok(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError, got " + aResult);
|
|
}
|
|
|
|
function expectAbortError(aResult) {
|
|
is(aResult.code, DOMException.ABORT_ERR, "Expecting an AbortError");
|
|
}
|
|
|
|
// Set up a valid credential
|
|
async function test_setup_valid_credential() {
|
|
let publicKey = {
|
|
rp: {id: document.domain, name: "none"},
|
|
user: {id: new Uint8Array(), name: "none", displayName: "none"},
|
|
challenge: crypto.getRandomValues(new Uint8Array(16)),
|
|
pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
|
|
};
|
|
|
|
return navigator.credentials.create({publicKey})
|
|
.then(res => validCred = {type: "public-key", id: res.rawId} );
|
|
}
|
|
|
|
// Test with a valid credential
|
|
async function test_with_credential() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [validCred]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
}
|
|
|
|
// Test with an unexpected option. That won't stop anything, and we'll
|
|
// fail with NotAllowed just as if we had no valid credentials -- which
|
|
// we don't.
|
|
async function test_unexpected_option() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
unknownValue: "hi"
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectNotAllowedError);
|
|
}
|
|
|
|
// Test with an unexpected option but a valid credential
|
|
async function test_unexpected_option_with_credential() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
unknownValue: "hi",
|
|
allowCredentials: [validCred]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
}
|
|
|
|
// Test with an unexpected transport on a valid credential
|
|
async function test_unexpected_transport() {
|
|
let cred = validCred;
|
|
cred.transports = ["unknown", "usb"];
|
|
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
unknownValue: "hi",
|
|
allowCredentials: [cred]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
}
|
|
|
|
// Test with an unknown credential type
|
|
async function test_unknown_credential_type() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [unknownCredType]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectNotAllowedError);
|
|
}
|
|
|
|
// Test with an unknown credential
|
|
async function test_unknown_credential() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [unknownCred]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectNotAllowedError);
|
|
}
|
|
|
|
// Test with too many credentials
|
|
async function test_too_many_credentials() {
|
|
let tooManyCredentials = Array(21).fill(validCred);
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: tooManyCredentials,
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectSecurityError);
|
|
}
|
|
|
|
// Test with an unexpected option and an unknown credential type
|
|
async function test_unexpected_option_unknown_credential_type() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
unknownValue: "hi",
|
|
allowCredentials: [unknownCredType]
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectNotAllowedError);
|
|
}
|
|
|
|
// Test with an empty credential list
|
|
async function test_empty_credential_list() {
|
|
let publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: []
|
|
};
|
|
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(expectNotAllowedError);
|
|
}
|
|
|
|
async function test_credential_protection_policy_uv_optional_with_list() {
|
|
let publicKey = {
|
|
rp: {id: document.domain, name: "none"},
|
|
user: {id: new Uint8Array(), name: "none", displayName: "none"},
|
|
challenge: crypto.getRandomValues(new Uint8Array(16)),
|
|
authenticatorSelection: { residentKey: "required"},
|
|
pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
|
|
extensions: { credentialProtectionPolicy: "userVerificationOptionalWithCredentialIDList" },
|
|
};
|
|
|
|
let protectedCred = null;
|
|
await navigator.credentials.create({publicKey})
|
|
.then(res => protectedCred = {type: "public-key", id: res.rawId} );
|
|
|
|
publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [protectedCred],
|
|
userVerification: "discouraged"
|
|
};
|
|
|
|
// User verification is optional for this request. So it should succeed
|
|
// both with and without user verification as long as the credential ID
|
|
// is provided in allowCredentials.
|
|
setUserVerified(authenticatorId, true)
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
|
|
setUserVerified(authenticatorId, false)
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
|
|
// User verification is required if the credential ID is not provided in
|
|
// allowCredentials.
|
|
publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [],
|
|
userVerification: "discouraged"
|
|
};
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(arrivingHereIsGood);
|
|
|
|
setUserVerified(authenticatorId, true)
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
}
|
|
|
|
async function test_credential_protection_policy_uv_required() {
|
|
let publicKey = {
|
|
rp: {id: document.domain, name: "none"},
|
|
user: {id: new Uint8Array(), name: "none", displayName: "none"},
|
|
challenge: crypto.getRandomValues(new Uint8Array(16)),
|
|
pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
|
|
extensions: { credentialProtectionPolicy: "userVerificationRequired" },
|
|
};
|
|
|
|
let protectedCred = null;
|
|
await navigator.credentials.create({publicKey})
|
|
.then(res => protectedCred = {type: "public-key", id: res.rawId} );
|
|
|
|
publicKey = {
|
|
challenge: gAssertionChallenge,
|
|
allowCredentials: [protectedCred],
|
|
userVerification: "discouraged"
|
|
};
|
|
|
|
// User verification is required; this should succeed.
|
|
setUserVerified(authenticatorId, true)
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsGood)
|
|
.catch(arrivingHereIsBad);
|
|
|
|
// The same request should fail without user verification.
|
|
setUserVerified(authenticatorId, false)
|
|
await requestGetAssertion({publicKey})
|
|
.then(arrivingHereIsBad)
|
|
.catch(arrivingHereIsGood);
|
|
|
|
setUserVerified(authenticatorId, true)
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|