|  | // Copyright 2015 The Weave Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/privet/auth_manager.h" | 
|  |  | 
|  | #include <gmock/gmock.h> | 
|  | #include <gtest/gtest.h> | 
|  | #include <weave/settings.h> | 
|  |  | 
|  | #include "src/config.h" | 
|  | #include "src/data_encoding.h" | 
|  | #include "src/privet/mock_delegates.h" | 
|  | #include "src/test/mock_black_list_manager.h" | 
|  | #include "src/test/mock_clock.h" | 
|  |  | 
|  | using testing::Return; | 
|  | using testing::SaveArg; | 
|  | using testing::_; | 
|  |  | 
|  | namespace weave { | 
|  | namespace privet { | 
|  |  | 
|  | class MockBlackListManager : public test::MockAccessBlackListManager { | 
|  | public: | 
|  | MockBlackListManager() { | 
|  | EXPECT_CALL(*this, AddEntryAddedCallback(_)) | 
|  | .WillOnce(SaveArg<0>(&changed_callback_)); | 
|  | } | 
|  |  | 
|  | base::Closure changed_callback_; | 
|  | }; | 
|  |  | 
|  | class AuthManagerTest : public testing::Test { | 
|  | public: | 
|  | void SetUp() override { | 
|  | EXPECT_GE(auth_.GetAuthSecret().size(), 32u); | 
|  | EXPECT_GE(auth_.GetAccessSecret().size(), 32u); | 
|  | EXPECT_GE(auth_.GetCertificateFingerprint().size(), 32u); | 
|  |  | 
|  | EXPECT_CALL(clock_, Now()) | 
|  | .WillRepeatedly(Return(base::Time::FromTimeT(1410000000))); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | std::vector<uint8_t> DelegateToUser(const std::vector<uint8_t>& token, | 
|  | base::TimeDelta ttl, | 
|  | const UserInfo& user_info) const { | 
|  | return auth_.DelegateToUser(token, ttl, user_info); | 
|  | } | 
|  | const std::vector<uint8_t> kSecret1{ | 
|  | 78, 40, 39, 68, 29, 19, 70, 86, 38, 61, 13, 55, 33, 32, 51, 52, | 
|  | 34, 43, 97, 48, 8,  56, 11, 99, 50, 59, 24, 26, 31, 71, 76, 28}; | 
|  | const std::vector<uint8_t> kSecret2{ | 
|  | 69, 53, 17, 37, 80, 73, 2,  5, 79, 64, 41, 57, 12, 54, 65, 63, | 
|  | 72, 74, 93, 81, 20, 95, 89, 3, 94, 92, 27, 21, 49, 90, 36, 6}; | 
|  | const std::vector<uint8_t> kFingerprint{ | 
|  | 22, 47, 23, 77, 42, 98, 96, 25,  83, 16, 9, 14, 91, 44, 15, 75, | 
|  | 60, 62, 10, 18, 82, 35, 88, 100, 30, 45, 7, 46, 67, 84, 58, 85}; | 
|  |  | 
|  | test::MockClock clock_; | 
|  | MockBlackListManager black_list_; | 
|  | AuthManager auth_{kSecret1, kFingerprint, kSecret2, &clock_, &black_list_}; | 
|  | }; | 
|  |  | 
|  | TEST_F(AuthManagerTest, RandomSecret) { | 
|  | AuthManager auth{{}, {}, {}, &clock_}; | 
|  | EXPECT_EQ(auth.GetAuthSecret().size(), 32u); | 
|  | EXPECT_EQ(auth.GetAccessSecret().size(), 32u); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, DifferentSecret) { | 
|  | AuthManager auth{kSecret2, {}, kSecret1}; | 
|  | EXPECT_EQ(auth.GetAuthSecret().size(), 32u); | 
|  | EXPECT_EQ(auth.GetAccessSecret().size(), 32u); | 
|  | EXPECT_NE(auth_.GetAccessSecret(), auth.GetAccessSecret()); | 
|  | EXPECT_NE(auth_.GetAuthSecret(), auth.GetAuthSecret()); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, Constructor) { | 
|  | EXPECT_EQ(kSecret1, auth_.GetAuthSecret()); | 
|  | EXPECT_EQ(kSecret2, auth_.GetAccessSecret()); | 
|  | EXPECT_EQ(kFingerprint, auth_.GetCertificateFingerprint()); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessToken) { | 
|  | EXPECT_EQ("WC2FRggaG52hAEIBFEYJRDIzNABCCkBGBRobnaEAUFAF46oQlMmXgnLstt7wU2w=", | 
|  | Base64Encode(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"234"}}, {}))); | 
|  | EXPECT_EQ("WC2FRggaG52hAEIBCEYJRDI1NwBCCkBGBRobnaEAUEdWRNHcu/0mA6c3e0tgDrk=", | 
|  | Base64Encode(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kManager, TestUserId{"257"}}, {}))); | 
|  | EXPECT_EQ("WC2FRggaG52hAEIBAkYJRDQ1NgBCCkBGBRobnaEAUH2ZLgUPdTtjNRa+PoDkMW4=", | 
|  | Base64Encode(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {}))); | 
|  | auto new_time = clock_.Now() + base::TimeDelta::FromDays(11); | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); | 
|  | EXPECT_EQ("WC2FRggaG6whgEIBDkYJRDM0NQBCCkBGBRobrCGAUDAFptj7bbYmbpaa6Wpb1Wo=", | 
|  | Base64Encode(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kUser, TestUserId{"345"}}, {}))); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateSameToken) { | 
|  | EXPECT_EQ(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateSameTokenWithApp) { | 
|  | EXPECT_EQ(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}}, | 
|  | {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}}, | 
|  | {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateSameTokenWithDifferentType) { | 
|  | EXPECT_NE(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}}, | 
|  | {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kPairing, {1, 2, 3}, {4, 5, 6}}}, | 
|  | {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateSameTokenWithDifferentApp) { | 
|  | EXPECT_NE(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}}, | 
|  | {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, | 
|  | {AuthType::kLocal, {1, 2, 3}, {4, 5, 7}}}, | 
|  | {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateTokenDifferentScope) { | 
|  | EXPECT_NE(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"456"}}, {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateTokenDifferentUser) { | 
|  | EXPECT_NE(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {}), | 
|  | auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"789"}}, {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateTokenDifferentTime) { | 
|  | auto token = auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"567"}}, {}); | 
|  | EXPECT_CALL(clock_, Now()) | 
|  | .WillRepeatedly(Return(base::Time::FromTimeT(1400000000))); | 
|  | EXPECT_NE(token, auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kOwner, TestUserId{"567"}}, {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateTokenDifferentInstance) { | 
|  | EXPECT_NE(auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}), | 
|  | AuthManager({}, nullptr, {}) | 
|  | .CreateAccessToken( | 
|  | UserInfo{AuthScope::kUser, TestUserId{"123"}}, {})); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, ParseAccessToken) { | 
|  | // Multiple attempts with random secrets. | 
|  | const auto kStartTime = base::Time::FromTimeT(1412121212); | 
|  | for (size_t i = 0; i < 1000; ++i) { | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(kStartTime)); | 
|  |  | 
|  | AuthManager auth{{}, {}, {}, &clock_}; | 
|  |  | 
|  | auto token = | 
|  | auth.CreateAccessToken(UserInfo{AuthScope::kUser, TestUserId{"5"}}, | 
|  | base::TimeDelta::FromSeconds(i)); | 
|  | UserInfo user_info; | 
|  | EXPECT_FALSE(auth_.ParseAccessToken(token, &user_info, nullptr)); | 
|  | EXPECT_TRUE(auth.ParseAccessToken(token, &user_info, nullptr)); | 
|  | EXPECT_EQ(AuthScope::kUser, user_info.scope()); | 
|  | EXPECT_EQ(TestUserId{"5"}, user_info.id()); | 
|  |  | 
|  | EXPECT_CALL(clock_, Now()) | 
|  | .WillRepeatedly(Return(kStartTime + base::TimeDelta::FromSeconds(i))); | 
|  | EXPECT_TRUE(auth.ParseAccessToken(token, &user_info, nullptr)); | 
|  |  | 
|  | auto extended = | 
|  | DelegateToUser(token, base::TimeDelta::FromSeconds(1000), | 
|  | UserInfo{AuthScope::kUser, TestUserId{"234"}}); | 
|  | EXPECT_FALSE(auth.ParseAccessToken(extended, &user_info, nullptr)); | 
|  |  | 
|  | EXPECT_CALL(clock_, Now()) | 
|  | .WillRepeatedly( | 
|  | Return(kStartTime + base::TimeDelta::FromSeconds(i + 1))); | 
|  | EXPECT_FALSE(auth.ParseAccessToken(token, &user_info, nullptr)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, AccessTokenAfterReset) { | 
|  | UserInfo user_info; | 
|  | auto token1 = auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {}); | 
|  | EXPECT_TRUE(auth_.ParseAccessToken(token1, &user_info, nullptr)); | 
|  |  | 
|  | black_list_.changed_callback_.Run(); | 
|  |  | 
|  | auto token2 = auth_.CreateAccessToken( | 
|  | UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {}); | 
|  |  | 
|  | EXPECT_NE(token1, token2); | 
|  | EXPECT_FALSE(auth_.ParseAccessToken(token1, &user_info, nullptr)); | 
|  | EXPECT_TRUE(auth_.ParseAccessToken(token2, &user_info, nullptr)); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, GetRootClientAuthToken) { | 
|  | EXPECT_EQ("WCCDQxkgAUYIGhudoQBCDABQX3fPR5zsPnrs9aOSvS7/eQ==", | 
|  | Base64Encode( | 
|  | auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient))); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentOwner) { | 
|  | EXPECT_EQ( | 
|  | "WCCDQxkgAUYIGhudoQBCDAFQRrCQfq+g7drVwCbxpug4Ig==", | 
|  | Base64Encode(auth_.GetRootClientAuthToken(RootClientTokenOwner::kCloud))); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentTime) { | 
|  | auto new_time = clock_.Now() + base::TimeDelta::FromDays(15); | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); | 
|  | EXPECT_EQ("WCCDQxkgAUYIGhuxZ4BCDABQ9omJ3ooMrcYUZ1DiVqNKAA==", | 
|  | Base64Encode( | 
|  | auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient))); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentSecret) { | 
|  | AuthManager auth{kSecret2, {}, kSecret1, &clock_}; | 
|  | EXPECT_EQ( | 
|  | "WCCDQxkgAUYIGhudoQBCDABQWl2CB8CiP1BiV0ksnnkQQQ==", | 
|  | Base64Encode(auth.GetRootClientAuthToken(RootClientTokenOwner::kClient))); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, IsValidAuthToken) { | 
|  | EXPECT_TRUE(auth_.IsValidAuthToken( | 
|  | auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient), nullptr)); | 
|  | // Multiple attempts with random secrets. | 
|  | for (size_t i = 0; i < 1000; ++i) { | 
|  | AuthManager auth{{}, {}, {}, &clock_}; | 
|  |  | 
|  | auto token = auth.GetRootClientAuthToken(RootClientTokenOwner::kClient); | 
|  | EXPECT_FALSE(auth_.IsValidAuthToken(token, nullptr)); | 
|  | EXPECT_TRUE(auth.IsValidAuthToken(token, nullptr)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateSessionId) { | 
|  | EXPECT_EQ("463315200:1", auth_.CreateSessionId()); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, IsValidSessionId) { | 
|  | EXPECT_TRUE(auth_.IsValidSessionId("463315200:1")); | 
|  | EXPECT_TRUE(auth_.IsValidSessionId("463315200:2")); | 
|  | EXPECT_TRUE(auth_.IsValidSessionId("463315150")); | 
|  |  | 
|  | // Future | 
|  | EXPECT_FALSE(auth_.IsValidSessionId("463315230:1")); | 
|  |  | 
|  | // Expired | 
|  | EXPECT_FALSE(auth_.IsValidSessionId("463315100:1")); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessTokenFromAuth) { | 
|  | std::vector<uint8_t> access_token; | 
|  | AuthScope scope; | 
|  | base::TimeDelta ttl; | 
|  | auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kCloud); | 
|  | auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000), | 
|  | UserInfo{AuthScope::kUser, TestUserId{"234"}}); | 
|  | EXPECT_EQ( | 
|  | "WEWIQxkgAUYIGhudoQBCDAFGCBobnaEARgUaG52k6EIBDkUJQzIzNE0RSzQ2MzMxNTIwMDox" | 
|  | "UIujtnCZlcRvJPOra5BwM6E=", | 
|  | Base64Encode(extended)); | 
|  | EXPECT_TRUE( | 
|  | auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1), | 
|  | &access_token, &scope, &ttl, nullptr)); | 
|  | UserInfo user_info; | 
|  | EXPECT_TRUE(auth_.ParseAccessToken(access_token, &user_info, nullptr)); | 
|  | EXPECT_EQ(scope, user_info.scope()); | 
|  | EXPECT_EQ(AuthScope::kUser, user_info.scope()); | 
|  |  | 
|  | EXPECT_EQ(TestUserId{"234"}, user_info.id()); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessTokenFromAuthNotMinted) { | 
|  | std::vector<uint8_t> access_token; | 
|  | auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient); | 
|  | ErrorPtr error; | 
|  | EXPECT_FALSE(auth_.CreateAccessTokenFromAuth( | 
|  | root, base::TimeDelta::FromDays(1), nullptr, nullptr, nullptr, &error)); | 
|  | EXPECT_TRUE(error->HasError("invalidAuthCode")); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessTokenFromAuthValidateAfterSomeTime) { | 
|  | auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient); | 
|  | auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000), | 
|  | UserInfo{AuthScope::kUser, TestUserId{"234"}}); | 
|  |  | 
|  | // new_time < session_id_expiration < token_expiration. | 
|  | auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(15); | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); | 
|  | EXPECT_TRUE( | 
|  | auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1), | 
|  | nullptr, nullptr, nullptr, nullptr)); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessTokenFromAuthExpired) { | 
|  | auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient); | 
|  | auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(10), | 
|  | UserInfo{AuthScope::kUser, TestUserId{"234"}}); | 
|  | ErrorPtr error; | 
|  |  | 
|  | // token_expiration < new_time < session_id_expiration. | 
|  | auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(15); | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); | 
|  | EXPECT_FALSE( | 
|  | auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1), | 
|  | nullptr, nullptr, nullptr, &error)); | 
|  | EXPECT_TRUE(error->HasError("invalidAuthCode")); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerTest, CreateAccessTokenFromAuthExpiredSessionid) { | 
|  | auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient); | 
|  | auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000), | 
|  | UserInfo{AuthScope::kUser, TestUserId{"234"}}); | 
|  | ErrorPtr error; | 
|  |  | 
|  | // session_id_expiration < new_time < token_expiration. | 
|  | auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(200); | 
|  | EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); | 
|  | EXPECT_FALSE( | 
|  | auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1), | 
|  | nullptr, nullptr, nullptr, &error)); | 
|  | EXPECT_TRUE(error->HasError("invalidAuthCode")); | 
|  | } | 
|  |  | 
|  | class AuthManagerClaimTest : public testing::Test { | 
|  | public: | 
|  | void SetUp() override { EXPECT_EQ(auth_.GetAuthSecret().size(), 32u); } | 
|  |  | 
|  | bool TestClaim(RootClientTokenOwner owner, RootClientTokenOwner claimer) { | 
|  | Config::Transaction change{&config_}; | 
|  | change.set_root_client_token_owner(owner); | 
|  | change.Commit(); | 
|  | return !auth_.ClaimRootClientAuthToken(claimer, nullptr).empty(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | Config config_{nullptr}; | 
|  | AuthManager auth_{&config_, nullptr, {}}; | 
|  | }; | 
|  |  | 
|  | TEST_F(AuthManagerClaimTest, WithPreviosOwner) { | 
|  | EXPECT_DEATH( | 
|  | TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kNone), ""); | 
|  | EXPECT_DEATH( | 
|  | TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kNone), | 
|  | ""); | 
|  | EXPECT_DEATH( | 
|  | TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kNone), ""); | 
|  | EXPECT_TRUE( | 
|  | TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kClient)); | 
|  | EXPECT_FALSE( | 
|  | TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kClient)); | 
|  | EXPECT_FALSE( | 
|  | TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kClient)); | 
|  | EXPECT_TRUE( | 
|  | TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kCloud)); | 
|  | EXPECT_TRUE( | 
|  | TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kCloud)); | 
|  | EXPECT_TRUE( | 
|  | TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kCloud)); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerClaimTest, NormalClaim) { | 
|  | auto token = | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | EXPECT_FALSE(auth_.IsValidAuthToken(token, nullptr)); | 
|  | EXPECT_EQ(RootClientTokenOwner::kNone, | 
|  | config_.GetSettings().root_client_token_owner); | 
|  |  | 
|  | EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr)); | 
|  | EXPECT_TRUE(auth_.IsValidAuthToken(token, nullptr)); | 
|  | EXPECT_EQ(RootClientTokenOwner::kCloud, | 
|  | config_.GetSettings().root_client_token_owner); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerClaimTest, DoubleConfirm) { | 
|  | auto token = | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr)); | 
|  | EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr)); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerClaimTest, DoubleClaim) { | 
|  | auto token1 = | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | auto token2 = | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | EXPECT_TRUE(auth_.ConfirmClientAuthToken(token1, nullptr)); | 
|  | EXPECT_FALSE(auth_.ConfirmClientAuthToken(token2, nullptr)); | 
|  | } | 
|  |  | 
|  | TEST_F(AuthManagerClaimTest, TokenOverflow) { | 
|  | auto token = | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | for (size_t i = 0; i < 100; ++i) | 
|  | auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); | 
|  | EXPECT_FALSE(auth_.ConfirmClientAuthToken(token, nullptr)); | 
|  | } | 
|  |  | 
|  | }  // namespace privet | 
|  | }  // namespace weave |