Commit e95b9a30 authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

chrome/browser/ui/webauthn: double-UI resident creds on Windows API v1.

This change adds a confirmation step when creating resident credentials
with Windows Webauthn DLL version one (currently in 19H1). This version
requires the use of native APIs for interaction with security keys, but
doesn't show a notice informing the user that creating a resident
credential will store information on their security key.

However, such a notice is a privacy requirement and therefore a
confirmation step is added prior to dispatching the API call.

Bug: 941120
Change-Id: Ia39aefe7e2b294a604346a66851dbda67372bd63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1601299Reviewed-by: default avatarMartin Kreichgauer <martinkr@chromium.org>
Commit-Queue: Adam Langley <agl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659267}
parent 4e8749b1
...@@ -166,6 +166,12 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf( ...@@ -166,6 +166,12 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
AuthenticatorGenericErrorSheetModel:: AuthenticatorGenericErrorSheetModel::
ForClientPinErrorAuthenticatorRemoved(dialog_model)); ForClientPinErrorAuthenticatorRemoved(dialog_model));
break; break;
case Step::kResidentCredentialConfirmation:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<
AuthenticatorResidentCredentialConfirmationSheetView>(
dialog_model));
break;
case Step::kSelectAccount: case Step::kSelectAccount:
sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>( sheet_view = std::make_unique<AuthenticatorSelectAccountSheetView>(
std::make_unique<AuthenticatorSelectAccountSheetModel>(dialog_model)); std::make_unique<AuthenticatorSelectAccountSheetModel>(dialog_model));
......
...@@ -275,6 +275,11 @@ IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_storage_full) { ...@@ -275,6 +275,11 @@ IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_storage_full) {
ShowAndVerifyUi(); ShowAndVerifyUi();
} }
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
InvokeUi_resident_credential_confirm) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_account_select) { IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_account_select) {
ShowAndVerifyUi(); ShowAndVerifyUi();
} }
......
...@@ -42,8 +42,7 @@ base::string16 GetRelyingPartyIdString( ...@@ -42,8 +42,7 @@ base::string16 GetRelyingPartyIdString(
base::Optional<base::string16> PossibleResidentKeyWarning( base::Optional<base::string16> PossibleResidentKeyWarning(
AuthenticatorRequestDialogModel* dialog_model) { AuthenticatorRequestDialogModel* dialog_model) {
if (dialog_model->might_create_resident_credential()) { if (dialog_model->might_create_resident_credential()) {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY, return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
GetRelyingPartyIdString(dialog_model));
} }
return base::nullopt; return base::nullopt;
} }
...@@ -987,6 +986,60 @@ base::string16 AuthenticatorGenericErrorSheetModel::GetStepDescription() const { ...@@ -987,6 +986,60 @@ base::string16 AuthenticatorGenericErrorSheetModel::GetStepDescription() const {
return description_; return description_;
} }
// AuthenticatorResidentCredentialConfirmationSheetView -----------------------
AuthenticatorResidentCredentialConfirmationSheetView::
AuthenticatorResidentCredentialConfirmationSheetView(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {}
AuthenticatorResidentCredentialConfirmationSheetView::
~AuthenticatorResidentCredentialConfirmationSheetView() = default;
const gfx::VectorIcon&
AuthenticatorResidentCredentialConfirmationSheetView::GetStepIllustration(
ImageColorScheme color_scheme) const {
return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
: kWebauthnPermissionIcon;
}
bool AuthenticatorResidentCredentialConfirmationSheetView::IsBackButtonVisible()
const {
return false;
}
bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonEnabled() const {
return true;
}
base::string16
AuthenticatorResidentCredentialConfirmationSheetView::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_NEXT);
}
base::string16
AuthenticatorResidentCredentialConfirmationSheetView::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
base::string16
AuthenticatorResidentCredentialConfirmationSheetView::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
}
void AuthenticatorResidentCredentialConfirmationSheetView::OnAccept() {
dialog_model()->OnResidentCredentialConfirmed();
}
// AuthenticatorSelectAccountSheetModel --------------------------------------- // AuthenticatorSelectAccountSheetModel ---------------------------------------
AuthenticatorSelectAccountSheetModel::AuthenticatorSelectAccountSheetModel( AuthenticatorSelectAccountSheetModel::AuthenticatorSelectAccountSheetModel(
......
...@@ -457,6 +457,26 @@ class AuthenticatorGenericErrorSheetModel : public AuthenticatorSheetModelBase { ...@@ -457,6 +457,26 @@ class AuthenticatorGenericErrorSheetModel : public AuthenticatorSheetModelBase {
base::string16 description_; base::string16 description_;
}; };
class AuthenticatorResidentCredentialConfirmationSheetView
: public AuthenticatorSheetModelBase {
public:
AuthenticatorResidentCredentialConfirmationSheetView(
AuthenticatorRequestDialogModel* dialog_model);
~AuthenticatorResidentCredentialConfirmationSheetView() override;
private:
// AuthenticatorSheetModelBase:
const gfx::VectorIcon& GetStepIllustration(
ImageColorScheme color_scheme) const override;
bool IsBackButtonVisible() const override;
bool IsAcceptButtonVisible() const override;
bool IsAcceptButtonEnabled() const override;
base::string16 GetAcceptButtonLabel() const override;
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
void OnAccept() override;
};
// The sheet shown when the user needs to select an account. // The sheet shown when the user needs to select an account.
class AuthenticatorSelectAccountSheetModel class AuthenticatorSelectAccountSheetModel
: public AuthenticatorSheetModelBase { : public AuthenticatorSheetModelBase {
......
...@@ -129,7 +129,13 @@ void AuthenticatorRequestDialogModel:: ...@@ -129,7 +129,13 @@ void AuthenticatorRequestDialogModel::
// Windows UI. // Windows UI.
if (transport_availability_.has_win_native_api_authenticator && if (transport_availability_.has_win_native_api_authenticator &&
transport_availability_.available_transports.empty()) { transport_availability_.available_transports.empty()) {
HideDialogAndDispatchToNativeWindowsApi(); if (might_create_resident_credential_ &&
!transport_availability_
.win_native_ui_shows_resident_credential_notice) {
SetCurrentStep(Step::kResidentCredentialConfirmation);
} else {
HideDialogAndDispatchToNativeWindowsApi();
}
return; return;
} }
...@@ -476,6 +482,11 @@ void AuthenticatorRequestDialogModel::OnHavePIN(const std::string& pin) { ...@@ -476,6 +482,11 @@ void AuthenticatorRequestDialogModel::OnHavePIN(const std::string& pin) {
has_attempted_pin_entry_ = true; has_attempted_pin_entry_ = true;
} }
void AuthenticatorRequestDialogModel::OnResidentCredentialConfirmed() {
DCHECK_EQ(current_step(), Step::kResidentCredentialConfirmation);
HideDialogAndDispatchToNativeWindowsApi();
}
void AuthenticatorRequestDialogModel::OnAttestationPermissionResponse( void AuthenticatorRequestDialogModel::OnAttestationPermissionResponse(
bool attestation_permission_granted) { bool attestation_permission_granted) {
if (!attestation_callback_) { if (!attestation_callback_) {
......
...@@ -94,6 +94,11 @@ class AuthenticatorRequestDialogModel { ...@@ -94,6 +94,11 @@ class AuthenticatorRequestDialogModel {
kClientPinErrorHardBlock, kClientPinErrorHardBlock,
kClientPinErrorAuthenticatorRemoved, kClientPinErrorAuthenticatorRemoved,
// Confirm user consent to create a resident credential. Used prior to
// triggering Windows-native APIs when Windows itself won't show any
// notice about resident credentials.
kResidentCredentialConfirmation,
// Account selection, // Account selection,
kSelectAccount, kSelectAccount,
...@@ -334,6 +339,10 @@ class AuthenticatorRequestDialogModel { ...@@ -334,6 +339,10 @@ class AuthenticatorRequestDialogModel {
// OnHavePIN is called when the user enters a PIN in the UI. // OnHavePIN is called when the user enters a PIN in the UI.
void OnHavePIN(const std::string& pin); void OnHavePIN(const std::string& pin);
// OnResidentCredentialConfirmed is called when a user accepts a dialog
// confirming that they're happy to create a resident credential.
void OnResidentCredentialConfirmed();
// OnAttestationPermissionResponse is called when the user either allows or // OnAttestationPermissionResponse is called when the user either allows or
// disallows an attestation permission request. // disallows an attestation permission request.
void OnAttestationPermissionResponse(bool attestation_permission_granted); void OnAttestationPermissionResponse(bool attestation_permission_granted);
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include "device/fido/fido_discovery_factory.h" #include "device/fido/fido_discovery_factory.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#if defined(OS_WIN)
#include "device/fido/win/authenticator.h"
#endif
namespace device { namespace device {
// PlatformAuthenticatorInfo -------------------------- // PlatformAuthenticatorInfo --------------------------
...@@ -154,6 +158,8 @@ void FidoRequestHandlerBase::InitDiscoveriesWin( ...@@ -154,6 +158,8 @@ void FidoRequestHandlerBase::InitDiscoveriesWin(
// responsible for dispatch of the authenticator and whether they // responsible for dispatch of the authenticator and whether they
// display any UI in addition to the one provided by the OS. // display any UI in addition to the one provided by the OS.
transport_availability_info_.has_win_native_api_authenticator = true; transport_availability_info_.has_win_native_api_authenticator = true;
transport_availability_info_.win_native_ui_shows_resident_credential_notice =
WinWebAuthnApiAuthenticator::ShowsResidentCredentialPrivacyNotice();
// Allow caBLE as a potential additional transport if requested by // Allow caBLE as a potential additional transport if requested by
// the implementing class because it is not subject to the OS' // the implementing class because it is not subject to the OS'
......
...@@ -94,6 +94,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase ...@@ -94,6 +94,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase
// - should dispatch immediately if no other transport is available // - should dispatch immediately if no other transport is available
bool has_win_native_api_authenticator = false; bool has_win_native_api_authenticator = false;
// Indicates whether the Windows native UI will include a privacy notice
// when creating a resident credential.
bool win_native_ui_shows_resident_credential_notice = false;
// Contains the authenticator ID of the native Windows // Contains the authenticator ID of the native Windows
// authenticator if |has_win_native_api_authenticator| is true. // authenticator if |has_win_native_api_authenticator| is true.
// This allows the observer to distinguish it from other // This allows the observer to distinguish it from other
......
...@@ -42,6 +42,13 @@ bool WinWebAuthnApiAuthenticator:: ...@@ -42,6 +42,13 @@ bool WinWebAuthnApiAuthenticator::
result == TRUE; result == TRUE;
} }
// static
bool WinWebAuthnApiAuthenticator::ShowsResidentCredentialPrivacyNotice() {
// TODO: Once Windows shows a resident credential privacy notice in their UI,
// this should check for the respective API version.
return false;
}
WinWebAuthnApiAuthenticator::WinWebAuthnApiAuthenticator(HWND current_window) WinWebAuthnApiAuthenticator::WinWebAuthnApiAuthenticator(HWND current_window)
: FidoAuthenticator(), : FidoAuthenticator(),
current_window_(current_window), current_window_(current_window),
......
...@@ -34,6 +34,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) WinWebAuthnApiAuthenticator ...@@ -34,6 +34,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) WinWebAuthnApiAuthenticator
// WinWebAuthnApi::IsAvailable(). // WinWebAuthnApi::IsAvailable().
static bool IsUserVerifyingPlatformAuthenticatorAvailable(); static bool IsUserVerifyingPlatformAuthenticatorAvailable();
// ShowsResidentCredentialPrivacyNotice returns true if the Windows native UI
// will show a privacy notice when creating a resident credential.
static bool ShowsResidentCredentialPrivacyNotice();
// Instantiates an authenticator that uses the default WinWebAuthnApi. // Instantiates an authenticator that uses the default WinWebAuthnApi.
// //
// Callers must ensure that WinWebAuthnApi::IsAvailable() returns true // Callers must ensure that WinWebAuthnApi::IsAvailable() returns true
......
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