Commit d676fda0 authored by Yicheng Li's avatar Yicheng Li Committed by Commit Bot

Pass source window of in-session auth over dbus

In WebAuthn, we want the in-session auth dialog to be the child of
window that initiated the WebAuthn request. To do this, we register
the source window with a request_id. The request_id is passed all
the way through DBus. When the in-session auth dialog receives
the request_id, it validates that there's a corresponding
window and uses that window as the parent.

Bug: b/156258540
Cq-Depend: chromium:2487542
Change-Id: If0eab5a261a5423f74b3bad1718353184333cd69
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2488360Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Commit-Queue: Yicheng Li <yichengli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823435}
parent 5d7223a8
...@@ -543,6 +543,8 @@ component("ash") { ...@@ -543,6 +543,8 @@ component("ash") {
"in_session_auth/in_session_auth_dialog.h", "in_session_auth/in_session_auth_dialog.h",
"in_session_auth/in_session_auth_dialog_controller_impl.cc", "in_session_auth/in_session_auth_dialog_controller_impl.cc",
"in_session_auth/in_session_auth_dialog_controller_impl.h", "in_session_auth/in_session_auth_dialog_controller_impl.h",
"in_session_auth/webauthn_request_registrar_impl.cc",
"in_session_auth/webauthn_request_registrar_impl.h",
"keyboard/arc/arc_virtual_keyboard_container_layout_manager.cc", "keyboard/arc/arc_virtual_keyboard_container_layout_manager.cc",
"keyboard/arc/arc_virtual_keyboard_container_layout_manager.h", "keyboard/arc/arc_virtual_keyboard_container_layout_manager.h",
"keyboard/keyboard_controller_impl.cc", "keyboard/keyboard_controller_impl.cc",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/dbus/user_authentication_service_provider.h" #include "ash/dbus/user_authentication_service_provider.h"
#include "ash/public/cpp/in_session_auth_dialog_controller.h" #include "ash/public/cpp/in_session_auth_dialog_controller.h"
#include "ash/public/cpp/webauthn_request_registrar.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "dbus/bus.h" #include "dbus/bus.h"
...@@ -42,10 +43,41 @@ void UserAuthenticationServiceProvider::OnExported( ...@@ -42,10 +43,41 @@ void UserAuthenticationServiceProvider::OnExported(
void UserAuthenticationServiceProvider::ShowAuthDialog( void UserAuthenticationServiceProvider::ShowAuthDialog(
dbus::MethodCall* method_call, dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) { dbus::ExportedObject::ResponseSender response_sender) {
dbus::MessageReader reader(method_call);
std::string rp_id;
if (!reader.PopString(&rp_id)) {
LOG(ERROR) << "Unable to parse rp_id";
OnAuthFlowComplete(method_call, std::move(response_sender), false);
return;
}
// TODO(b/156258540): Show RP id in the dialog prompt.
int verification_type;
if (!reader.PopInt32(&verification_type)) {
LOG(ERROR) << "Unable to parse verification_type";
OnAuthFlowComplete(method_call, std::move(response_sender), false);
return;
}
uint64_t request_id = 0;
if (!reader.PopUint64(&request_id)) {
LOG(ERROR) << "Unable to parse request id";
OnAuthFlowComplete(method_call, std::move(response_sender), false);
return;
}
aura::Window* source_window =
WebAuthnRequestRegistrar::Get()->GetWindowForRequestId(request_id);
if (!source_window) {
LOG(ERROR) << "Cannot find window with the given request id";
OnAuthFlowComplete(method_call, std::move(response_sender), false);
return;
}
auto* auth_dialog_controller = InSessionAuthDialogController::Get(); auto* auth_dialog_controller = InSessionAuthDialogController::Get();
auth_dialog_controller->ShowAuthenticationDialog(base::BindOnce( auth_dialog_controller->ShowAuthenticationDialog(
&UserAuthenticationServiceProvider::OnAuthFlowComplete, source_window,
weak_ptr_factory_.GetWeakPtr(), method_call, std::move(response_sender))); base::BindOnce(&UserAuthenticationServiceProvider::OnAuthFlowComplete,
weak_ptr_factory_.GetWeakPtr(), method_call,
std::move(response_sender)));
} }
void UserAuthenticationServiceProvider::OnAuthFlowComplete( void UserAuthenticationServiceProvider::OnAuthFlowComplete(
......
...@@ -21,19 +21,20 @@ namespace { ...@@ -21,19 +21,20 @@ namespace {
constexpr int kCornerRadius = 12; constexpr int kCornerRadius = 12;
std::unique_ptr<views::Widget> CreateAuthDialogWidget( std::unique_ptr<views::Widget> CreateAuthDialogWidget(
std::unique_ptr<views::View> contents_view) { std::unique_ptr<views::View> contents_view,
aura::Window* parent) {
views::Widget::InitParams params( views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.delegate = new views::WidgetDelegate(); params.delegate = new views::WidgetDelegate();
params.show_state = ui::SHOW_STATE_NORMAL; params.show_state = ui::SHOW_STATE_NORMAL;
params.parent = nullptr; params.parent = parent;
params.name = "AuthDialogWidget"; params.name = "AuthDialogWidget";
params.shadow_type = views::Widget::InitParams::ShadowType::kDrop; params.shadow_type = views::Widget::InitParams::ShadowType::kDrop;
params.shadow_elevation = 3; params.shadow_elevation = 3;
params.delegate->SetInitiallyFocusedView(contents_view.get()); params.delegate->SetInitiallyFocusedView(contents_view.get());
params.delegate->SetModalType(ui::MODAL_TYPE_SYSTEM); params.delegate->SetModalType(ui::MODAL_TYPE_WINDOW);
params.delegate->SetOwnedByWidget(true); params.delegate->SetOwnedByWidget(true);
std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>(); std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>();
...@@ -45,10 +46,11 @@ std::unique_ptr<views::Widget> CreateAuthDialogWidget( ...@@ -45,10 +46,11 @@ std::unique_ptr<views::Widget> CreateAuthDialogWidget(
} // namespace } // namespace
InSessionAuthDialog::InSessionAuthDialog(uint32_t auth_methods) InSessionAuthDialog::InSessionAuthDialog(uint32_t auth_methods,
aura::Window* parent_window)
: auth_methods_(auth_methods) { : auth_methods_(auth_methods) {
widget_ = CreateAuthDialogWidget( widget_ = CreateAuthDialogWidget(
std::make_unique<AuthDialogContentsView>(auth_methods)); std::make_unique<AuthDialogContentsView>(auth_methods), parent_window);
aura::Window* window = widget_->GetNativeWindow(); aura::Window* window = widget_->GetNativeWindow();
rounded_corner_decorator_ = std::make_unique<RoundedCornerDecorator>( rounded_corner_decorator_ = std::make_unique<RoundedCornerDecorator>(
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
namespace aura {
class Window;
}
namespace views { namespace views {
class Widget; class Widget;
} }
...@@ -22,7 +26,7 @@ class RoundedCornerDecorator; ...@@ -22,7 +26,7 @@ class RoundedCornerDecorator;
// completed. // completed.
class InSessionAuthDialog { class InSessionAuthDialog {
public: public:
explicit InSessionAuthDialog(uint32_t auth_methods); InSessionAuthDialog(uint32_t auth_methods, aura::Window* parent_window);
InSessionAuthDialog(const InSessionAuthDialog&) = delete; InSessionAuthDialog(const InSessionAuthDialog&) = delete;
InSessionAuthDialog& operator=(const InSessionAuthDialog&) = delete; InSessionAuthDialog& operator=(const InSessionAuthDialog&) = delete;
~InSessionAuthDialog(); ~InSessionAuthDialog();
......
...@@ -5,17 +5,20 @@ ...@@ -5,17 +5,20 @@
#include "ash/in_session_auth/in_session_auth_dialog_controller_impl.h" #include "ash/in_session_auth/in_session_auth_dialog_controller_impl.h"
#include "ash/in_session_auth/auth_dialog_contents_view.h" #include "ash/in_session_auth/auth_dialog_contents_view.h"
#include "ash/in_session_auth/webauthn_request_registrar_impl.h"
#include "ash/public/cpp/in_session_auth_dialog_client.h" #include "ash/public/cpp/in_session_auth_dialog_client.h"
#include "ash/session/session_controller_impl.h" #include "ash/session/session_controller_impl.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "ui/aura/window.h"
namespace ash { namespace ash {
InSessionAuthDialogControllerImpl::InSessionAuthDialogControllerImpl() = InSessionAuthDialogControllerImpl::InSessionAuthDialogControllerImpl()
default; : webauthn_request_registrar_(
std::make_unique<WebAuthnRequestRegistrarImpl>()) {}
InSessionAuthDialogControllerImpl::~InSessionAuthDialogControllerImpl() = InSessionAuthDialogControllerImpl::~InSessionAuthDialogControllerImpl() =
default; default;
...@@ -26,11 +29,13 @@ void InSessionAuthDialogControllerImpl::SetClient( ...@@ -26,11 +29,13 @@ void InSessionAuthDialogControllerImpl::SetClient(
} }
void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog( void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog(
aura::Window* source_window,
FinishCallback finish_callback) { FinishCallback finish_callback) {
DCHECK(client_); DCHECK(client_);
// Concurrent requests are not supported. // Concurrent requests are not supported.
DCHECK(!dialog_); DCHECK(!dialog_);
window_tracker_.Add(source_window);
finish_callback_ = std::move(finish_callback); finish_callback_ = std::move(finish_callback);
AccountId account_id = AccountId account_id =
...@@ -43,7 +48,8 @@ void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog( ...@@ -43,7 +48,8 @@ void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog(
account_id, account_id,
base::BindOnce( base::BindOnce(
&InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession, &InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession,
weak_factory_.GetWeakPtr(), account_id, auth_methods)); weak_factory_.GetWeakPtr(), account_id, auth_methods,
source_window));
// OnStartFingerprintAuthSession checks PIN availability. // OnStartFingerprintAuthSession checks PIN availability.
return; return;
} }
...@@ -51,12 +57,13 @@ void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog( ...@@ -51,12 +57,13 @@ void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog(
client_->CheckPinAuthAvailability( client_->CheckPinAuthAvailability(
account_id, account_id,
base::BindOnce(&InSessionAuthDialogControllerImpl::OnPinCanAuthenticate, base::BindOnce(&InSessionAuthDialogControllerImpl::OnPinCanAuthenticate,
weak_factory_.GetWeakPtr(), auth_methods)); weak_factory_.GetWeakPtr(), auth_methods, source_window));
} }
void InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession( void InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession(
AccountId account_id, AccountId account_id,
uint32_t auth_methods, uint32_t auth_methods,
aura::Window* source_window,
bool success) { bool success) {
if (success) if (success)
auth_methods |= AuthDialogContentsView::kAuthFingerprint; auth_methods |= AuthDialogContentsView::kAuthFingerprint;
...@@ -64,11 +71,12 @@ void InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession( ...@@ -64,11 +71,12 @@ void InSessionAuthDialogControllerImpl::OnStartFingerprintAuthSession(
client_->CheckPinAuthAvailability( client_->CheckPinAuthAvailability(
account_id, account_id,
base::BindOnce(&InSessionAuthDialogControllerImpl::OnPinCanAuthenticate, base::BindOnce(&InSessionAuthDialogControllerImpl::OnPinCanAuthenticate,
weak_factory_.GetWeakPtr(), auth_methods)); weak_factory_.GetWeakPtr(), auth_methods, source_window));
} }
void InSessionAuthDialogControllerImpl::OnPinCanAuthenticate( void InSessionAuthDialogControllerImpl::OnPinCanAuthenticate(
uint32_t auth_methods, uint32_t auth_methods,
aura::Window* source_window,
bool pin_auth_available) { bool pin_auth_available) {
if (pin_auth_available) if (pin_auth_available)
auth_methods |= AuthDialogContentsView::kAuthPin; auth_methods |= AuthDialogContentsView::kAuthPin;
...@@ -81,7 +89,14 @@ void InSessionAuthDialogControllerImpl::OnPinCanAuthenticate( ...@@ -81,7 +89,14 @@ void InSessionAuthDialogControllerImpl::OnPinCanAuthenticate(
return; return;
} }
dialog_ = std::make_unique<InSessionAuthDialog>(auth_methods); if (!window_tracker_.Contains(source_window)) {
LOG(ERROR) << "Source window is no longer available.";
Cancel();
return;
}
window_tracker_.Remove(source_window);
dialog_ = std::make_unique<InSessionAuthDialog>(auth_methods, source_window);
} }
void InSessionAuthDialogControllerImpl::DestroyAuthenticationDialog() { void InSessionAuthDialogControllerImpl::DestroyAuthenticationDialog() {
...@@ -93,6 +108,7 @@ void InSessionAuthDialogControllerImpl::DestroyAuthenticationDialog() { ...@@ -93,6 +108,7 @@ void InSessionAuthDialogControllerImpl::DestroyAuthenticationDialog() {
client_->EndFingerprintAuthSession(); client_->EndFingerprintAuthSession();
dialog_.reset(); dialog_.reset();
window_tracker_.RemoveAll();
} }
void InSessionAuthDialogControllerImpl::AuthenticateUserWithPin( void InSessionAuthDialogControllerImpl::AuthenticateUserWithPin(
......
...@@ -12,12 +12,18 @@ ...@@ -12,12 +12,18 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "ui/aura/window_tracker.h"
class AccountId; class AccountId;
namespace aura {
class Window;
}
namespace ash { namespace ash {
class InSessionAuthDialogClient; class InSessionAuthDialogClient;
class WebAuthnRequestRegistrarImpl;
// InSessionAuthDialogControllerImpl persists as long as UI is running. // InSessionAuthDialogControllerImpl persists as long as UI is running.
class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController { class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController {
...@@ -31,7 +37,8 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController { ...@@ -31,7 +37,8 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController {
// InSessionAuthDialogController overrides // InSessionAuthDialogController overrides
void SetClient(InSessionAuthDialogClient* client) override; void SetClient(InSessionAuthDialogClient* client) override;
void ShowAuthenticationDialog(FinishCallback finish_callback) override; void ShowAuthenticationDialog(aura::Window* source_window,
FinishCallback finish_callback) override;
void DestroyAuthenticationDialog() override; void DestroyAuthenticationDialog() override;
void AuthenticateUserWithPin(const std::string& pin, void AuthenticateUserWithPin(const std::string& pin,
OnAuthenticateCallback callback) override; OnAuthenticateCallback callback) override;
...@@ -43,8 +50,11 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController { ...@@ -43,8 +50,11 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController {
bool IsFingerprintAvailable(const AccountId& account_id); bool IsFingerprintAvailable(const AccountId& account_id);
void OnStartFingerprintAuthSession(AccountId account_id, void OnStartFingerprintAuthSession(AccountId account_id,
uint32_t auth_methods, uint32_t auth_methods,
aura::Window* source_window,
bool success); bool success);
void OnPinCanAuthenticate(uint32_t auth_methods, bool pin_auth_available); void OnPinCanAuthenticate(uint32_t auth_methods,
aura::Window* source_window,
bool pin_auth_available);
// Callback to execute when auth on ChromeOS side completes. // Callback to execute when auth on ChromeOS side completes.
void OnAuthenticateComplete(OnAuthenticateCallback callback, bool success); void OnAuthenticateComplete(OnAuthenticateCallback callback, bool success);
...@@ -62,6 +72,10 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController { ...@@ -62,6 +72,10 @@ class InSessionAuthDialogControllerImpl : public InSessionAuthDialogController {
std::unique_ptr<InSessionAuthDialog> dialog_; std::unique_ptr<InSessionAuthDialog> dialog_;
aura::WindowTracker window_tracker_;
std::unique_ptr<WebAuthnRequestRegistrarImpl> webauthn_request_registrar_;
base::WeakPtrFactory<InSessionAuthDialogControllerImpl> weak_factory_{this}; base::WeakPtrFactory<InSessionAuthDialogControllerImpl> weak_factory_{this};
}; };
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/in_session_auth/webauthn_request_registrar_impl.h"
#include "ash/shell.h"
#include "ash/wm/mru_window_tracker.h"
#include "ui/aura/window.h"
#include "ui/base/class_property.h"
namespace ash {
namespace {
// A property key to tie the WebAuthn request id to a window.
DEFINE_UI_CLASS_PROPERTY_KEY(uint32_t, kWebAuthnRequestId, 0u)
uint32_t g_current_request_id = 0u;
} // namespace
WebAuthnRequestRegistrarImpl::WebAuthnRequestRegistrarImpl() = default;
WebAuthnRequestRegistrarImpl::~WebAuthnRequestRegistrarImpl() = default;
WebAuthnRequestRegistrarImpl::GenerateRequestIdCallback
WebAuthnRequestRegistrarImpl::GetRegisterCallback(aura::Window* window) {
window_tracker_.Add(window);
// base::Unretained() is safe here because WebAuthnRequestRegistrarImpl
// has the same lifetime as Shell and is released at
// PostMainMessageLoopRun stage. The callback should not be invoked
// after main message loop tearing down.
return base::BindRepeating(&WebAuthnRequestRegistrarImpl::DoRegister,
base::Unretained(this), window);
}
uint32_t WebAuthnRequestRegistrarImpl::DoRegister(aura::Window* window) {
g_current_request_id++;
// If |window| is still valid, associate it with the new request id.
// If |window| is gone, the incremented id will fail the request later,
// which is ok.
if (window_tracker_.Contains(window))
window->SetProperty(kWebAuthnRequestId, g_current_request_id);
return g_current_request_id;
}
aura::Window* WebAuthnRequestRegistrarImpl::GetWindowForRequestId(
uint32_t request_id) {
MruWindowTracker::WindowList windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kAllDesks);
for (aura::Window* window : windows) {
uint32_t window_request_id = window->GetProperty(kWebAuthnRequestId);
if (window_request_id == request_id) {
return window;
}
}
return nullptr;
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_IN_SESSION_AUTH_WEBAUTHN_REQUEST_REGISTRAR_IMPL_H_
#define ASH_IN_SESSION_AUTH_WEBAUTHN_REQUEST_REGISTRAR_IMPL_H_
#include "ash/public/cpp/webauthn_request_registrar.h"
#include "base/callback_forward.h"
#include "ui/aura/window_tracker.h"
namespace aura {
class Window;
}
namespace ash {
// WebAuthnRequestRegistrarImpl persists as long as UI is running.
class WebAuthnRequestRegistrarImpl : public WebAuthnRequestRegistrar {
public:
WebAuthnRequestRegistrarImpl();
WebAuthnRequestRegistrarImpl(const WebAuthnRequestRegistrarImpl&) = delete;
WebAuthnRequestRegistrarImpl& operator=(const WebAuthnRequestRegistrarImpl&) =
delete;
~WebAuthnRequestRegistrarImpl() override;
// WebAuthnRequestRegistrar:
GenerateRequestIdCallback GetRegisterCallback(aura::Window* window) override;
aura::Window* GetWindowForRequestId(uint32_t request_id) override;
private:
uint32_t DoRegister(aura::Window* window);
aura::WindowTracker window_tracker_;
};
} // namespace ash
#endif // ASH_IN_SESSION_AUTH_WEBAUTHN_REQUEST_REGISTRAR_IMPL_H_
...@@ -297,6 +297,8 @@ component("cpp") { ...@@ -297,6 +297,8 @@ component("cpp") {
"wallpaper_controller_observer.h", "wallpaper_controller_observer.h",
"wallpaper_info.h", "wallpaper_info.h",
"wallpaper_types.h", "wallpaper_types.h",
"webauthn_request_registrar.cc",
"webauthn_request_registrar.h",
"window_animation_types.h", "window_animation_types.h",
"window_backdrop.cc", "window_backdrop.cc",
"window_backdrop.h", "window_backdrop.h",
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#include "ash/public/cpp/in_session_auth_dialog_client.h" #include "ash/public/cpp/in_session_auth_dialog_client.h"
#include "base/optional.h" #include "base/optional.h"
namespace aura {
class Window;
}
namespace ash { namespace ash {
// InSessionAuthDialogController manages the in-session auth dialog. // InSessionAuthDialogController manages the in-session auth dialog.
...@@ -29,7 +33,8 @@ class ASH_PUBLIC_EXPORT InSessionAuthDialogController { ...@@ -29,7 +33,8 @@ class ASH_PUBLIC_EXPORT InSessionAuthDialogController {
virtual void SetClient(InSessionAuthDialogClient* client) = 0; virtual void SetClient(InSessionAuthDialogClient* client) = 0;
// Displays the authentication dialog. // Displays the authentication dialog.
virtual void ShowAuthenticationDialog(FinishCallback finish_callback) = 0; virtual void ShowAuthenticationDialog(aura::Window* source_window,
FinishCallback finish_callback) = 0;
// Destroys the authentication dialog. // Destroys the authentication dialog.
virtual void DestroyAuthenticationDialog() = 0; virtual void DestroyAuthenticationDialog() = 0;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/public/cpp/webauthn_request_registrar.h"
#include "base/check_op.h"
namespace ash {
namespace {
WebAuthnRequestRegistrar* g_instance = nullptr;
} // namespace
// static
WebAuthnRequestRegistrar* WebAuthnRequestRegistrar::Get() {
return g_instance;
}
WebAuthnRequestRegistrar::WebAuthnRequestRegistrar() {
DCHECK_EQ(nullptr, g_instance);
g_instance = this;
}
WebAuthnRequestRegistrar::~WebAuthnRequestRegistrar() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
} // namespace ash
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_PUBLIC_CPP_WEBAUTHN_REQUEST_REGISTRAR_H_
#define ASH_PUBLIC_CPP_WEBAUTHN_REQUEST_REGISTRAR_H_
#include <stdint.h>
#include "ash/public/cpp/ash_public_export.h"
#include "base/callback_forward.h"
namespace aura {
class Window;
}
namespace ash {
// Provides service to associate webauthn request ids with windows.
class ASH_PUBLIC_EXPORT WebAuthnRequestRegistrar {
public:
// Returns the singleton instance.
static WebAuthnRequestRegistrar* Get();
// Returns a callback to generate request id for |window|.
using GenerateRequestIdCallback = base::RepeatingCallback<uint32_t()>;
virtual GenerateRequestIdCallback GetRegisterCallback(
aura::Window* window) = 0;
// Returns the window that was registered with |request_id|, or nullptr if no
// such window.
virtual aura::Window* GetWindowForRequestId(uint32_t request_id) = 0;
protected:
WebAuthnRequestRegistrar();
virtual ~WebAuthnRequestRegistrar();
};
} // namespace ash
#endif // ASH_PUBLIC_CPP_WEBAUTHN_REQUEST_REGISTRAR_H_
...@@ -40,7 +40,8 @@ class FakeInSessionAuthDialogController ...@@ -40,7 +40,8 @@ class FakeInSessionAuthDialogController
// ash::InSessionAuthDialogController: // ash::InSessionAuthDialogController:
void SetClient(ash::InSessionAuthDialogClient* client) override {} void SetClient(ash::InSessionAuthDialogClient* client) override {}
void ShowAuthenticationDialog(FinishCallback callback) override {} void ShowAuthenticationDialog(aura::Window* source_window,
FinishCallback callback) override {}
void DestroyAuthenticationDialog() override {} void DestroyAuthenticationDialog() override {}
void AuthenticateUserWithPin(const std::string& pin, void AuthenticateUserWithPin(const std::string& pin,
OnAuthenticateCallback callback) override {} OnAuthenticateCallback callback) override {}
......
...@@ -46,6 +46,11 @@ ...@@ -46,6 +46,11 @@
#include "device/fido/win/authenticator.h" #include "device/fido/win/authenticator.h"
#endif #endif
#if defined(OS_CHROMEOS)
#include "ash/public/cpp/webauthn_request_registrar.h"
#include "ui/aura/window.h"
#endif
namespace { namespace {
// Returns true iff |relying_party_id| is listed in the // Returns true iff |relying_party_id| is listed in the
...@@ -446,6 +451,16 @@ ChromeAuthenticatorRequestDelegate::TouchIdAuthenticatorConfigForProfile( ...@@ -446,6 +451,16 @@ ChromeAuthenticatorRequestDelegate::TouchIdAuthenticatorConfigForProfile(
} }
#endif #endif
#if defined(OS_CHROMEOS)
ChromeAuthenticatorRequestDelegate::ChromeOSGenerateRequestIdCallback
ChromeAuthenticatorRequestDelegate::GetGenerateRequestIdCallback(
content::RenderFrameHost* render_frame_host) {
aura::Window* window =
render_frame_host->GetNativeView()->GetToplevelWindow();
return ash::WebAuthnRequestRegistrar::Get()->GetRegisterCallback(window);
}
#endif // defined(OS_CHROMEOS)
void ChromeAuthenticatorRequestDelegate::UpdateLastTransportUsed( void ChromeAuthenticatorRequestDelegate::UpdateLastTransportUsed(
device::FidoTransportProtocol transport) { device::FidoTransportProtocol transport) {
PrefService* prefs = PrefService* prefs =
......
...@@ -57,6 +57,11 @@ class ChromeAuthenticatorRequestDelegate ...@@ -57,6 +57,11 @@ class ChromeAuthenticatorRequestDelegate
override; override;
#endif // defined(OS_MAC) #endif // defined(OS_MAC)
#if defined(OS_CHROMEOS)
ChromeOSGenerateRequestIdCallback GetGenerateRequestIdCallback(
content::RenderFrameHost* render_frame_host) override;
#endif // defined(OS_CHROMEOS)
base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr(); base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr();
AuthenticatorRequestDialogModel* WeakDialogModelForTesting() const; AuthenticatorRequestDialogModel* WeakDialogModelForTesting() const;
......
...@@ -638,6 +638,8 @@ std::unique_ptr<device::FidoDiscoveryFactory> MakeDiscoveryFactory( ...@@ -638,6 +638,8 @@ std::unique_ptr<device::FidoDiscoveryFactory> MakeDiscoveryFactory(
!is_u2f_api_request) { !is_u2f_api_request) {
constexpr device::VidPid kChromeOsU2fdVidPid{0x18d1, 0x502c}; constexpr device::VidPid kChromeOsU2fdVidPid{0x18d1, 0x502c};
discovery_factory->set_hid_ignore_list({kChromeOsU2fdVidPid}); discovery_factory->set_hid_ignore_list({kChromeOsU2fdVidPid});
discovery_factory->set_generate_request_id_callback(
request_delegate->GetGenerateRequestIdCallback(render_frame_host));
} }
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
......
...@@ -88,6 +88,14 @@ AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig() { ...@@ -88,6 +88,14 @@ AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig() {
} }
#endif // defined(OS_MAC) #endif // defined(OS_MAC)
#if defined(OS_CHROMEOS)
AuthenticatorRequestClientDelegate::ChromeOSGenerateRequestIdCallback
AuthenticatorRequestClientDelegate::GetGenerateRequestIdCallback(
RenderFrameHost* render_frame_host) {
return base::NullCallback();
}
#endif
base::Optional<bool> AuthenticatorRequestClientDelegate:: base::Optional<bool> AuthenticatorRequestClientDelegate::
IsUserVerifyingPlatformAuthenticatorAvailableOverride() { IsUserVerifyingPlatformAuthenticatorAvailableOverride() {
return base::nullopt; return base::nullopt;
......
...@@ -33,6 +33,10 @@ class Origin; ...@@ -33,6 +33,10 @@ class Origin;
namespace content { namespace content {
#if defined(OS_CHROMEOS)
class RenderFrameHost;
#endif
// Interface that the embedder should implement to provide the //content layer // Interface that the embedder should implement to provide the //content layer
// with embedder-specific configuration for a single Web Authentication API [1] // with embedder-specific configuration for a single Web Authentication API [1]
// request serviced in a given RenderFrame. // request serviced in a given RenderFrame.
...@@ -186,6 +190,19 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate ...@@ -186,6 +190,19 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate
GetTouchIdAuthenticatorConfig(); GetTouchIdAuthenticatorConfig();
#endif // defined(OS_MAC) #endif // defined(OS_MAC)
#if defined(OS_CHROMEOS)
// Callback that should generate and return a unique request id.
using ChromeOSGenerateRequestIdCallback = base::RepeatingCallback<uint32_t()>;
// Returns a callback to generate a request id for |render_frame_host|. The
// request id has two purposes: 1. ChromeOS UI will use the request id to
// find the source window and show a dialog accordingly; 2. The authenticator
// will include the request id when asking ChromeOS platform to cancel the
// request.
virtual ChromeOSGenerateRequestIdCallback GetGenerateRequestIdCallback(
RenderFrameHost* render_frame_host);
#endif // defined(OS_CHROMEOS)
// Returns a bool if the result of the isUserVerifyingPlatformAuthenticator // Returns a bool if the result of the isUserVerifyingPlatformAuthenticator
// API call should be overridden with that value, or base::nullopt otherwise. // API call should be overridden with that value, or base::nullopt otherwise.
virtual base::Optional<bool> virtual base::Optional<bool>
......
...@@ -22,7 +22,10 @@ ...@@ -22,7 +22,10 @@
namespace device { namespace device {
ChromeOSAuthenticator::ChromeOSAuthenticator() : weak_factory_(this) {} ChromeOSAuthenticator::ChromeOSAuthenticator(
base::RepeatingCallback<uint32_t()> generate_request_id_callback)
: generate_request_id_callback_(std::move(generate_request_id_callback)),
weak_factory_(this) {}
ChromeOSAuthenticator::~ChromeOSAuthenticator() {} ChromeOSAuthenticator::~ChromeOSAuthenticator() {}
...@@ -96,6 +99,8 @@ void ChromeOSAuthenticator::MakeCredential(CtapMakeCredentialRequest request, ...@@ -96,6 +99,8 @@ void ChromeOSAuthenticator::MakeCredential(CtapMakeCredentialRequest request,
req.set_user_entity( req.set_user_entity(
std::string(request.user.id.begin(), request.user.id.end())); std::string(request.user.id.begin(), request.user.id.end()));
req.set_resident_credential(request.resident_key_required); req.set_resident_credential(request.resident_key_required);
DCHECK(generate_request_id_callback_);
req.set_request_id(generate_request_id_callback_.Run());
dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FMakeCredential); dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FMakeCredential);
dbus::MessageWriter writer(&method_call); dbus::MessageWriter writer(&method_call);
...@@ -193,6 +198,9 @@ void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request, ...@@ -193,6 +198,9 @@ void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request,
req.set_rp_id(request.rp_id); req.set_rp_id(request.rp_id);
req.set_client_data_hash(std::string(request.client_data_hash.begin(), req.set_client_data_hash(std::string(request.client_data_hash.begin(),
request.client_data_hash.end())); request.client_data_hash.end()));
DCHECK(generate_request_id_callback_);
req.set_request_id(generate_request_id_callback_.Run());
for (const PublicKeyCredentialDescriptor& descriptor : request.allow_list) { for (const PublicKeyCredentialDescriptor& descriptor : request.allow_list) {
const std::vector<uint8_t>& id = descriptor.id(); const std::vector<uint8_t>& id = descriptor.id();
req.add_allowed_credential_id(std::string(id.begin(), id.end())); req.add_allowed_credential_id(std::string(id.begin(), id.end()));
......
...@@ -24,7 +24,8 @@ namespace device { ...@@ -24,7 +24,8 @@ namespace device {
class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
: public FidoAuthenticator { : public FidoAuthenticator {
public: public:
ChromeOSAuthenticator(); explicit ChromeOSAuthenticator(
base::RepeatingCallback<uint32_t()> generate_request_id_callback);
~ChromeOSAuthenticator() override; ~ChromeOSAuthenticator() override;
bool HasCredentialForGetAssertionRequest( bool HasCredentialForGetAssertionRequest(
...@@ -65,6 +66,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator ...@@ -65,6 +66,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
dbus::Response* dbus_response, dbus::Response* dbus_response,
dbus::ErrorResponse* error); dbus::ErrorResponse* error);
// Callback to set request_id in the window property.
base::RepeatingCallback<uint32_t()> generate_request_id_callback_;
base::WeakPtrFactory<ChromeOSAuthenticator> weak_factory_; base::WeakPtrFactory<ChromeOSAuthenticator> weak_factory_;
}; };
......
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
namespace device { namespace device {
FidoChromeOSDiscovery::FidoChromeOSDiscovery() FidoChromeOSDiscovery::FidoChromeOSDiscovery(
base::RepeatingCallback<uint32_t()> generate_request_id_callback)
: FidoDiscoveryBase(FidoTransportProtocol::kInternal), : FidoDiscoveryBase(FidoTransportProtocol::kInternal),
authenticator_(std::make_unique<ChromeOSAuthenticator>()), authenticator_(std::make_unique<ChromeOSAuthenticator>(
std::move(generate_request_id_callback))),
weak_factory_(this) {} weak_factory_(this) {}
FidoChromeOSDiscovery::~FidoChromeOSDiscovery() {} FidoChromeOSDiscovery::~FidoChromeOSDiscovery() {}
......
...@@ -17,7 +17,8 @@ namespace device { ...@@ -17,7 +17,8 @@ namespace device {
class COMPONENT_EXPORT(DEVICE_FIDO) FidoChromeOSDiscovery class COMPONENT_EXPORT(DEVICE_FIDO) FidoChromeOSDiscovery
: public FidoDiscoveryBase { : public FidoDiscoveryBase {
public: public:
FidoChromeOSDiscovery(); explicit FidoChromeOSDiscovery(
base::RepeatingCallback<uint32_t()> generate_request_id_callback);
~FidoChromeOSDiscovery() override; ~FidoChromeOSDiscovery() override;
// FidoDiscoveryBase: // FidoDiscoveryBase:
......
...@@ -178,9 +178,15 @@ FidoDiscoveryFactory::MaybeCreatePlatformDiscovery() const { ...@@ -178,9 +178,15 @@ FidoDiscoveryFactory::MaybeCreatePlatformDiscovery() const {
std::unique_ptr<FidoDiscoveryBase> std::unique_ptr<FidoDiscoveryBase>
FidoDiscoveryFactory::MaybeCreatePlatformDiscovery() const { FidoDiscoveryFactory::MaybeCreatePlatformDiscovery() const {
return base::FeatureList::IsEnabled(kWebAuthCrosPlatformAuthenticator) return base::FeatureList::IsEnabled(kWebAuthCrosPlatformAuthenticator)
? std::make_unique<FidoChromeOSDiscovery>() ? std::make_unique<FidoChromeOSDiscovery>(
generate_request_id_callback_)
: nullptr; : nullptr;
} }
void FidoDiscoveryFactory::set_generate_request_id_callback(
base::RepeatingCallback<uint32_t()> callback) {
generate_request_id_callback_ = std::move(callback);
}
#endif #endif
} // namespace device } // namespace device
...@@ -89,6 +89,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -89,6 +89,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
WinWebAuthnApi* win_webauthn_api() const; WinWebAuthnApi* win_webauthn_api() const;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
#if defined(OS_CHROMEOS)
// Records the callback to generates request_id.
void set_generate_request_id_callback(base::RepeatingCallback<uint32_t()>);
#endif // defined(OS_CHROMEOS)
protected: protected:
static std::vector<std::unique_ptr<FidoDiscoveryBase>> SingleDiscovery( static std::vector<std::unique_ptr<FidoDiscoveryBase>> SingleDiscovery(
std::unique_ptr<FidoDiscoveryBase> discovery); std::unique_ptr<FidoDiscoveryBase> discovery);
...@@ -113,6 +118,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory { ...@@ -113,6 +118,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
#if defined(OS_WIN) #if defined(OS_WIN)
WinWebAuthnApi* win_webauthn_api_ = nullptr; WinWebAuthnApi* win_webauthn_api_ = nullptr;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
#if defined(OS_CHROMEOS)
base::RepeatingCallback<uint32_t()> generate_request_id_callback_;
#endif // defined(OS_CHROMEOS)
base::flat_set<VidPid> hid_ignore_list_; base::flat_set<VidPid> hid_ignore_list_;
}; };
......
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