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;