зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1810851 - add the authenticator attachment field to PublicKeyCredential. r=keeler,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D189397
This commit is contained in:
Родитель
931903c87a
Коммит
5553a8b85d
|
@ -109,6 +109,7 @@ struct WebAuthnMakeCredentialResult {
|
|||
uint8_t[] KeyHandle;
|
||||
nsString[] Transports;
|
||||
WebAuthnExtensionResult[] Extensions;
|
||||
nsString? AuthenticatorAttachment;
|
||||
};
|
||||
|
||||
struct WebAuthnGetAssertionInfo {
|
||||
|
@ -130,6 +131,7 @@ struct WebAuthnGetAssertionResult {
|
|||
uint8_t[] AuthenticatorData;
|
||||
WebAuthnExtensionResult[] Extensions;
|
||||
uint8_t[] UserHandle;
|
||||
nsString? AuthenticatorAttachment;
|
||||
};
|
||||
|
||||
[ManualDealloc]
|
||||
|
|
|
@ -75,6 +75,15 @@ void PublicKeyCredential::GetRawId(JSContext* aCx,
|
|||
aValue.set(mRawIdCachedObj);
|
||||
}
|
||||
|
||||
void PublicKeyCredential::GetAuthenticatorAttachment(
|
||||
DOMString& aAuthenticatorAttachment) {
|
||||
if (mAuthenticatorAttachment.isSome()) {
|
||||
aAuthenticatorAttachment.SetKnownLiveString(mAuthenticatorAttachment.ref());
|
||||
} else {
|
||||
aAuthenticatorAttachment.SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<AuthenticatorResponse> PublicKeyCredential::Response() const {
|
||||
if (mAttestationResponse) {
|
||||
return do_AddRef(mAttestationResponse);
|
||||
|
@ -89,6 +98,11 @@ void PublicKeyCredential::SetRawId(const nsTArray<uint8_t>& aBuffer) {
|
|||
mRawId.Assign(aBuffer);
|
||||
}
|
||||
|
||||
void PublicKeyCredential::SetAuthenticatorAttachment(
|
||||
const Maybe<nsString>& aAuthenticatorAttachment) {
|
||||
mAuthenticatorAttachment = aAuthenticatorAttachment;
|
||||
}
|
||||
|
||||
void PublicKeyCredential::SetAttestationResponse(
|
||||
const RefPtr<AuthenticatorAttestationResponse>& aAttestationResponse) {
|
||||
mAttestationResponse = aAttestationResponse;
|
||||
|
@ -200,7 +214,10 @@ void PublicKeyCredential::ToJSON(JSContext* aCx,
|
|||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
// TODO(bug 1810851): authenticatorAttachment
|
||||
if (mAuthenticatorAttachment.isSome()) {
|
||||
json.mAuthenticatorAttachment.Construct();
|
||||
json.mAuthenticatorAttachment.Value() = mAuthenticatorAttachment.ref();
|
||||
}
|
||||
if (mClientExtensionOutputs.mCredProps.WasPassed()) {
|
||||
json.mClientExtensionResults.mCredProps.Construct(
|
||||
mClientExtensionOutputs.mCredProps.Value());
|
||||
|
@ -222,7 +239,10 @@ void PublicKeyCredential::ToJSON(JSContext* aCx,
|
|||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
// TODO(bug 1810851): authenticatorAttachment
|
||||
if (mAuthenticatorAttachment.isSome()) {
|
||||
json.mAuthenticatorAttachment.Construct();
|
||||
json.mAuthenticatorAttachment.Value() = mAuthenticatorAttachment.ref();
|
||||
}
|
||||
if (mClientExtensionOutputs.mAppid.WasPassed()) {
|
||||
json.mClientExtensionResults.mAppid.Construct(
|
||||
mClientExtensionOutputs.mAppid.Value());
|
||||
|
|
|
@ -36,10 +36,15 @@ class PublicKeyCredential final : public Credential {
|
|||
void GetRawId(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetAuthenticatorAttachment(DOMString& aAuthenticatorAttachment);
|
||||
|
||||
already_AddRefed<AuthenticatorResponse> Response() const;
|
||||
|
||||
void SetRawId(const nsTArray<uint8_t>& aBuffer);
|
||||
|
||||
void SetAuthenticatorAttachment(
|
||||
const Maybe<nsString>& aAuthenticatorAttachment);
|
||||
|
||||
void SetAttestationResponse(
|
||||
const RefPtr<AuthenticatorAttestationResponse>& aAttestationResponse);
|
||||
void SetAssertionResponse(
|
||||
|
@ -80,6 +85,7 @@ class PublicKeyCredential final : public Credential {
|
|||
private:
|
||||
nsTArray<uint8_t> mRawId;
|
||||
JS::Heap<JSObject*> mRawIdCachedObj;
|
||||
Maybe<nsString> mAuthenticatorAttachment;
|
||||
RefPtr<AuthenticatorAttestationResponse> mAttestationResponse;
|
||||
RefPtr<AuthenticatorAssertionResponse> mAssertionResponse;
|
||||
AuthenticationExtensionsClientOutputs mClientExtensionOutputs;
|
||||
|
|
|
@ -744,6 +744,7 @@ void WebAuthnManager::FinishMakeCredential(
|
|||
credential->SetType(u"public-key"_ns);
|
||||
credential->SetRawId(aResult.KeyHandle());
|
||||
credential->SetAttestationResponse(attestation);
|
||||
credential->SetAuthenticatorAttachment(aResult.AuthenticatorAttachment());
|
||||
|
||||
// Forward client extension results.
|
||||
for (const auto& ext : aResult.Extensions()) {
|
||||
|
@ -797,6 +798,7 @@ void WebAuthnManager::FinishGetAssertion(
|
|||
credential->SetType(u"public-key"_ns);
|
||||
credential->SetRawId(aResult.KeyHandle());
|
||||
credential->SetAssertionResponse(assertion);
|
||||
credential->SetAuthenticatorAttachment(aResult.AuthenticatorAttachment());
|
||||
|
||||
// Forward client extension results.
|
||||
for (const auto& ext : aResult.Extensions()) {
|
||||
|
|
|
@ -71,6 +71,16 @@ WebAuthnRegisterResult::SetCredPropsRk(bool aCredPropsRk) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnRegisterResult::GetAuthenticatorAttachment(
|
||||
nsAString& aAuthenticatorAttachment) {
|
||||
if (mAuthenticatorAttachment.isSome()) {
|
||||
aAuthenticatorAttachment = mAuthenticatorAttachment.ref();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WebAuthnSignResult, nsIWebAuthnSignResult)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -108,4 +118,14 @@ WebAuthnSignResult::GetUsedAppId(bool* aUsedAppId) {
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebAuthnSignResult::GetAuthenticatorAttachment(
|
||||
nsAString& aAuthenticatorAttachment) {
|
||||
if (mAuthenticatorAttachment.isSome()) {
|
||||
aAuthenticatorAttachment = mAuthenticatorAttachment.ref();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -21,8 +21,11 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
|||
WebAuthnRegisterResult(const nsTArray<uint8_t>& aAttestationObject,
|
||||
const nsCString& aClientDataJSON,
|
||||
const nsTArray<uint8_t>& aCredentialId,
|
||||
const nsTArray<nsString>& aTransports)
|
||||
: mClientDataJSON(aClientDataJSON), mCredPropsRk(Nothing()) {
|
||||
const nsTArray<nsString>& aTransports,
|
||||
const Maybe<nsString>& aAuthenticatorAttachment)
|
||||
: mClientDataJSON(aClientDataJSON),
|
||||
mCredPropsRk(Nothing()),
|
||||
mAuthenticatorAttachment(aAuthenticatorAttachment) {
|
||||
mAttestationObject.AppendElements(aAttestationObject);
|
||||
mCredentialId.AppendElements(aCredentialId);
|
||||
mTransports.AppendElements(aTransports);
|
||||
|
@ -49,6 +52,8 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
|||
mTransports.AppendElement(
|
||||
jni::String::LocalRef(transports->GetElement(i))->ToString());
|
||||
}
|
||||
// authenticator attachment is not available on Android
|
||||
mAuthenticatorAttachment = Nothing();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -60,6 +65,7 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
|||
nsTArray<nsString> mTransports;
|
||||
nsCString mClientDataJSON;
|
||||
Maybe<bool> mCredPropsRk;
|
||||
Maybe<nsString> mAuthenticatorAttachment;
|
||||
};
|
||||
|
||||
class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
||||
|
@ -71,8 +77,10 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
|||
const nsCString& aClientDataJSON,
|
||||
const nsTArray<uint8_t>& aCredentialId,
|
||||
const nsTArray<uint8_t>& aSignature,
|
||||
const nsTArray<uint8_t>& aUserHandle)
|
||||
: mClientDataJSON(aClientDataJSON) {
|
||||
const nsTArray<uint8_t>& aUserHandle,
|
||||
const Maybe<nsString>& aAuthenticatorAttachment)
|
||||
: mClientDataJSON(aClientDataJSON),
|
||||
mAuthenticatorAttachment(aAuthenticatorAttachment) {
|
||||
mAuthenticatorData.AppendElements(aAuthenticatorData);
|
||||
mCredentialId.AppendElements(aCredentialId);
|
||||
mSignature.AppendElements(aSignature);
|
||||
|
@ -103,6 +111,8 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
|||
reinterpret_cast<uint8_t*>(
|
||||
aResponse->UserHandle()->GetElements().Elements()),
|
||||
aResponse->UserHandle()->Length());
|
||||
// authenticator attachment is not available on Android
|
||||
mAuthenticatorAttachment = Nothing();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -114,6 +124,7 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
|||
nsTArray<uint8_t> mCredentialId;
|
||||
nsTArray<uint8_t> mSignature;
|
||||
nsTArray<uint8_t> mUserHandle;
|
||||
Maybe<nsString> mAuthenticatorAttachment;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -86,6 +86,22 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestRegister(
|
|||
return;
|
||||
}
|
||||
|
||||
Maybe<nsString> authenticatorAttachment;
|
||||
nsString maybeAuthenticatorAttachment;
|
||||
rv = aValue->GetAuthenticatorAttachment(
|
||||
maybeAuthenticatorAttachment);
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
|
||||
u"CTAPRegisterAbort"_ns, 1);
|
||||
Unused << parent->SendAbort(aTransactionId,
|
||||
NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
authenticatorAttachment = Some(maybeAuthenticatorAttachment);
|
||||
}
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
bool credPropsRk;
|
||||
rv = aValue->GetCredPropsRk(&credPropsRk);
|
||||
|
@ -103,7 +119,8 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestRegister(
|
|||
}
|
||||
|
||||
WebAuthnMakeCredentialResult result(
|
||||
clientData, attObj, credentialId, transports, extensions);
|
||||
clientData, attObj, credentialId, transports, extensions,
|
||||
authenticatorAttachment);
|
||||
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
|
||||
u"CTAPRegisterFinish"_ns, 1);
|
||||
|
@ -202,6 +219,22 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestSign(
|
|||
nsTArray<uint8_t> userHandle;
|
||||
Unused << aValue->GetUserHandle(userHandle); // optional
|
||||
|
||||
Maybe<nsString> authenticatorAttachment;
|
||||
nsString maybeAuthenticatorAttachment;
|
||||
rv = aValue->GetAuthenticatorAttachment(
|
||||
maybeAuthenticatorAttachment);
|
||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
|
||||
u"CTAPSignAbort"_ns, 1);
|
||||
Unused << parent->SendAbort(aTransactionId,
|
||||
NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
authenticatorAttachment = Some(maybeAuthenticatorAttachment);
|
||||
}
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
bool usedAppId;
|
||||
rv = aValue->GetUsedAppId(&usedAppId);
|
||||
|
@ -217,9 +250,9 @@ mozilla::ipc::IPCResult WebAuthnTransactionParent::RecvRequestSign(
|
|||
extensions.AppendElement(WebAuthnExtensionResultAppId(usedAppId));
|
||||
}
|
||||
|
||||
WebAuthnGetAssertionResult result(clientData, credentialId,
|
||||
signature, authenticatorData,
|
||||
extensions, userHandle);
|
||||
WebAuthnGetAssertionResult result(
|
||||
clientData, credentialId, signature, authenticatorData,
|
||||
extensions, userHandle, authenticatorAttachment);
|
||||
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
|
||||
u"CTAPSignFinish"_ns, 1);
|
||||
|
|
|
@ -543,8 +543,20 @@ void WinWebAuthnManager::Register(
|
|||
}
|
||||
}
|
||||
|
||||
Maybe<nsString> authenticatorAttachment;
|
||||
if (pWebAuthNCredentialAttestation->dwVersion >=
|
||||
WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3) {
|
||||
if (pWebAuthNCredentialAttestation->dwUsedTransport &
|
||||
WEBAUTHN_CTAP_TRANSPORT_INTERNAL) {
|
||||
authenticatorAttachment = Some(u"platform"_ns);
|
||||
} else {
|
||||
authenticatorAttachment = Some(u"cross-platform"_ns);
|
||||
}
|
||||
}
|
||||
|
||||
WebAuthnMakeCredentialResult result(aInfo.ClientDataJSON(), attObject,
|
||||
credentialId, transports, extensions);
|
||||
credentialId, transports, extensions,
|
||||
authenticatorAttachment);
|
||||
|
||||
Unused << mTransactionParent->SendConfirmRegister(aTransactionId, result);
|
||||
ClearTransaction();
|
||||
|
@ -735,9 +747,11 @@ void WinWebAuthnManager::Sign(PWebAuthnTransactionParent* aTransactionParent,
|
|||
extensions.AppendElement(WebAuthnExtensionResultAppId(true));
|
||||
}
|
||||
|
||||
Maybe<nsString> authenticatorAttachment = Nothing(); // not available
|
||||
|
||||
WebAuthnGetAssertionResult result(aInfo.ClientDataJSON(), keyHandle,
|
||||
signature, authenticatorData, extensions,
|
||||
userHandle);
|
||||
userHandle, authenticatorAttachment);
|
||||
|
||||
Unused << mTransactionParent->SendConfirmSign(aTransactionId, result);
|
||||
ClearTransaction();
|
||||
|
|
|
@ -13,9 +13,10 @@ use authenticator::{
|
|||
ctap2::attestation::AttestationObject,
|
||||
ctap2::commands::get_info::AuthenticatorVersion,
|
||||
ctap2::server::{
|
||||
AuthenticationExtensionsClientInputs, PublicKeyCredentialDescriptor,
|
||||
PublicKeyCredentialParameters, PublicKeyCredentialUserEntity, RelyingParty,
|
||||
ResidentKeyRequirement, UserVerificationRequirement,
|
||||
AuthenticationExtensionsClientInputs, AuthenticatorAttachment,
|
||||
PublicKeyCredentialDescriptor, PublicKeyCredentialParameters,
|
||||
PublicKeyCredentialUserEntity, RelyingParty, ResidentKeyRequirement,
|
||||
UserVerificationRequirement,
|
||||
},
|
||||
errors::AuthenticatorError,
|
||||
statecallback::StateCallback,
|
||||
|
@ -29,7 +30,7 @@ use nserror::{
|
|||
NS_ERROR_FAILURE, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_AVAILABLE, NS_ERROR_NOT_IMPLEMENTED,
|
||||
NS_ERROR_NULL_POINTER, NS_OK,
|
||||
};
|
||||
use nsstring::{nsACString, nsCString, nsString};
|
||||
use nsstring::{nsACString, nsAString, nsCString, nsString};
|
||||
use serde::Serialize;
|
||||
use serde_cbor;
|
||||
use serde_json::json;
|
||||
|
@ -160,10 +161,16 @@ impl WebAuthnRegisterResult {
|
|||
xpcom_method!(get_transports => GetTransports() -> ThinVec<nsString>);
|
||||
fn get_transports(&self) -> Result<ThinVec<nsString>, nsresult> {
|
||||
// The list that we return here might be included in a future GetAssertion request as a
|
||||
// hint as to which transports to try. We currently only support the USB transport. If
|
||||
// that changes, we will need a mechanism to track which transport was used for a
|
||||
// request.
|
||||
Ok(thin_vec![nsString::from("usb")])
|
||||
// hint as to which transports to try. In production, we only support the "usb" transport.
|
||||
// In tests, the result is not very important, but we can at least return "internal" if
|
||||
// we're simulating platform attachment.
|
||||
if static_prefs::pref!("security.webauth.webauthn_enable_softtoken")
|
||||
&& self.result.attachment == AuthenticatorAttachment::Platform
|
||||
{
|
||||
Ok(thin_vec![nsString::from("internal")])
|
||||
} else {
|
||||
Ok(thin_vec![nsString::from("usb")])
|
||||
}
|
||||
}
|
||||
|
||||
xpcom_method!(get_cred_props_rk => GetCredPropsRk() -> bool);
|
||||
|
@ -178,6 +185,15 @@ impl WebAuthnRegisterResult {
|
|||
fn set_cred_props_rk(&self, _cred_props_rk: bool) -> Result<(), nsresult> {
|
||||
Err(NS_ERROR_NOT_IMPLEMENTED)
|
||||
}
|
||||
|
||||
xpcom_method!(get_authenticator_attachment => GetAuthenticatorAttachment() -> nsAString);
|
||||
fn get_authenticator_attachment(&self) -> Result<nsString, nsresult> {
|
||||
match self.result.attachment {
|
||||
AuthenticatorAttachment::CrossPlatform => Ok(nsString::from("cross-platform")),
|
||||
AuthenticatorAttachment::Platform => Ok(nsString::from("platform")),
|
||||
AuthenticatorAttachment::Unknown => Err(NS_ERROR_NOT_AVAILABLE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[xpcom(implement(nsIWebAuthnAttObj), atomic)]
|
||||
|
@ -264,6 +280,15 @@ impl WebAuthnSignResult {
|
|||
Ok(nsCString::from(name))
|
||||
}
|
||||
|
||||
xpcom_method!(get_authenticator_attachment => GetAuthenticatorAttachment() -> nsAString);
|
||||
fn get_authenticator_attachment(&self) -> Result<nsString, nsresult> {
|
||||
match self.result.attachment {
|
||||
AuthenticatorAttachment::CrossPlatform => Ok(nsString::from("cross-platform")),
|
||||
AuthenticatorAttachment::Platform => Ok(nsString::from("platform")),
|
||||
AuthenticatorAttachment::Unknown => Err(NS_ERROR_NOT_AVAILABLE),
|
||||
}
|
||||
}
|
||||
|
||||
xpcom_method!(get_used_app_id => GetUsedAppId() -> bool);
|
||||
fn get_used_app_id(&self) -> Result<bool, nsresult> {
|
||||
self.result.extensions.app_id.ok_or(NS_ERROR_NOT_AVAILABLE)
|
||||
|
|
|
@ -25,6 +25,8 @@ interface nsIWebAuthnRegisterResult : nsISupports {
|
|||
// readonly attribute bool hmacCreateSecret;
|
||||
|
||||
[must_use] attribute bool credPropsRk;
|
||||
|
||||
[must_use] readonly attribute AString authenticatorAttachment;
|
||||
};
|
||||
|
||||
// The nsIWebAuthnSignResult interface is used to construct IPDL-defined
|
||||
|
@ -52,4 +54,6 @@ interface nsIWebAuthnSignResult : nsISupports {
|
|||
|
||||
// appId field of AuthenticationExtensionsClientOutputs (Optional)
|
||||
[must_use] readonly attribute bool usedAppId;
|
||||
|
||||
[must_use] readonly attribute AString authenticatorAttachment;
|
||||
};
|
||||
|
|
|
@ -252,7 +252,7 @@
|
|||
};
|
||||
let registrationResponse = await navigator.credentials.create({publicKey});
|
||||
let registrationResponseJSON = registrationResponse.toJSON();
|
||||
is(Object.keys(registrationResponseJSON).length, 5, "registrationResponseJSON should have 5 properties");
|
||||
is(Object.keys(registrationResponseJSON).length, 6, "registrationResponseJSON should have 6 properties");
|
||||
is(registrationResponseJSON.id, registrationResponseJSON.rawId, "registrationResponseJSON.id and rawId should be the same");
|
||||
ok(isUrlsafeBase64(registrationResponseJSON.id), "registrationResponseJSON.id should be urlsafe base64");
|
||||
is(Object.keys(registrationResponseJSON.response).length, 6, "registrationResponseJSON.response should have 6 properties");
|
||||
|
@ -262,7 +262,8 @@
|
|||
ok(isUrlsafeBase64(registrationResponseJSON.response.attestationObject), "registrationResponseJSON.response.attestationObject should be urlsafe base64");
|
||||
is(registrationResponseJSON.response.publicKeyAlgorithm, cose_alg_ECDSA_w_SHA256, "registrationResponseJSON.response.publicKeyAlgorithm should be ECDSA with SHA256 (COSE)");
|
||||
is(registrationResponseJSON.response.transports.length, 1, "registrationResponseJSON.response.transports.length should be 1");
|
||||
is(registrationResponseJSON.response.transports[0], "usb", "registrationResponseJSON.response.transports[0] should be usb");
|
||||
is(registrationResponseJSON.response.transports[0], "internal", "registrationResponseJSON.response.transports[0] should be internal");
|
||||
is(registrationResponseJSON.authenticatorAttachment, "platform", "registrationResponseJSON.authenticatorAttachment should be platform");
|
||||
is(registrationResponseJSON.clientExtensionResults?.credProps?.rk, false, "registrationResponseJSON.clientExtensionResults.credProps.rk should be false");
|
||||
is(registrationResponseJSON.type, "public-key", "registrationResponseJSON.type should be public-key");
|
||||
});
|
||||
|
@ -286,13 +287,14 @@
|
|||
};
|
||||
let assertionResponse = await navigator.credentials.get(assertionRequest);
|
||||
let assertionResponseJSON = assertionResponse.toJSON();
|
||||
is(Object.keys(assertionResponseJSON).length, 5, "assertionResponseJSON should have 5 properties");
|
||||
is(Object.keys(assertionResponseJSON).length, 6, "assertionResponseJSON should have 6 properties");
|
||||
is(assertionResponseJSON.id, assertionResponseJSON.rawId, "assertionResponseJSON.id and rawId should be the same");
|
||||
ok(isUrlsafeBase64(assertionResponseJSON.id), "assertionResponseJSON.id should be urlsafe base64");
|
||||
is(Object.keys(assertionResponseJSON.response).length, 3, "assertionResponseJSON.response should have 3 properties");
|
||||
ok(isUrlsafeBase64(assertionResponseJSON.response.clientDataJSON), "assertionResponseJSON.response.clientDataJSON should be urlsafe base64");
|
||||
ok(isUrlsafeBase64(assertionResponseJSON.response.authenticatorData), "assertionResponseJSON.response.authenticatorData should be urlsafe base64");
|
||||
ok(isUrlsafeBase64(assertionResponseJSON.response.signature), "assertionResponseJSON.response.signature should be urlsafe base64");
|
||||
is(assertionResponseJSON.authenticatorAttachment, "platform", "assertionResponseJSON.authenticatorAttachment should be platform");
|
||||
is(Object.keys(assertionResponseJSON.clientExtensionResults).length, 0, "assertionResponseJSON.clientExtensionResults should be an empty dictionary");
|
||||
is(assertionResponseJSON.type, "public-key", "assertionResponseJSON.type should be public-key");
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
interface PublicKeyCredential : Credential {
|
||||
[SameObject, Throws] readonly attribute ArrayBuffer rawId;
|
||||
[SameObject] readonly attribute AuthenticatorResponse response;
|
||||
readonly attribute DOMString? authenticatorAttachment;
|
||||
AuthenticationExtensionsClientOutputs getClientExtensionResults();
|
||||
[NewObject] static Promise<boolean> isConditionalMediationAvailable();
|
||||
[Throws] object toJSON();
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
[createcredential-attachment.https.html]
|
||||
[navigator.credentials.create() with usb authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.create() with ble authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.create() with nfc authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.create() with internal authenticator, attachment as platform]
|
||||
expected: FAIL
|
|
@ -1,12 +0,0 @@
|
|||
[getcredential-attachment.https.html]
|
||||
[navigator.credentials.get() with usb authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.get() with ble authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.get() with nfc authenticator, attachment as cross-platform]
|
||||
expected: FAIL
|
||||
|
||||
[navigator.credentials.get() with internal authenticator, attachment as platform]
|
||||
expected: FAIL
|
Загрузка…
Ссылка в новой задаче