Commit d1db8447 authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Add Cancel logic to WebAuthN UI

Add logic to cancel ongoing WebAuthN request when user clicks "cancel"
button from any UI modal or "back" button from the initial welcome
screen.

Bug: 847985
TBR: jam@chromium.org
Change-Id: Ia9a014cf78583c2512ceaebf822758aa0dc65d99
Reviewed-on: https://chromium-review.googlesource.com/1173489
Commit-Queue: Balazs Engedy <engedy@chromium.org>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#582886}
parent 5220d0e2
...@@ -73,11 +73,17 @@ void AuthenticatorRequestDialogModel::TryUsbDevice() { ...@@ -73,11 +73,17 @@ void AuthenticatorRequestDialogModel::TryUsbDevice() {
DCHECK_EQ(current_step(), Step::kUsbInsertAndActivateOnRegister); DCHECK_EQ(current_step(), Step::kUsbInsertAndActivateOnRegister);
} }
void AuthenticatorRequestDialogModel::Cancel() {} void AuthenticatorRequestDialogModel::Cancel() {
for (auto& observer : observers_)
observer.OnCancelRequest();
}
void AuthenticatorRequestDialogModel::Back() { void AuthenticatorRequestDialogModel::Back() {
// For now, return to the initial step all the time. if (current_step() == Step::kInitial) {
Cancel();
} else {
SetCurrentStep(Step::kInitial); SetCurrentStep(Step::kInitial);
}
} }
void AuthenticatorRequestDialogModel::AddObserver(Observer* observer) { void AuthenticatorRequestDialogModel::AddObserver(Observer* observer) {
......
...@@ -71,6 +71,10 @@ class AuthenticatorRequestDialogModel { ...@@ -71,6 +71,10 @@ class AuthenticatorRequestDialogModel {
// Called when the UX flow has navigated to a different step, so the UI // Called when the UX flow has navigated to a different step, so the UI
// should update. // should update.
virtual void OnStepTransition() {} virtual void OnStepTransition() {}
// Called when the user cancelled WebAuthN request by clicking the
// "cancel" button or the back arrow in the UI dialog.
virtual void OnCancelRequest() {}
}; };
AuthenticatorRequestDialogModel(); AuthenticatorRequestDialogModel();
......
...@@ -123,6 +123,14 @@ ChromeAuthenticatorRequestDelegate::~ChromeAuthenticatorRequestDelegate() { ...@@ -123,6 +123,14 @@ ChromeAuthenticatorRequestDelegate::~ChromeAuthenticatorRequestDelegate() {
} }
} }
base::Optional<device::FidoTransportProtocol>
ChromeAuthenticatorRequestDelegate::GetLastTransportUsed() const {
PrefService* prefs =
Profile::FromBrowserContext(browser_context())->GetPrefs();
return device::ConvertToFidoTransportProtocol(
prefs->GetString(kWebAuthnLastTransportUsedPrefName));
}
base::WeakPtr<ChromeAuthenticatorRequestDelegate> base::WeakPtr<ChromeAuthenticatorRequestDelegate>
ChromeAuthenticatorRequestDelegate::AsWeakPtr() { ChromeAuthenticatorRequestDelegate::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr(); return weak_ptr_factory_.GetWeakPtr();
...@@ -134,7 +142,8 @@ content::BrowserContext* ChromeAuthenticatorRequestDelegate::browser_context() ...@@ -134,7 +142,8 @@ content::BrowserContext* ChromeAuthenticatorRequestDelegate::browser_context()
->GetBrowserContext(); ->GetBrowserContext();
} }
void ChromeAuthenticatorRequestDelegate::DidStartRequest() { void ChromeAuthenticatorRequestDelegate::DidStartRequest(
base::OnceClosure cancel_callback) {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
if (!IsWebAuthnUiEnabled()) if (!IsWebAuthnUiEnabled())
return; return;
...@@ -143,6 +152,7 @@ void ChromeAuthenticatorRequestDelegate::DidStartRequest() { ...@@ -143,6 +152,7 @@ void ChromeAuthenticatorRequestDelegate::DidStartRequest() {
weak_dialog_model_ = dialog_model.get(); weak_dialog_model_ = dialog_model.get();
SetInitialUiModelBasedOnPreviouslyUsedTransport(weak_dialog_model_, SetInitialUiModelBasedOnPreviouslyUsedTransport(weak_dialog_model_,
GetLastTransportUsed()); GetLastTransportUsed());
cancel_callback_ = std::move(cancel_callback);
weak_dialog_model_->AddObserver(this); weak_dialog_model_->AddObserver(this);
ShowAuthenticatorRequestDialog( ShowAuthenticatorRequestDialog(
...@@ -248,12 +258,12 @@ ChromeAuthenticatorRequestDelegate::GetTouchIdAuthenticatorConfig() const { ...@@ -248,12 +258,12 @@ ChromeAuthenticatorRequestDelegate::GetTouchIdAuthenticatorConfig() const {
} }
#endif #endif
base::Optional<device::FidoTransportProtocol> void ChromeAuthenticatorRequestDelegate::UpdateLastTransportUsed(
ChromeAuthenticatorRequestDelegate::GetLastTransportUsed() const { device::FidoTransportProtocol transport) {
PrefService* prefs = PrefService* prefs =
Profile::FromBrowserContext(browser_context())->GetPrefs(); Profile::FromBrowserContext(browser_context())->GetPrefs();
return device::ConvertToFidoTransportProtocol( prefs->SetString(kWebAuthnLastTransportUsedPrefName,
prefs->GetString(kWebAuthnLastTransportUsedPrefName)); device::ToString(transport));
} }
void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorAdded( void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorAdded(
...@@ -281,15 +291,14 @@ void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorRemoved( ...@@ -281,15 +291,14 @@ void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorRemoved(
saved_authenticators.end()); saved_authenticators.end());
} }
void ChromeAuthenticatorRequestDelegate::UpdateLastTransportUsed(
device::FidoTransportProtocol transport) {
PrefService* prefs =
Profile::FromBrowserContext(browser_context())->GetPrefs();
prefs->SetString(kWebAuthnLastTransportUsedPrefName,
device::ToString(transport));
}
void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() { void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() {
DCHECK(weak_dialog_model_); DCHECK(weak_dialog_model_);
weak_dialog_model_ = nullptr; weak_dialog_model_ = nullptr;
} }
void ChromeAuthenticatorRequestDelegate::OnCancelRequest() {
// |cancel_callback_| must be invoked at most once as invocation of
// |cancel_callback_| will destroy |this|.
DCHECK(cancel_callback_);
std::move(cancel_callback_).Run();
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <string> #include <string>
#include "base/callback.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
...@@ -62,7 +63,7 @@ class ChromeAuthenticatorRequestDelegate ...@@ -62,7 +63,7 @@ class ChromeAuthenticatorRequestDelegate
content::BrowserContext* browser_context() const; content::BrowserContext* browser_context() const;
// content::AuthenticatorRequestClientDelegate: // content::AuthenticatorRequestClientDelegate:
void DidStartRequest() override; void DidStartRequest(base::OnceClosure cancel_callback) override;
bool ShouldPermitIndividualAttestation( bool ShouldPermitIndividualAttestation(
const std::string& relying_party_id) override; const std::string& relying_party_id) override;
void ShouldReturnAttestation( void ShouldReturnAttestation(
...@@ -79,9 +80,11 @@ class ChromeAuthenticatorRequestDelegate ...@@ -79,9 +80,11 @@ class ChromeAuthenticatorRequestDelegate
// AuthenticatorRequestDialogModel::Observer: // AuthenticatorRequestDialogModel::Observer:
void OnModelDestroyed() override; void OnModelDestroyed() override;
void OnCancelRequest() override;
content::RenderFrameHost* const render_frame_host_; content::RenderFrameHost* const render_frame_host_;
AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr; AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr;
base::OnceClosure cancel_callback_;
base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_; base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_;
......
...@@ -473,7 +473,9 @@ void AuthenticatorImpl::MakeCredential( ...@@ -473,7 +473,9 @@ void AuthenticatorImpl::MakeCredential(
DCHECK(make_credential_response_callback_.is_null()); DCHECK(make_credential_response_callback_.is_null());
make_credential_response_callback_ = std::move(callback); make_credential_response_callback_ = std::move(callback);
request_delegate_->DidStartRequest(); request_delegate_->DidStartRequest(
base::BindOnce(&AuthenticatorImpl::Cancel,
weak_factory_.GetWeakPtr()) /* cancel_callback */);
timer_->Start( timer_->Start(
FROM_HERE, options->adjusted_timeout, FROM_HERE, options->adjusted_timeout,
...@@ -569,7 +571,9 @@ void AuthenticatorImpl::GetAssertion( ...@@ -569,7 +571,9 @@ void AuthenticatorImpl::GetAssertion(
DCHECK(get_assertion_response_callback_.is_null()); DCHECK(get_assertion_response_callback_.is_null());
get_assertion_response_callback_ = std::move(callback); get_assertion_response_callback_ = std::move(callback);
request_delegate_->DidStartRequest(); request_delegate_->DidStartRequest(
base::BindOnce(&AuthenticatorImpl::Cancel,
weak_factory_.GetWeakPtr()) /* cancel_callback */);
timer_->Start( timer_->Start(
FROM_HERE, options->adjusted_timeout, FROM_HERE, options->adjusted_timeout,
...@@ -805,6 +809,16 @@ void AuthenticatorImpl::OnTimeout() { ...@@ -805,6 +809,16 @@ void AuthenticatorImpl::OnTimeout() {
} }
} }
void AuthenticatorImpl::Cancel() {
// If response callback is invoked already, then ignore cancel request.
if (!make_credential_response_callback_ && !get_assertion_response_callback_)
return;
// Response from user cancellation is indistinguishable from error due to
// timeout.
OnTimeout();
}
void AuthenticatorImpl::InvokeCallbackAndCleanup( void AuthenticatorImpl::InvokeCallbackAndCleanup(
MakeCredentialCallback callback, MakeCredentialCallback callback,
blink::mojom::AuthenticatorStatus status, blink::mojom::AuthenticatorStatus status,
......
...@@ -141,6 +141,8 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator, ...@@ -141,6 +141,8 @@ class CONTENT_EXPORT AuthenticatorImpl : public blink::mojom::Authenticator,
// Runs when timer expires and cancels all issued requests to a U2fDevice. // Runs when timer expires and cancels all issued requests to a U2fDevice.
void OnTimeout(); void OnTimeout();
// Runs when the user cancels WebAuthN request via UI dialog.
void Cancel();
void InvokeCallbackAndCleanup( void InvokeCallbackAndCleanup(
MakeCredentialCallback callback, MakeCredentialCallback callback,
......
...@@ -1141,7 +1141,7 @@ class TestAuthenticatorRequestDelegate ...@@ -1141,7 +1141,7 @@ class TestAuthenticatorRequestDelegate
is_focused_(is_focused) {} is_focused_(is_focused) {}
~TestAuthenticatorRequestDelegate() override {} ~TestAuthenticatorRequestDelegate() override {}
void DidStartRequest() override { void DidStartRequest(base::OnceClosure cancel_callback) override {
ASSERT_TRUE(did_start_request_callback_) << "DidStartRequest called twice."; ASSERT_TRUE(did_start_request_callback_) << "DidStartRequest called twice.";
std::move(did_start_request_callback_).Run(); std::move(did_start_request_callback_).Run();
} }
......
...@@ -16,7 +16,8 @@ AuthenticatorRequestClientDelegate::AuthenticatorRequestClientDelegate() = ...@@ -16,7 +16,8 @@ AuthenticatorRequestClientDelegate::AuthenticatorRequestClientDelegate() =
AuthenticatorRequestClientDelegate::~AuthenticatorRequestClientDelegate() = AuthenticatorRequestClientDelegate::~AuthenticatorRequestClientDelegate() =
default; default;
void AuthenticatorRequestClientDelegate::DidStartRequest() {} void AuthenticatorRequestClientDelegate::DidStartRequest(
base::OnceClosure cancel_callback) {}
bool AuthenticatorRequestClientDelegate::ShouldPermitIndividualAttestation( bool AuthenticatorRequestClientDelegate::ShouldPermitIndividualAttestation(
const std::string& relying_party_id) { const std::string& relying_party_id) {
......
...@@ -33,7 +33,7 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate ...@@ -33,7 +33,7 @@ class CONTENT_EXPORT AuthenticatorRequestClientDelegate
~AuthenticatorRequestClientDelegate() override; ~AuthenticatorRequestClientDelegate() override;
// Notifies the delegate that the request is actually starting. // Notifies the delegate that the request is actually starting.
virtual void DidStartRequest(); virtual void DidStartRequest(base::OnceClosure cancel_callback);
// Returns true if the given relying party ID is permitted to receive // Returns true if the given relying party ID is permitted to receive
// individual attestation certificates. This: // individual attestation certificates. This:
......
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