Commit 35029527 authored by Manas Verma's avatar Manas Verma Committed by Commit Bot

[Autofill Auth] Invoking WebAuthn registration prompt after CVC unmask.

If the user chooses to opt-in for FIDO authentication for card unmasking, and
Payments servers respond with PublicKeyCredentialCreationOptions, then invoke
WebAuthn registration prompt.

Bug: 949269
Change-Id: I36f24de438e19118389253ca526e587494e4c448
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1731142
Commit-Queue: Manas Verma <manasverma@google.com>
Reviewed-by: default avatarJared Saul <jsaul@google.com>
Cr-Commit-Position: refs/heads/master@{#686240}
parent e85d5812
...@@ -301,8 +301,13 @@ void CreditCardAccessManager::OnCVCAuthenticationComplete( ...@@ -301,8 +301,13 @@ void CreditCardAccessManager::OnCVCAuthenticationComplete(
is_authentication_in_progress_ = false; is_authentication_in_progress_ = false;
accessor_->OnCreditCardFetched(did_succeed, card, cvc); accessor_->OnCreditCardFetched(did_succeed, card, cvc);
// TODO(crbug/949269): Call CreditCardFIDOAuthenticator::Register() with given #if !defined(OS_IOS)
// |creation_options|. // Now that unmask flow is complete, if GetRealPan includes
// |creation_options|, completely hand over registration flow to
// CreditCardFIDOAuthenticator.
if (did_succeed && creation_options.is_dict())
GetOrCreateFIDOAuthenticator()->Register(std::move(creation_options));
#endif
} }
#if !defined(OS_IOS) #if !defined(OS_IOS)
......
...@@ -81,6 +81,8 @@ const char kTestGUID[] = "00000000-0000-0000-0000-000000000001"; ...@@ -81,6 +81,8 @@ const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
const char kTestNumber[] = "4234567890123456"; // Visa const char kTestNumber[] = "4234567890123456"; // Visa
#if !defined(OS_IOS) #if !defined(OS_IOS)
// Base64 encoding of "This is a test challenge".
constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
// Base64 encoding of "This is a test Credential ID". // Base64 encoding of "This is a test Credential ID".
const char kCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4="; const char kCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4=";
const char kGooglePaymentsRpid[] = "google.com"; const char kGooglePaymentsRpid[] = "google.com";
...@@ -216,7 +218,8 @@ class CreditCardAccessManagerTest : public testing::Test { ...@@ -216,7 +218,8 @@ class CreditCardAccessManagerTest : public testing::Test {
// Returns true if full card request was sent from CVC auth. // Returns true if full card request was sent from CVC auth.
bool GetRealPanForCVCAuth(AutofillClient::PaymentsRpcResult result, bool GetRealPanForCVCAuth(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) { const std::string& real_pan,
bool fido_opt_in = false) {
payments::FullCardRequest* full_card_request = payments::FullCardRequest* full_card_request =
GetCVCAuthenticator()->full_card_request_.get(); GetCVCAuthenticator()->full_card_request_.get();
...@@ -224,12 +227,29 @@ class CreditCardAccessManagerTest : public testing::Test { ...@@ -224,12 +227,29 @@ class CreditCardAccessManagerTest : public testing::Test {
return false; return false;
payments::PaymentsClient::UnmaskResponseDetails response; payments::PaymentsClient::UnmaskResponseDetails response;
#if !defined(OS_IOS)
if (fido_opt_in) {
response.fido_creation_options =
base::Value(base::Value::Type::DICTIONARY);
response.fido_creation_options.SetKey("relying_party_id",
base::Value(kGooglePaymentsRpid));
response.fido_creation_options.SetKey("challenge",
base::Value(kTestChallenge));
}
#endif
full_card_request->OnDidGetRealPan(result, full_card_request->OnDidGetRealPan(result,
response.with_real_pan(real_pan)); response.with_real_pan(real_pan));
return true; return true;
} }
#if !defined(OS_IOS) #if !defined(OS_IOS)
void SetUserOptedIn(bool user_is_opted_in) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillCreditCardAuthentication);
::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
user_is_opted_in);
}
// Returns true if full card request was sent from FIDO auth. // Returns true if full card request was sent from FIDO auth.
bool GetRealPanForFIDOAuth(AutofillClient::PaymentsRpcResult result, bool GetRealPanForFIDOAuth(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) { const std::string& real_pan) {
...@@ -245,6 +265,14 @@ class CreditCardAccessManagerTest : public testing::Test { ...@@ -245,6 +265,14 @@ class CreditCardAccessManagerTest : public testing::Test {
return true; return true;
} }
// Mocks an OptChange response from Payments Client.
void OptChange(AutofillClient::PaymentsRpcResult result,
bool user_is_opted_in,
base::Value creation_options = base::Value()) {
GetFIDOAuthenticator()->OnDidGetOptChangeResult(
result, user_is_opted_in, std::move(creation_options));
}
TestCreditCardFIDOAuthenticator* GetFIDOAuthenticator() { TestCreditCardFIDOAuthenticator* GetFIDOAuthenticator() {
return static_cast<TestCreditCardFIDOAuthenticator*>( return static_cast<TestCreditCardFIDOAuthenticator*>(
credit_card_access_manager_->GetOrCreateFIDOAuthenticator()); credit_card_access_manager_->GetOrCreateFIDOAuthenticator());
...@@ -435,7 +463,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) { ...@@ -435,7 +463,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
CreateServerCard(kTestGUID, kTestNumber); CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true); GetFIDOAuthenticator()->SetUserVerifiable(true);
GetFIDOAuthenticator()->SetUserOptIn(true); SetUserOptedIn(true);
payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId, payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
kGooglePaymentsRpid); kGooglePaymentsRpid);
...@@ -461,7 +489,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) { ...@@ -461,7 +489,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber); CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true); GetFIDOAuthenticator()->SetUserVerifiable(true);
GetFIDOAuthenticator()->SetUserOptIn(true); SetUserOptedIn(true);
payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId, payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
kGooglePaymentsRpid); kGooglePaymentsRpid);
...@@ -490,7 +518,7 @@ TEST_F(CreditCardAccessManagerTest, ...@@ -490,7 +518,7 @@ TEST_F(CreditCardAccessManagerTest,
CreateServerCard(kTestGUID, kTestNumber); CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true); GetFIDOAuthenticator()->SetUserVerifiable(true);
GetFIDOAuthenticator()->SetUserOptIn(true); SetUserOptedIn(true);
// Don't set Credential ID. // Don't set Credential ID.
payments_client_->AddFidoEligibleCard(card->server_id(), /*credential_id=*/"", payments_client_->AddFidoEligibleCard(card->server_id(), /*credential_id=*/"",
kGooglePaymentsRpid); kGooglePaymentsRpid);
...@@ -517,7 +545,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) { ...@@ -517,7 +545,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber); CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true); GetFIDOAuthenticator()->SetUserVerifiable(true);
GetFIDOAuthenticator()->SetUserOptIn(true); SetUserOptedIn(true);
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr()); credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
InvokeUnmaskDetailsTimeout(); InvokeUnmaskDetailsTimeout();
...@@ -527,6 +555,75 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) { ...@@ -527,6 +555,75 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
EXPECT_TRUE(accessor_->did_succeed()); EXPECT_TRUE(accessor_->did_succeed());
EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number()); EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
} }
// Ensures that the WebAuthn enrollment prompt is invoked after user opts in.
TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentSuccess) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetUserOptedIn(false);
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
/*fido_opt_in=*/true));
WaitForCallbacks();
// Mock user response and OptChange payments call.
TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
/*did_succeed=*/true);
OptChange(AutofillClient::SUCCESS, true);
EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
EXPECT_EQ(kTestChallenge,
BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
}
// Ensures that the failed user verification disallows enrollment.
TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentUserVerificationFailure) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetUserOptedIn(false);
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
/*fido_opt_in=*/true));
// Mock user response.
TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
/*did_succeed=*/false);
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
}
// Ensures that enrollment does not happen if the server returns a failure.
TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentServerFailure) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
SetUserOptedIn(false);
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
/*fido_opt_in=*/true));
// Mock user response and OptChange payments call.
TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
/*did_succeed=*/true);
OptChange(AutofillClient::PERMANENT_FAILURE, false);
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
}
#endif #endif
// Ensures that |is_authentication_in_progress_| is set correctly. // Ensures that |is_authentication_in_progress_| is set correctly.
......
...@@ -90,8 +90,4 @@ void TestCreditCardFIDOAuthenticator::IsUserVerifiable( ...@@ -90,8 +90,4 @@ void TestCreditCardFIDOAuthenticator::IsUserVerifiable(
return std::move(callback).Run(is_user_verifiable_); return std::move(callback).Run(is_user_verifiable_);
} }
bool TestCreditCardFIDOAuthenticator::IsUserOptedIn() {
return is_user_opted_in_;
}
} // namespace autofill } // namespace autofill
...@@ -49,13 +49,8 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator { ...@@ -49,13 +49,8 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator {
is_user_verifiable_ = is_user_verifiable; is_user_verifiable_ = is_user_verifiable;
} }
void SetUserOptIn(bool is_user_opted_in) {
is_user_opted_in_ = is_user_opted_in;
}
// CreditCardFIDOAuthenticator: // CreditCardFIDOAuthenticator:
void IsUserVerifiable(base::OnceCallback<void(bool)> callback) override; void IsUserVerifiable(base::OnceCallback<void(bool)> callback) override;
bool IsUserOptedIn() override;
private: private:
friend class AutofillManagerTest; friend class AutofillManagerTest;
...@@ -64,7 +59,6 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator { ...@@ -64,7 +59,6 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator {
PublicKeyCredentialRequestOptionsPtr request_options_; PublicKeyCredentialRequestOptionsPtr request_options_;
PublicKeyCredentialCreationOptionsPtr creation_options_; PublicKeyCredentialCreationOptionsPtr creation_options_;
bool is_user_verifiable_ = false; bool is_user_verifiable_ = false;
bool is_user_opted_in_ = false;
DISALLOW_COPY_AND_ASSIGN(TestCreditCardFIDOAuthenticator); DISALLOW_COPY_AND_ASSIGN(TestCreditCardFIDOAuthenticator);
}; };
......
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