diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index 5535339a08ade9..63ce542da5ce37 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc @@ -166,6 +166,12 @@ std::unique_ptr CreateSheetViewForCurrentStepOf( AuthenticatorGenericErrorSheetModel:: ForClientPinErrorAuthenticatorRemoved(dialog_model)); break; + case Step::kResidentCredentialConfirmation: + sheet_view = std::make_unique( + std::make_unique< + AuthenticatorResidentCredentialConfirmationSheetView>( + dialog_model)); + break; case Step::kSelectAccount: sheet_view = std::make_unique( std::make_unique(dialog_model)); diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index 86997c19fbd6f9..c75a6c14590de9 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc @@ -275,6 +275,11 @@ IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_storage_full) { ShowAndVerifyUi(); } +IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, + InvokeUi_resident_credential_confirm) { + ShowAndVerifyUi(); +} + IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_account_select) { ShowAndVerifyUi(); } diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index 064bda2802cae3..705c4b1f8c622d 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc @@ -42,8 +42,7 @@ base::string16 GetRelyingPartyIdString( base::Optional PossibleResidentKeyWarning( AuthenticatorRequestDialogModel* dialog_model) { if (dialog_model->might_create_resident_credential()) { - return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY, - GetRelyingPartyIdString(dialog_model)); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY); } return base::nullopt; } @@ -987,6 +986,60 @@ base::string16 AuthenticatorGenericErrorSheetModel::GetStepDescription() const { 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( diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index 0113218876a04c..25b0f5a947ba2b 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h @@ -457,6 +457,26 @@ class AuthenticatorGenericErrorSheetModel : public AuthenticatorSheetModelBase { 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. class AuthenticatorSelectAccountSheetModel : public AuthenticatorSheetModelBase { diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 60ac8a7c1bcf8c..075cb8a4b0b3dd 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc @@ -129,7 +129,13 @@ void AuthenticatorRequestDialogModel:: // Windows UI. if (transport_availability_.has_win_native_api_authenticator && 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; } @@ -476,6 +482,11 @@ void AuthenticatorRequestDialogModel::OnHavePIN(const std::string& pin) { has_attempted_pin_entry_ = true; } +void AuthenticatorRequestDialogModel::OnResidentCredentialConfirmed() { + DCHECK_EQ(current_step(), Step::kResidentCredentialConfirmation); + HideDialogAndDispatchToNativeWindowsApi(); +} + void AuthenticatorRequestDialogModel::OnAttestationPermissionResponse( bool attestation_permission_granted) { if (!attestation_callback_) { diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 900f3851f8dd26..6dc4a3cd599245 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h @@ -94,6 +94,11 @@ class AuthenticatorRequestDialogModel { kClientPinErrorHardBlock, 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, kSelectAccount, @@ -334,6 +339,10 @@ class AuthenticatorRequestDialogModel { // OnHavePIN is called when the user enters a PIN in the UI. 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 // disallows an attestation permission request. void OnAttestationPermissionResponse(bool attestation_permission_granted); diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index 3b137213c1c010..b185f7fdf19fc8 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc @@ -18,6 +18,10 @@ #include "device/fido/fido_discovery_factory.h" #include "services/service_manager/public/cpp/connector.h" +#if defined(OS_WIN) +#include "device/fido/win/authenticator.h" +#endif + namespace device { // PlatformAuthenticatorInfo -------------------------- @@ -154,6 +158,8 @@ void FidoRequestHandlerBase::InitDiscoveriesWin( // responsible for dispatch of the authenticator and whether they // display any UI in addition to the one provided by the OS. 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 // the implementing class because it is not subject to the OS' diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index cc339201b549eb..ed9f89a2287ae4 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h @@ -94,6 +94,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase // - should dispatch immediately if no other transport is available 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 // authenticator if |has_win_native_api_authenticator| is true. // This allows the observer to distinguish it from other diff --git a/device/fido/win/authenticator.cc b/device/fido/win/authenticator.cc index 8eac19e67b665b..019f2bb6585257 100644 --- a/device/fido/win/authenticator.cc +++ b/device/fido/win/authenticator.cc @@ -42,6 +42,13 @@ bool WinWebAuthnApiAuthenticator:: 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) : FidoAuthenticator(), current_window_(current_window), diff --git a/device/fido/win/authenticator.h b/device/fido/win/authenticator.h index 11399f736e593b..a7677d22ec0b00 100644 --- a/device/fido/win/authenticator.h +++ b/device/fido/win/authenticator.h @@ -34,6 +34,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) WinWebAuthnApiAuthenticator // WinWebAuthnApi::IsAvailable(). 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. // // Callers must ensure that WinWebAuthnApi::IsAvailable() returns true