Upload local auth data Code still does not reset local_auth_info_changed. For now we will update info on every refresh of access token. BUG:25934771 Change-Id: Iab639395b7fc8dbba57769a8a018180fc8f1b0e1 Reviewed-on: https://weave-review.googlesource.com/1828 Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc index b29bd52..a6d863c 100644 --- a/src/device_registration_info.cc +++ b/src/device_registration_info.cc
@@ -27,6 +27,7 @@ #include "src/http_constants.h" #include "src/json_error_codes.h" #include "src/notification/xmpp_channel.h" +#include "src/privet/auth_manager.h" #include "src/string_utils.h" #include "src/utils.h" @@ -234,6 +235,17 @@ return code >= http::kContinue && code < http::kBadRequest; } +std::unique_ptr<base::DictionaryValue> BuildDeviceLocalAuth( + const std::string& id, + const std::string& client_token, + const std::string& cert_fingerprint) { + std::unique_ptr<base::DictionaryValue> auth{new base::DictionaryValue}; + auth->SetString("localId", id); + auth->SetString("clientToken", client_token); + auth->SetString("certFingerprint", cert_fingerprint); + return auth; +} + } // anonymous namespace DeviceRegistrationInfo::DeviceRegistrationInfo( @@ -430,6 +442,9 @@ // Now that we have a new access token, retry the connection. StartNotificationChannel(); } + + SendAuthInfo(); + callback.Run(nullptr); } @@ -639,6 +654,7 @@ task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, nullptr), {}); StartNotificationChannel(); + SendAuthInfo(); // We're going to respond with our success immediately and we'll connect to // cloud shortly after. @@ -914,6 +930,48 @@ AsWeakPtr())); } +void DeviceRegistrationInfo::SendAuthInfo() { + if (!auth_manager_ || auth_info_update_inprogress_) + return; + auth_info_update_inprogress_ = true; + + std::string id = GetSettings().device_id; + std::string token = Base64Encode(auth_manager_->GetRootDeviceToken()); + std::string fingerprint = + Base64Encode(auth_manager_->GetCertificateFingerprint()); + + std::unique_ptr<base::DictionaryValue> auth = + BuildDeviceLocalAuth(id, token, fingerprint); + + // TODO(vitalybuka): Remove args from URL when server is ready. + std::string url = + GetDeviceURL("upsertLocalAuthInfo", {{"localid", id}, + {"clienttoken", token}, + {"certfingerprint", fingerprint}}); + DoCloudRequest( + HttpClient::Method::kPost, url, auth.get(), + base::Bind(&DeviceRegistrationInfo::OnSendAuthInfoDone, AsWeakPtr())); +} + +void DeviceRegistrationInfo::OnSendAuthInfoDone( + const base::DictionaryValue& body, + ErrorPtr error) { + CHECK(auth_info_update_inprogress_); + auth_info_update_inprogress_ = false; + + if (!error) { + // TODO(vitalybuka): Enable this when we start uploading real data. + // Config::Transaction change{config_.get()}; + // change.set_local_auth_info_changed(false); + // change.Commit(); + return; + } + + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(&DeviceRegistrationInfo::SendAuthInfo, AsWeakPtr()), + {}); +} + void DeviceRegistrationInfo::OnDeviceInfoRetrieved( const base::DictionaryValue& device_info, ErrorPtr error) {
diff --git a/src/device_registration_info.h b/src/device_registration_info.h index c196e0c..04fb7b6 100644 --- a/src/device_registration_info.h +++ b/src/device_registration_info.h
@@ -201,6 +201,9 @@ ErrorPtr error); void OnUpdateDeviceResourceError(ErrorPtr error); + void SendAuthInfo(); + void OnSendAuthInfoDone(const base::DictionaryValue& body, ErrorPtr error); + // Callback from GetDeviceInfo() to retrieve the device resource timestamp // and retry UpdateDeviceResource() call. void OnDeviceInfoRetrieved(const base::DictionaryValue& device_info, @@ -334,6 +337,8 @@ // is in flight to the cloud server. ResourceUpdateCallbackList queued_resource_update_callbacks_; + bool auth_info_update_inprogress_{false}; + std::unique_ptr<NotificationChannel> primary_notification_channel_; std::unique_ptr<PullChannel> pull_channel_; NotificationChannel* current_notification_channel_{nullptr};
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc index d03ae15..cc519d2 100644 --- a/src/device_registration_info_unittest.cc +++ b/src/device_registration_info_unittest.cc
@@ -16,9 +16,12 @@ #include "src/bind_lambda.h" #include "src/component_manager_impl.h" #include "src/http_constants.h" +#include "src/privet/auth_manager.h" +#include "src/test/mock_clock.h" using testing::_; using testing::AtLeast; +using testing::HasSubstr; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::Mock; @@ -49,6 +52,7 @@ "fkjh7f.apps.googleusercontent.com"; const char kClientSecret[] = "5sdGdGlfolGlrFKfdFlgP6FG"; const char kCloudId[] = "4a7ea2d1-b331-1e1f-b206-e863c7635196"; +const char kDeviceId[] = "f6885e46-b432-42d7-86a5-d759bfb61f62"; const char kClaimTicketId[] = "RTcUE"; const char kAccessToken[] = "ya29.1.AADtN_V-dLUM-sVZ0qVjG9Dxm5NgdS9J" @@ -63,6 +67,12 @@ const char kRobotAccountEmail[] = "6ed0b3f54f9bd619b942f4ad2441c252@" "clouddevices.gserviceaccount.com"; +const char kAuthInfo[] = R"({ + "certFingerprint": + "FQY6BEINDjw3FgsmYChRWgMzMhc4TC8uG0UUUFhdDz0=", + "clientToken": "UBPkqttkiWt5VWgICLP0eHuCQgECRgMaVm0+gA==", + "localId": "f6885e46-b432-42d7-86a5-d759bfb61f62" +})"; } // namespace test_data @@ -113,9 +123,11 @@ class DeviceRegistrationInfoTest : public ::testing::Test { protected: void SetUp() override { + EXPECT_CALL(clock_, Now()) + .WillRepeatedly(Return(base::Time::FromTimeT(1450000000))); dev_reg_.reset(new DeviceRegistrationInfo{&config_, &component_manager_, &task_runner_, &http_client_, - nullptr, nullptr}); + nullptr, &auth_}); ReloadDefaults(); } @@ -146,6 +158,7 @@ dict.SetString("refresh_token", test_data::kRefreshToken); dict.SetString("cloud_id", test_data::kCloudId); dict.SetString("robot_account", test_data::kRobotAccountEmail); + dict.SetString("device_id", test_data::kDeviceId); std::string json_string; base::JSONWriter::WriteWithOptions( dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string); @@ -183,6 +196,13 @@ StrictMock<MockHttpClient> http_client_; base::DictionaryValue data_; Config config_{&config_store_}; + test::MockClock clock_; + privet::AuthManager auth_{ + {68, 52, 36, 95, 74, 89, 25, 2, 31, 5, 65, 87, 64, 32, 17, 26, 8, 73, 57, + 16, 33, 82, 71, 10, 72, 62, 45, 1, 77, 97, 70, 24}, + {21, 6, 58, 4, 66, 13, 14, 60, 55, 22, 11, 38, 96, 40, 81, 90, 3, 51, 50, + 23, 56, 76, 47, 46, 27, 69, 20, 80, 88, 93, 15, 61}, + &clock_}; std::unique_ptr<DeviceRegistrationInfo> dev_reg_; ComponentManagerImpl component_manager_; }; @@ -242,6 +262,18 @@ callback.Run(ReplyWithJson(200, json), nullptr); }))); + EXPECT_CALL( + http_client_, + SendRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"), + HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _)) + .WillOnce(WithArgs<3, 4>( + Invoke([](const std::string& data, + const HttpClient::SendRequestCallback& callback) { + EXPECT_JSON_EQ(test_data::kAuthInfo, *CreateDictionaryValue(data)); + base::DictionaryValue json; + callback.Run(ReplyWithJson(200, json), nullptr); + }))); + EXPECT_TRUE(RefreshAccessToken(nullptr)); EXPECT_TRUE(HaveRegistrationCredentials()); } @@ -338,6 +370,8 @@ } TEST_F(DeviceRegistrationInfoTest, RegisterDevice) { + ReloadSettings(); + auto json_traits = CreateDictionaryValue(R"({ 'base': { 'commands': { @@ -520,6 +554,18 @@ callback.Run(ReplyWithJson(200, json), nullptr); }))); + EXPECT_CALL( + http_client_, + SendRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"), + HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _)) + .WillOnce(WithArgs<3, 4>( + Invoke([](const std::string& data, + const HttpClient::SendRequestCallback& callback) { + EXPECT_JSON_EQ(test_data::kAuthInfo, *CreateDictionaryValue(data)); + base::DictionaryValue json; + callback.Run(ReplyWithJson(200, json), nullptr); + }))); + bool done = false; dev_reg_->RegisterDevice( test_data::kClaimTicketId, base::Bind([this, &done](ErrorPtr error) {
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc index 66850cf..24c6973 100644 --- a/src/weave_unittest.cc +++ b/src/weave_unittest.cc
@@ -183,10 +183,11 @@ protected: void SetUp() override {} + template <class UrlMatcher> void ExpectRequest(HttpClient::Method method, - const std::string& url, + const UrlMatcher& url_matcher, const std::string& json_response) { - EXPECT_CALL(http_client_, SendRequest(method, url, _, _, _)) + EXPECT_CALL(http_client_, SendRequest(method, url_matcher, _, _, _)) .WillOnce(WithArgs<4>(Invoke([json_response]( const HttpClient::SendRequestCallback& callback) { std::unique_ptr<provider::test::MockHttpClientResponse> response{ @@ -400,6 +401,9 @@ "https://accounts.google.com/o/oauth2/token", kAuthTokenResponse); + ExpectRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"), + {}); + InitDnsSdPublishing(true, "DB"); bool done = false;