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

[Autofill Payments] Updating UnmaskRequest to include FIDO Assertion Info.

This CL allows for a payments request to include a FIDO assertion response instead of a CVC to unmask a credit card.

Bug: 949269
Change-Id: Icdae1023f8b9f3eac1e6e19b595990229a3f9236
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1623920Reviewed-by: default avatarJared Saul <jsaul@google.com>
Commit-Queue: Manas Verma <manasverma@google.com>
Cr-Commit-Position: refs/heads/master@{#668442}
parent 26e689c0
...@@ -48,8 +48,30 @@ void FullCardRequest::GetFullCard(const CreditCard& card, ...@@ -48,8 +48,30 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
AutofillClient::UnmaskCardReason reason, AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate, base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate) { base::WeakPtr<UIDelegate> ui_delegate) {
DCHECK(result_delegate);
DCHECK(ui_delegate); DCHECK(ui_delegate);
GetFullCard(card, reason, result_delegate, ui_delegate, base::Value());
}
void FullCardRequest::GetFullCardViaFIDO(
const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::Value fido_assertion_info) {
DCHECK(fido_assertion_info.is_dict());
GetFullCard(card, reason, result_delegate, nullptr,
std::move(fido_assertion_info));
}
void FullCardRequest::GetFullCard(const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate,
base::Value fido_assertion_info) {
// Retrieval of card information should happen via CVC auth or FIDO, but not
// both. Use |ui_delegate|'s existence as evidence of doing CVC auth and
// |fido_assertion_info| as evidence of doing FIDO auth.
DCHECK_NE(fido_assertion_info.is_dict(), !!ui_delegate);
DCHECK(result_delegate);
// Only one request can be active at a time. If the member variable // Only one request can be active at a time. If the member variable
// |result_delegate_| is already set, then immediately reject the new request // |result_delegate_| is already set, then immediately reject the new request
...@@ -60,7 +82,6 @@ void FullCardRequest::GetFullCard(const CreditCard& card, ...@@ -60,7 +82,6 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
} }
result_delegate_ = result_delegate; result_delegate_ = result_delegate;
ui_delegate_ = ui_delegate;
request_.reset(new payments::PaymentsClient::UnmaskRequestDetails); request_.reset(new payments::PaymentsClient::UnmaskRequestDetails);
request_->card = card; request_->card = card;
should_unmask_card_ = card.record_type() == CreditCard::MASKED_SERVER_CARD || should_unmask_card_ = card.record_type() == CreditCard::MASKED_SERVER_CARD ||
...@@ -72,8 +93,15 @@ void FullCardRequest::GetFullCard(const CreditCard& card, ...@@ -72,8 +93,15 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
personal_data_manager_, /*should_log_validity=*/true); personal_data_manager_, /*should_log_validity=*/true);
} }
ui_delegate_->ShowUnmaskPrompt(request_->card, reason, request_->fido_assertion_info = std::move(fido_assertion_info);
weak_ptr_factory_.GetWeakPtr()); ui_delegate_ = ui_delegate;
// If there is a UI delegate, then perform a CVC check.
// Otherwise, continue and use |fido_assertion_info| to unmask.
if (ui_delegate_) {
ui_delegate_->ShowUnmaskPrompt(request_->card, reason,
weak_ptr_factory_.GetWeakPtr());
}
if (should_unmask_card_) { if (should_unmask_card_) {
risk_data_loader_->LoadRiskData( risk_data_loader_->LoadRiskData(
...@@ -124,7 +152,8 @@ void FullCardRequest::OnUnmaskPromptClosed() { ...@@ -124,7 +152,8 @@ void FullCardRequest::OnUnmaskPromptClosed() {
void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) { void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) {
request_->risk_data = risk_data; request_->risk_data = risk_data;
if (!request_->user_response.cvc.empty()) if (!request_->user_response.cvc.empty() ||
!request_->fido_assertion_info.is_none())
SendUnmaskCardRequest(); SendUnmaskCardRequest();
} }
......
...@@ -59,7 +59,7 @@ class FullCardRequest final : public CardUnmaskDelegate { ...@@ -59,7 +59,7 @@ class FullCardRequest final : public CardUnmaskDelegate {
base::TimeTicks form_parsed_timestamp); base::TimeTicks form_parsed_timestamp);
~FullCardRequest(); ~FullCardRequest();
// Retrieves the pan and cvc for |card| and invokes // Retrieves the pan for |card| after querying the user for CVC and invokes
// Delegate::OnFullCardRequestSucceeded() or // Delegate::OnFullCardRequestSucceeded() or
// Delegate::OnFullCardRequestFailed(). Only one request should be active at a // Delegate::OnFullCardRequestFailed(). Only one request should be active at a
// time. // time.
...@@ -72,6 +72,19 @@ class FullCardRequest final : public CardUnmaskDelegate { ...@@ -72,6 +72,19 @@ class FullCardRequest final : public CardUnmaskDelegate {
base::WeakPtr<ResultDelegate> result_delegate, base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate); base::WeakPtr<UIDelegate> ui_delegate);
// Retrieves the pan for |card| through a FIDO assertion and invokes
// Delegate::OnFullCardRequestSucceeded() or
// Delegate::OnFullCardRequestFailed(). Only one request should be active at a
// time.
//
// If the card is local, has a non-empty GUID, and the user has updated its
// expiration date, then this function will write the new information to
// autofill table on disk.
void GetFullCardViaFIDO(const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::Value fido_assertion_info);
// Returns true if there's a pending request to get the full card. // Returns true if there's a pending request to get the full card.
bool IsGettingFullCard() const; bool IsGettingFullCard() const;
...@@ -84,6 +97,23 @@ class FullCardRequest final : public CardUnmaskDelegate { ...@@ -84,6 +97,23 @@ class FullCardRequest final : public CardUnmaskDelegate {
} }
private: private:
// Retrieves the pan for |card| and invokes
// Delegate::OnFullCardRequestSucceeded() or
// Delegate::OnFullCardRequestFailed(). Only one request should be active at a
// time.
//
// If |ui_delegate| is set, then the user is queried for CVC.
// Else if |fido_assertion_info| is a dictionary, FIDO verification is used.
//
// If the card is local, has a non-empty GUID, and the user has updated its
// expiration date, then this function will write the new information to
// autofill table on disk.
void GetFullCard(const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate,
base::Value fido_assertion_info);
// CardUnmaskDelegate: // CardUnmaskDelegate:
void OnUnmaskResponse(const UnmaskResponse& response) override; void OnUnmaskResponse(const UnmaskResponse& response) override;
void OnUnmaskPromptClosed() override; void OnUnmaskPromptClosed() override;
......
...@@ -137,7 +137,7 @@ MATCHER_P4(CardMatches, record_type, number, month, year, "") { ...@@ -137,7 +137,7 @@ MATCHER_P4(CardMatches, record_type, number, month, year, "") {
} }
// Verify getting the full PAN and the CVC for a masked server card. // Verify getting the full PAN and the CVC for a masked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCard) { TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaCvc) {
EXPECT_CALL(*result_delegate(), EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded( OnFullCardRequestSucceeded(
testing::Ref(*request()), testing::Ref(*request()),
...@@ -158,6 +158,21 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCard) { ...@@ -158,6 +158,21 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCard) {
card_unmask_delegate()->OnUnmaskPromptClosed(); card_unmask_delegate()->OnUnmaskPromptClosed();
} }
// Verify getting the full PAN for a masked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaFido) {
EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("")));
request()->GetFullCardViaFIDO(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
base::Value(base::Value::Type::DICTIONARY));
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
}
// Verify getting the CVC for a local card. // Verify getting the CVC for a local card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForLocalCard) { TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForLocalCard) {
EXPECT_CALL( EXPECT_CALL(
......
...@@ -371,6 +371,11 @@ class UnmaskCardRequest : public PaymentsRequest { ...@@ -371,6 +371,11 @@ class UnmaskCardRequest : public PaymentsRequest {
if (base::StringToInt(request_details_.user_response.exp_year, &value)) if (base::StringToInt(request_details_.user_response.exp_year, &value))
request_dict.SetKey("expiration_year", base::Value(value)); request_dict.SetKey("expiration_year", base::Value(value));
if (request_details_.fido_assertion_info.is_dict()) {
request_dict.SetKey("fido_assertion_info",
std::move(request_details_.fido_assertion_info));
}
std::string json_request; std::string json_request;
base::JSONWriter::Write(request_dict, &json_request); base::JSONWriter::Write(request_dict, &json_request);
std::string request_content = base::StringPrintf( std::string request_content = base::StringPrintf(
...@@ -835,7 +840,13 @@ const char PaymentsClient::kPhoneNumber[] = "phone_number"; ...@@ -835,7 +840,13 @@ const char PaymentsClient::kPhoneNumber[] = "phone_number";
PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails() {} PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails() {}
PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails( PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails(
const UnmaskRequestDetails& other) = default; const UnmaskRequestDetails& other) {
billing_customer_number = other.billing_customer_number;
card = other.card;
risk_data = other.risk_data;
user_response = other.user_response;
fido_assertion_info = other.fido_assertion_info.Clone();
}
PaymentsClient::UnmaskRequestDetails::~UnmaskRequestDetails() {} PaymentsClient::UnmaskRequestDetails::~UnmaskRequestDetails() {}
PaymentsClient::UploadRequestDetails::UploadRequestDetails() {} PaymentsClient::UploadRequestDetails::UploadRequestDetails() {}
......
...@@ -85,6 +85,7 @@ class PaymentsClient { ...@@ -85,6 +85,7 @@ class PaymentsClient {
CreditCard card; CreditCard card;
std::string risk_data; std::string risk_data;
CardUnmaskDelegate::UnmaskResponse user_response; CardUnmaskDelegate::UnmaskResponse user_response;
base::Value fido_assertion_info;
}; };
// A collection of the information required to make a credit card upload // A collection of the information required to make a credit card upload
......
...@@ -164,12 +164,17 @@ class PaymentsClientTest : public testing::Test { ...@@ -164,12 +164,17 @@ class PaymentsClientTest : public testing::Test {
// Issue an UnmaskCard request. This requires an OAuth token before starting // Issue an UnmaskCard request. This requires an OAuth token before starting
// the request. // the request.
void StartUnmasking() { void StartUnmasking(bool use_fido = false) {
PaymentsClient::UnmaskRequestDetails request_details; PaymentsClient::UnmaskRequestDetails request_details;
request_details.billing_customer_number = 111222333444; request_details.billing_customer_number = 111222333444;
request_details.card = test::GetMaskedServerCard(); request_details.card = test::GetMaskedServerCard();
request_details.user_response.cvc = base::ASCIIToUTF16("123");
request_details.risk_data = "some risk data"; request_details.risk_data = "some risk data";
if (use_fido) {
request_details.fido_assertion_info =
base::Value(base::Value::Type::DICTIONARY);
} else {
request_details.user_response.cvc = base::ASCIIToUTF16("123");
}
client_->UnmaskCard(request_details, client_->UnmaskCard(request_details,
base::BindOnce(&PaymentsClientTest::OnDidGetRealPan, base::BindOnce(&PaymentsClientTest::OnDidGetRealPan,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
...@@ -353,8 +358,16 @@ TEST_F(PaymentsClientTest, ...@@ -353,8 +358,16 @@ TEST_F(PaymentsClientTest,
std::string::npos); std::string::npos);
} }
TEST_F(PaymentsClientTest, UnmaskSuccess) { TEST_F(PaymentsClientTest, UnmaskSuccessViaCVC) {
StartUnmasking(); StartUnmasking(/*use_fido=*/false);
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
EXPECT_EQ("1234", real_pan_);
}
TEST_F(PaymentsClientTest, UnmaskSuccessViaFIDO) {
StartUnmasking(/*use_fido=*/true);
IssueOAuthToken(); IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }"); ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_); EXPECT_EQ(AutofillClient::SUCCESS, result_);
......
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