Commit a93e99ea authored by Nina Satragno's avatar Nina Satragno Committed by Commit Bot

[webauthn] Add support for all VirtualAuthenticatorOptions

This patch makes sure we honour all VirtualAuthenticator options
instead of silently ignoring most of them.

Bug: 826936
Change-Id: I34e81b5d11ced056226d6e36588a0e0ca1074cc9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1632729
Commit-Queue: Ken Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Auto-Submit: Nina Satragno <nsatragno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664851}
parent 7a6c82bc
......@@ -11,6 +11,7 @@
#include "base/base64url.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
......@@ -30,6 +31,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/service_manager_connection.h"
#include "crypto/sha2.h"
......@@ -494,6 +496,10 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) {
}
base::flat_set<device::FidoTransportProtocol> GetTransportsEnabledByFlags() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebAuthTestingAPI)) {
return device::GetAllTransportProtocols();
}
base::flat_set<device::FidoTransportProtocol> transports;
transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
transports.insert(device::FidoTransportProtocol::kInternal);
......
......@@ -24,6 +24,7 @@ using ::blink::mojom::PublicKeyCredentialRpEntityPtr;
using ::blink::mojom::PublicKeyCredentialType;
using ::blink::mojom::PublicKeyCredentialUserEntityPtr;
using ::blink::mojom::UserVerificationRequirement;
using ::blink::test::mojom::ClientToAuthenticatorProtocol;
// static
::device::FidoTransportProtocol
......@@ -239,4 +240,18 @@ TypeConverter<::device::AttestationConveyancePreference,
return ::device::AttestationConveyancePreference::NONE;
}
// static
::device::ProtocolVersion
TypeConverter<::device::ProtocolVersion, ClientToAuthenticatorProtocol>::
Convert(const ClientToAuthenticatorProtocol& input) {
switch (input) {
case ClientToAuthenticatorProtocol::U2F:
return ::device::ProtocolVersion::kU2f;
case ClientToAuthenticatorProtocol::CTAP2:
return ::device::ProtocolVersion::kCtap2;
}
NOTREACHED();
return ::device::ProtocolVersion::kUnknown;
}
} // namespace mojo
......@@ -17,6 +17,7 @@
#include "device/fido/public_key_credential_user_entity.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
// TODO(hongjunchoi): Remove type converters and instead expose mojo interface
// directly from device/fido service.
......@@ -111,6 +112,13 @@ struct TypeConverter<::device::AttestationConveyancePreference,
const ::blink::mojom::AttestationConveyancePreference& input);
};
template <>
struct TypeConverter<::device::ProtocolVersion,
::blink::test::mojom::ClientToAuthenticatorProtocol> {
static ::device::ProtocolVersion Convert(
const ::blink::test::mojom::ClientToAuthenticatorProtocol& input);
};
} // namespace mojo
#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_TYPE_CONVERTERS_H_
......@@ -10,15 +10,25 @@
#include "base/containers/span.h"
#include "base/guid.h"
#include "crypto/ec_private_key.h"
#include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_u2f_device.h"
namespace content {
VirtualAuthenticator::VirtualAuthenticator(
::device::FidoTransportProtocol transport)
: transport_(transport),
::device::ProtocolVersion protocol,
::device::FidoTransportProtocol transport,
::device::AuthenticatorAttachment attachment,
bool has_resident_key,
bool has_user_verification)
: protocol_(protocol),
attachment_(attachment),
has_resident_key_(has_resident_key),
has_user_verification_(has_user_verification),
unique_id_(base::GenerateGUID()),
state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {}
state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {
state_->transport = transport;
}
VirtualAuthenticator::~VirtualAuthenticator() = default;
......@@ -28,7 +38,21 @@ void VirtualAuthenticator::AddBinding(
}
std::unique_ptr<::device::FidoDevice> VirtualAuthenticator::ConstructDevice() {
return std::make_unique<::device::VirtualU2fDevice>(state_);
switch (protocol_) {
case ::device::ProtocolVersion::kU2f:
return std::make_unique<::device::VirtualU2fDevice>(state_);
case ::device::ProtocolVersion::kCtap2: {
device::VirtualCtap2Device::Config config;
config.resident_key_support = has_resident_key_;
config.internal_uv_support = has_user_verification_;
config.is_platform_authenticator =
attachment_ == ::device::AuthenticatorAttachment::kPlatform;
return std::make_unique<::device::VirtualCtap2Device>(state_, config);
}
default:
NOTREACHED();
return std::make_unique<::device::VirtualU2fDevice>(state_);
}
}
void VirtualAuthenticator::GetUniqueId(GetUniqueIdCallback callback) {
......
......@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_constants.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
......@@ -26,12 +26,18 @@ namespace content {
class CONTENT_EXPORT VirtualAuthenticator
: public blink::test::mojom::VirtualAuthenticator {
public:
explicit VirtualAuthenticator(::device::FidoTransportProtocol transport);
VirtualAuthenticator(::device::ProtocolVersion protocol,
::device::FidoTransportProtocol transport,
::device::AuthenticatorAttachment attachment,
bool has_resident_key,
bool has_user_verification);
~VirtualAuthenticator() override;
void AddBinding(blink::test::mojom::VirtualAuthenticatorRequest request);
::device::FidoTransportProtocol transport() const { return transport_; }
::device::FidoTransportProtocol transport() const {
return state_->transport;
}
const std::string& unique_id() const { return unique_id_; }
// Constructs a VirtualFidoDevice instance that will perform cryptographic
......@@ -55,7 +61,10 @@ class CONTENT_EXPORT VirtualAuthenticator
void GetUserPresence(GetUserPresenceCallback callback) override;
private:
const ::device::FidoTransportProtocol transport_;
const ::device::ProtocolVersion protocol_;
const ::device::AuthenticatorAttachment attachment_;
const bool has_resident_key_;
const bool has_user_verification_;
const std::string unique_id_;
scoped_refptr<::device::VirtualFidoDevice::State> state_;
mojo::BindingSet<blink::test::mojom::VirtualAuthenticator> binding_set_;
......
......@@ -79,7 +79,10 @@ void VirtualFidoDiscoveryFactory::CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
auto authenticator = std::make_unique<VirtualAuthenticator>(
mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport));
mojo::ConvertTo<::device::ProtocolVersion>(options->protocol),
mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport),
mojo::ConvertTo<::device::AuthenticatorAttachment>(options->attachment),
options->has_resident_key, options->has_user_verification);
auto* authenticator_ptr = authenticator.get();
authenticators_.emplace(authenticator_ptr->unique_id(),
std::move(authenticator));
......
......@@ -507,6 +507,11 @@ VirtualCtap2Device::VirtualCtap2Device(scoped_refptr<State> state,
}
}
if (config.is_platform_authenticator) {
options_updated = true;
options.is_platform_device = true;
}
if (options_updated) {
device_info_->options = std::move(options);
}
......
......@@ -65,6 +65,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) VirtualCtap2Device
// reject_silent_authenticator_requests causes the authenticator to return
// an error if a up=false assertion request is received.
bool reject_silent_authentication_requests = false;
bool is_platform_authenticator = false;
};
VirtualCtap2Device();
......
......@@ -50,7 +50,6 @@ promise_test(async t => {
navigator.credentials.get({ publicKey : customGetAssertionOptions}));
}, "navigator.credentials.get() with empty allowCredentials returns NotSupportedError");
promise_test(t => {
var customGetCredentialOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
customGetCredentialOptions.allowCredentials.transports = [];
......@@ -87,6 +86,22 @@ promise_test(async t => {
return promise;
}, "navigator.credentials.get() with abort signal flag set after promise resolved");
promise_test(async t => {
let bleTestAuthenticator = await navigator.credentials.test.createAuthenticator({
transport: blink.mojom.AuthenticatorTransport.BLE,
});
let bleCredential = deepCopy(ACCEPTABLE_CREDENTIAL);
bleCredential.id = new TextEncoder().encode("bleCredential");
bleCredential.transports = ["ble"]
assert_true(await bleTestAuthenticator.generateAndRegisterKey(bleCredential.id, "subdomain.example.test"));
let keys = await bleTestAuthenticator.registeredKeys();
assert_equals(keys.length, 1);
let customGetAssertionOptions = deepCopy(GET_CREDENTIAL_OPTIONS);
customGetAssertionOptions.allowCredentials = [bleCredential];
return navigator.credentials.get({ publicKey : customGetAssertionOptions });
}, "navigator.credentials.get() with authenticators supporting different transports");
promise_test(t => {
return navigator.credentials.test.clearAuthenticators();
}, "Clean up testing environment.");
......
......@@ -60,13 +60,13 @@ class VirtualAuthenticatorManager {
this.virtualAuthenticatorManager_.$.createRequest());
}
async createAuthenticator() {
async createAuthenticator(options = {}) {
let createAuthenticatorResponse = await this.virtualAuthenticatorManager_.createAuthenticator({
protocol: blink.test.mojom.ClientToAuthenticatorProtocol.U2F,
transport: blink.mojom.AuthenticatorTransport.USB,
attachment: blink.mojom.AuthenticatorAttachment.CROSS_PLATFORM,
hasResidentKey: false,
hasUserVerification: false,
protocol: options.protocol || blink.test.mojom.ClientToAuthenticatorProtocol.CTAP2,
transport: options.transport || blink.mojom.AuthenticatorTransport.USB,
attachment: options.attachment || blink.mojom.AuthenticatorAttachment.CROSS_PLATFORM,
hasResidentKey: options.hasResidentKey || false,
hasUserVerification: options.hasUserVerification || false,
});
return new VirtualAuthenticator(createAuthenticatorResponse.authenticator);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment