Provide RootClientTokenOwner into ClaimRootClientAuthToken

ClaimRootClientAuthToken will check if token is already claimed and
block claim if needed.

BUG=25766815

Change-Id: I8d12578c99307830afccd280c322d2240234e435
Reviewed-on: https://weave-review.googlesource.com/1934
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index ac4ad4e..f52c292 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -936,7 +936,8 @@
   auth_info_update_inprogress_ = true;
 
   std::string id = GetSettings().device_id;
-  std::vector<uint8_t> token = auth_manager_->ClaimRootClientAuthToken();
+  std::vector<uint8_t> token =
+      auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   std::string token_base64 = Base64Encode(token);
   std::string fingerprint =
       Base64Encode(auth_manager_->GetCertificateFingerprint());
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index 3a2f5e0..fa1d685 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -85,26 +85,41 @@
 AuthManager::AuthManager(Config* config,
                          const std::vector<uint8_t>& certificate_fingerprint)
     : config_{config}, certificate_fingerprint_{certificate_fingerprint} {
-  SetSecret(config_ ? config_->GetSettings().secret : std::vector<uint8_t>{});
+  if (config_) {
+    SetSecret(config_->GetSettings().secret,
+              config_->GetSettings().root_client_token_owner);
+  } else {
+    SetSecret({}, RootClientTokenOwner::kNone);
+  }
 }
 
 AuthManager::AuthManager(const std::vector<uint8_t>& secret,
                          const std::vector<uint8_t>& certificate_fingerprint,
                          base::Clock* clock)
     : AuthManager(nullptr, certificate_fingerprint) {
-  SetSecret(secret);
+  SetSecret(secret, RootClientTokenOwner::kNone);
   if (clock)
     clock_ = clock;
 }
 
-void AuthManager::SetSecret(const std::vector<uint8_t>& secret) {
-  secret_ = secret.size() == kSha256OutputSize ? secret : CreateSecret();
-  if (config_ && config_->GetSettings().secret != secret_) {
-    Config::Transaction change{config_};
-    change.set_secret(secret);
-    change.set_root_client_token_owner(RootClientTokenOwner::kNone);
-    change.Commit();
+void AuthManager::SetSecret(const std::vector<uint8_t>& secret,
+                            RootClientTokenOwner owner) {
+  secret_ = secret;
+
+  if (secret.size() != kSha256OutputSize) {
+    secret_ = CreateSecret();
+    owner = RootClientTokenOwner::kNone;
   }
+
+  if (!config_ || (config_->GetSettings().secret == secret_ &&
+                   config_->GetSettings().root_client_token_owner == owner)) {
+    return;
+  }
+
+  Config::Transaction change{config_};
+  change.set_secret(secret);
+  change.set_root_client_token_owner(owner);
+  change.Commit();
 }
 
 AuthManager::~AuthManager() {}
@@ -130,12 +145,13 @@
   return SplitTokenData(std::string(data.begin(), data.end()), time);
 }
 
-std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken() {
-  pending_claims_.push_back(
-      std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}});
+std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken(
+    RootClientTokenOwner owner) {
+  pending_claims_.push_back(std::make_pair(
+      std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}, owner));
   if (pending_claims_.size() > kMaxPendingClaims)
     pending_claims_.pop_front();
-  return pending_claims_.back()->GetRootClientAuthToken();
+  return pending_claims_.back().first->GetRootClientAuthToken();
 }
 
 bool AuthManager::ConfirmAuthToken(const std::vector<uint8_t>& token) {
@@ -143,14 +159,15 @@
   if (pending_claims_.empty() && IsValidAuthToken(token))
     return true;
 
-  auto claim = std::find_if(pending_claims_.begin(), pending_claims_.end(),
-                            [&token](const std::unique_ptr<AuthManager>& auth) {
-                              return auth->IsValidAuthToken(token);
-                            });
+  auto claim =
+      std::find_if(pending_claims_.begin(), pending_claims_.end(),
+                   [&token](const decltype(pending_claims_)::value_type& auth) {
+                     return auth.first->IsValidAuthToken(token);
+                   });
   if (claim == pending_claims_.end())
     return false;
 
-  secret_ = (*claim)->GetSecret();
+  SetSecret(claim->first->GetSecret(), claim->second);
   pending_claims_.clear();
   return true;
 }
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h
index dd4ad3d..62a1606 100644
--- a/src/privet/auth_manager.h
+++ b/src/privet/auth_manager.h
@@ -18,6 +18,7 @@
 namespace weave {
 
 class Config;
+enum class RootClientTokenOwner;
 
 namespace privet {
 
@@ -43,14 +44,15 @@
 
   base::Time Now() const;
 
-  std::vector<uint8_t> ClaimRootClientAuthToken();
+  std::vector<uint8_t> ClaimRootClientAuthToken(RootClientTokenOwner owner);
   bool ConfirmAuthToken(const std::vector<uint8_t>& token);
 
   std::vector<uint8_t> GetRootClientAuthToken() const;
   bool IsValidAuthToken(const std::vector<uint8_t>& token) const;
 
  private:
-  void SetSecret(const std::vector<uint8_t>& secret);
+  void SetSecret(const std::vector<uint8_t>& secret,
+                 RootClientTokenOwner owner);
 
   Config* config_{nullptr};
   base::DefaultClock default_clock_;
@@ -59,7 +61,8 @@
   std::vector<uint8_t> secret_;
   std::vector<uint8_t> certificate_fingerprint_;
 
-  std::deque<std::unique_ptr<AuthManager>> pending_claims_;
+  std::deque<std::pair<std::unique_ptr<AuthManager>, RootClientTokenOwner>>
+      pending_claims_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthManager);
 };
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc
index 4bef217..4dd753b 100644
--- a/src/privet/auth_manager_unittest.cc
+++ b/src/privet/auth_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include <gtest/gtest.h>
 #include <weave/settings.h>
 
+#include "src/config.h"
 #include "src/data_encoding.h"
 #include "src/test/mock_clock.h"
 
@@ -147,7 +148,7 @@
 }
 
 TEST_F(AuthManagerTest, ClaimRootClientAuthToken) {
-  auto token = auth_.ClaimRootClientAuthToken();
+  auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   EXPECT_FALSE(auth_.IsValidAuthToken(token));
 
   EXPECT_TRUE(auth_.ConfirmAuthToken(token));
@@ -155,22 +156,22 @@
 }
 
 TEST_F(AuthManagerTest, ClaimRootClientAuthTokenDoubleConfirm) {
-  auto token = auth_.ClaimRootClientAuthToken();
+  auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   EXPECT_TRUE(auth_.ConfirmAuthToken(token));
   EXPECT_TRUE(auth_.ConfirmAuthToken(token));
 }
 
 TEST_F(AuthManagerTest, DoubleClaimRootClientAuthToken) {
-  auto token1 = auth_.ClaimRootClientAuthToken();
-  auto token2 = auth_.ClaimRootClientAuthToken();
+  auto token1 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
+  auto token2 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   EXPECT_TRUE(auth_.ConfirmAuthToken(token1));
   EXPECT_FALSE(auth_.ConfirmAuthToken(token2));
 }
 
 TEST_F(AuthManagerTest, ClaimRootClientAuthTokenOverflow) {
-  auto token = auth_.ClaimRootClientAuthToken();
+  auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   for (size_t i = 0; i < 100; ++i)
-    auth_.ClaimRootClientAuthToken();
+    auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
   EXPECT_FALSE(auth_.ConfirmAuthToken(token));
 }
 
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc
index 34c65f0..cb0d73d 100644
--- a/src/privet/security_manager.cc
+++ b/src/privet/security_manager.cc
@@ -18,6 +18,7 @@
 #include <base/time/time.h>
 #include <weave/provider/task_runner.h>
 
+#include "src/config.h"
 #include "src/data_encoding.h"
 #include "src/privet/auth_manager.h"
 #include "src/privet/constants.h"
@@ -136,7 +137,8 @@
 }
 
 std::string SecurityManager::ClaimRootClientAuthToken() {
-  return Base64Encode(auth_manager_->ClaimRootClientAuthToken());
+  return Base64Encode(
+      auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kClient));
 }
 
 bool SecurityManager::ConfirmAuthToken(const std::string& token) {