1// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/privet/auth_manager.h"
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9#include <weave/settings.h>
10
11#include "src/config.h"
12#include "src/data_encoding.h"
13#include "src/privet/mock_delegates.h"
14#include "src/test/mock_clock.h"
15
16using testing::Return;
17
18namespace weave {
19namespace privet {
20
21class AuthManagerTest : public testing::Test {
22 public:
23  void SetUp() override {
24    EXPECT_GE(auth_.GetAuthSecret().size(), 32u);
25    EXPECT_GE(auth_.GetAccessSecret().size(), 32u);
26    EXPECT_GE(auth_.GetCertificateFingerprint().size(), 32u);
27
28    EXPECT_CALL(clock_, Now())
29        .WillRepeatedly(Return(base::Time::FromTimeT(1410000000)));
30  }
31
32 protected:
33  std::vector<uint8_t> DelegateToUser(const std::vector<uint8_t>& token,
34                                      base::TimeDelta ttl,
35                                      const UserInfo& user_info) const {
36    return auth_.DelegateToUser(token, ttl, user_info);
37  }
38  const std::vector<uint8_t> kSecret1{
39      78, 40, 39, 68, 29, 19, 70, 86, 38, 61, 13, 55, 33, 32, 51, 52,
40      34, 43, 97, 48, 8,  56, 11, 99, 50, 59, 24, 26, 31, 71, 76, 28};
41  const std::vector<uint8_t> kSecret2{
42      69, 53, 17, 37, 80, 73, 2,  5, 79, 64, 41, 57, 12, 54, 65, 63,
43      72, 74, 93, 81, 20, 95, 89, 3, 94, 92, 27, 21, 49, 90, 36, 6};
44  const std::vector<uint8_t> kFingerprint{
45      22, 47, 23, 77, 42, 98, 96, 25,  83, 16, 9, 14, 91, 44, 15, 75,
46      60, 62, 10, 18, 82, 35, 88, 100, 30, 45, 7, 46, 67, 84, 58, 85};
47
48  test::MockClock clock_;
49  AuthManager auth_{kSecret1, kFingerprint, kSecret2, &clock_};
50};
51
52TEST_F(AuthManagerTest, RandomSecret) {
53  AuthManager auth{{}, {}, {}, &clock_};
54  EXPECT_EQ(auth.GetAuthSecret().size(), 32u);
55  EXPECT_EQ(auth.GetAccessSecret().size(), 32u);
56}
57
58TEST_F(AuthManagerTest, DifferentSecret) {
59  AuthManager auth{kSecret2, {}, kSecret1};
60  EXPECT_EQ(auth.GetAuthSecret().size(), 32u);
61  EXPECT_EQ(auth.GetAccessSecret().size(), 32u);
62  EXPECT_NE(auth_.GetAccessSecret(), auth.GetAccessSecret());
63  EXPECT_NE(auth_.GetAuthSecret(), auth.GetAuthSecret());
64}
65
66TEST_F(AuthManagerTest, Constructor) {
67  EXPECT_EQ(kSecret1, auth_.GetAuthSecret());
68  EXPECT_EQ(kSecret2, auth_.GetAccessSecret());
69  EXPECT_EQ(kFingerprint, auth_.GetCertificateFingerprint());
70}
71
72TEST_F(AuthManagerTest, CreateAccessToken) {
73  EXPECT_EQ("WC2FRggaG52hAEIBFEYJRDIzNABCCkBGBRobnaEAUFAF46oQlMmXgnLstt7wU2w=",
74            Base64Encode(auth_.CreateAccessToken(
75                UserInfo{AuthScope::kViewer, TestUserId{"234"}}, {})));
76  EXPECT_EQ("WC2FRggaG52hAEIBCEYJRDI1NwBCCkBGBRobnaEAUEdWRNHcu/0mA6c3e0tgDrk=",
77            Base64Encode(auth_.CreateAccessToken(
78                UserInfo{AuthScope::kManager, TestUserId{"257"}}, {})));
79  EXPECT_EQ("WC2FRggaG52hAEIBAkYJRDQ1NgBCCkBGBRobnaEAUH2ZLgUPdTtjNRa+PoDkMW4=",
80            Base64Encode(auth_.CreateAccessToken(
81                UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {})));
82  auto new_time = clock_.Now() + base::TimeDelta::FromDays(11);
83  EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
84  EXPECT_EQ("WC2FRggaG6whgEIBDkYJRDM0NQBCCkBGBRobrCGAUDAFptj7bbYmbpaa6Wpb1Wo=",
85            Base64Encode(auth_.CreateAccessToken(
86                UserInfo{AuthScope::kUser, TestUserId{"345"}}, {})));
87}
88
89TEST_F(AuthManagerTest, CreateSameToken) {
90  EXPECT_EQ(auth_.CreateAccessToken(
91                UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {}),
92            auth_.CreateAccessToken(
93                UserInfo{AuthScope::kViewer, TestUserId{"555"}}, {}));
94}
95
96TEST_F(AuthManagerTest, CreateSameTokenWithApp) {
97  EXPECT_EQ(auth_.CreateAccessToken(
98                UserInfo{AuthScope::kViewer,
99                         {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}},
100                {}),
101            auth_.CreateAccessToken(
102                UserInfo{AuthScope::kViewer,
103                         {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}},
104                {}));
105}
106
107TEST_F(AuthManagerTest, CreateSameTokenWithDifferentType) {
108  EXPECT_NE(auth_.CreateAccessToken(
109                UserInfo{AuthScope::kViewer,
110                         {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}},
111                {}),
112            auth_.CreateAccessToken(
113                UserInfo{AuthScope::kViewer,
114                         {AuthType::kPairing, {1, 2, 3}, {4, 5, 6}}},
115                {}));
116}
117
118TEST_F(AuthManagerTest, CreateSameTokenWithDifferentApp) {
119  EXPECT_NE(auth_.CreateAccessToken(
120                UserInfo{AuthScope::kViewer,
121                         {AuthType::kLocal, {1, 2, 3}, {4, 5, 6}}},
122                {}),
123            auth_.CreateAccessToken(
124                UserInfo{AuthScope::kViewer,
125                         {AuthType::kLocal, {1, 2, 3}, {4, 5, 7}}},
126                {}));
127}
128
129TEST_F(AuthManagerTest, CreateTokenDifferentScope) {
130  EXPECT_NE(auth_.CreateAccessToken(
131                UserInfo{AuthScope::kViewer, TestUserId{"456"}}, {}),
132            auth_.CreateAccessToken(
133                UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {}));
134}
135
136TEST_F(AuthManagerTest, CreateTokenDifferentUser) {
137  EXPECT_NE(auth_.CreateAccessToken(
138                UserInfo{AuthScope::kOwner, TestUserId{"456"}}, {}),
139            auth_.CreateAccessToken(
140                UserInfo{AuthScope::kOwner, TestUserId{"789"}}, {}));
141}
142
143TEST_F(AuthManagerTest, CreateTokenDifferentTime) {
144  auto token = auth_.CreateAccessToken(
145      UserInfo{AuthScope::kOwner, TestUserId{"567"}}, {});
146  EXPECT_CALL(clock_, Now())
147      .WillRepeatedly(Return(base::Time::FromTimeT(1400000000)));
148  EXPECT_NE(token, auth_.CreateAccessToken(
149                       UserInfo{AuthScope::kOwner, TestUserId{"567"}}, {}));
150}
151
152TEST_F(AuthManagerTest, CreateTokenDifferentInstance) {
153  EXPECT_NE(auth_.CreateAccessToken(
154                UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}),
155            AuthManager({}, {}).CreateAccessToken(
156                UserInfo{AuthScope::kUser, TestUserId{"123"}}, {}));
157}
158
159TEST_F(AuthManagerTest, ParseAccessToken) {
160  // Multiple attempts with random secrets.
161  const auto kStartTime = base::Time::FromTimeT(1412121212);
162  for (size_t i = 0; i < 1000; ++i) {
163    EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(kStartTime));
164
165    AuthManager auth{{}, {}, {}, &clock_};
166
167    auto token =
168        auth.CreateAccessToken(UserInfo{AuthScope::kUser, TestUserId{"5"}},
169                               base::TimeDelta::FromSeconds(i));
170    UserInfo user_info;
171    EXPECT_FALSE(auth_.ParseAccessToken(token, &user_info, nullptr));
172    EXPECT_TRUE(auth.ParseAccessToken(token, &user_info, nullptr));
173    EXPECT_EQ(AuthScope::kUser, user_info.scope());
174    EXPECT_EQ(TestUserId{"5"}, user_info.id());
175
176    EXPECT_CALL(clock_, Now())
177        .WillRepeatedly(Return(kStartTime + base::TimeDelta::FromSeconds(i)));
178    EXPECT_TRUE(auth.ParseAccessToken(token, &user_info, nullptr));
179
180    auto extended =
181        DelegateToUser(token, base::TimeDelta::FromSeconds(1000),
182                       UserInfo{AuthScope::kUser, TestUserId{"234"}});
183    EXPECT_FALSE(auth.ParseAccessToken(extended, &user_info, nullptr));
184
185    EXPECT_CALL(clock_, Now())
186        .WillRepeatedly(
187            Return(kStartTime + base::TimeDelta::FromSeconds(i + 1)));
188    EXPECT_FALSE(auth.ParseAccessToken(token, &user_info, nullptr));
189  }
190}
191
192TEST_F(AuthManagerTest, GetRootClientAuthToken) {
193  EXPECT_EQ("WCCDQxkgAUYIGhudoQBCDEBQZgRhYq78I8GtFUZHNBbfGw==",
194            Base64Encode(
195                auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient)));
196}
197
198TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentOwner) {
199  EXPECT_EQ(
200      "WCqDQxkgAUYIGhudoQBMDEpnb29nbGUuY29tUOoLAxSUAZAAv54drarqhag=",
201      Base64Encode(auth_.GetRootClientAuthToken(RootClientTokenOwner::kCloud)));
202}
203
204TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentTime) {
205  auto new_time = clock_.Now() + base::TimeDelta::FromDays(15);
206  EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
207  EXPECT_EQ("WCCDQxkgAUYIGhuxZ4BCDEBQjO+OTbjjTzZ/Dvk66nfQqg==",
208            Base64Encode(
209                auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient)));
210}
211
212TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentSecret) {
213  AuthManager auth{kSecret2, {}, kSecret1, &clock_};
214  EXPECT_EQ(
215      "WCCDQxkgAUYIGhudoQBCDEBQ2MZF8YXv5pbtmMxwz9VtLA==",
216      Base64Encode(auth.GetRootClientAuthToken(RootClientTokenOwner::kClient)));
217}
218
219TEST_F(AuthManagerTest, IsValidAuthToken) {
220  EXPECT_TRUE(auth_.IsValidAuthToken(
221      auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient), nullptr));
222  // Multiple attempts with random secrets.
223  for (size_t i = 0; i < 1000; ++i) {
224    AuthManager auth{{}, {}, {}, &clock_};
225
226    auto token = auth.GetRootClientAuthToken(RootClientTokenOwner::kClient);
227    EXPECT_FALSE(auth_.IsValidAuthToken(token, nullptr));
228    EXPECT_TRUE(auth.IsValidAuthToken(token, nullptr));
229  }
230}
231
232TEST_F(AuthManagerTest, CreateSessionId) {
233  EXPECT_EQ("463315200:1", auth_.CreateSessionId());
234}
235
236TEST_F(AuthManagerTest, IsValidSessionId) {
237  EXPECT_TRUE(auth_.IsValidSessionId("463315200:1"));
238  EXPECT_TRUE(auth_.IsValidSessionId("463315200:2"));
239  EXPECT_TRUE(auth_.IsValidSessionId("463315150"));
240
241  // Future
242  EXPECT_FALSE(auth_.IsValidSessionId("463315230:1"));
243
244  // Expired
245  EXPECT_FALSE(auth_.IsValidSessionId("463315100:1"));
246}
247
248TEST_F(AuthManagerTest, CreateAccessTokenFromAuth) {
249  std::vector<uint8_t> access_token;
250  AuthScope scope;
251  base::TimeDelta ttl;
252  auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kCloud);
253  auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000),
254                                 UserInfo{AuthScope::kUser, TestUserId{"234"}});
255  EXPECT_EQ(
256      "WE+IQxkgAUYIGhudoQBMDEpnb29nbGUuY29tRggaG52hAEYFGhudpOhCAQ5FCUMyMzRNEUs0"
257      "NjMzMTUyMDA6MVCRVKU+0SpOoBppnwqdKMwP",
258      Base64Encode(extended));
259  EXPECT_TRUE(
260      auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1),
261                                      &access_token, &scope, &ttl, nullptr));
262  UserInfo user_info;
263  EXPECT_TRUE(auth_.ParseAccessToken(access_token, &user_info, nullptr));
264  EXPECT_EQ(scope, user_info.scope());
265  EXPECT_EQ(AuthScope::kUser, user_info.scope());
266
267  EXPECT_EQ(TestUserId{"234"}, user_info.id());
268}
269
270TEST_F(AuthManagerTest, CreateAccessTokenFromAuthNotMinted) {
271  std::vector<uint8_t> access_token;
272  auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient);
273  ErrorPtr error;
274  EXPECT_FALSE(auth_.CreateAccessTokenFromAuth(
275      root, base::TimeDelta::FromDays(1), nullptr, nullptr, nullptr, &error));
276  EXPECT_TRUE(error->HasError("invalidAuthCode"));
277}
278
279TEST_F(AuthManagerTest, CreateAccessTokenFromAuthValidateAfterSomeTime) {
280  auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient);
281  auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000),
282                                 UserInfo{AuthScope::kUser, TestUserId{"234"}});
283
284  // new_time < session_id_expiration < token_expiration.
285  auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(15);
286  EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
287  EXPECT_TRUE(
288      auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1),
289                                      nullptr, nullptr, nullptr, nullptr));
290}
291
292TEST_F(AuthManagerTest, CreateAccessTokenFromAuthExpired) {
293  auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient);
294  auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(10),
295                                 UserInfo{AuthScope::kUser, TestUserId{"234"}});
296  ErrorPtr error;
297
298  // token_expiration < new_time < session_id_expiration.
299  auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(15);
300  EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
301  EXPECT_FALSE(
302      auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1),
303                                      nullptr, nullptr, nullptr, &error));
304  EXPECT_TRUE(error->HasError("invalidAuthCode"));
305}
306
307TEST_F(AuthManagerTest, CreateAccessTokenFromAuthExpiredSessionid) {
308  auto root = auth_.GetRootClientAuthToken(RootClientTokenOwner::kClient);
309  auto extended = DelegateToUser(root, base::TimeDelta::FromSeconds(1000),
310                                 UserInfo{AuthScope::kUser, TestUserId{"234"}});
311  ErrorPtr error;
312
313  // session_id_expiration < new_time < token_expiration.
314  auto new_time = clock_.Now() + base::TimeDelta::FromSeconds(200);
315  EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
316  EXPECT_FALSE(
317      auth_.CreateAccessTokenFromAuth(extended, base::TimeDelta::FromDays(1),
318                                      nullptr, nullptr, nullptr, &error));
319  EXPECT_TRUE(error->HasError("invalidAuthCode"));
320}
321
322class AuthManagerClaimTest : public testing::Test {
323 public:
324  void SetUp() override { EXPECT_EQ(auth_.GetAuthSecret().size(), 32u); }
325
326  bool TestClaim(RootClientTokenOwner owner, RootClientTokenOwner claimer) {
327    Config::Transaction change{&config_};
328    change.set_root_client_token_owner(owner);
329    change.Commit();
330    return !auth_.ClaimRootClientAuthToken(claimer, nullptr).empty();
331  }
332
333 protected:
334  Config config_{nullptr};
335  AuthManager auth_{&config_, {}};
336};
337
338TEST_F(AuthManagerClaimTest, WithPreviosOwner) {
339  EXPECT_DEATH(
340      TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kNone), "");
341  EXPECT_DEATH(
342      TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kNone),
343      "");
344  EXPECT_DEATH(
345      TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kNone), "");
346  EXPECT_TRUE(
347      TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kClient));
348  EXPECT_FALSE(
349      TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kClient));
350  EXPECT_FALSE(
351      TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kClient));
352  EXPECT_TRUE(
353      TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kCloud));
354  EXPECT_TRUE(
355      TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kCloud));
356  EXPECT_TRUE(
357      TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kCloud));
358}
359
360TEST_F(AuthManagerClaimTest, NormalClaim) {
361  auto token =
362      auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
363  EXPECT_FALSE(auth_.IsValidAuthToken(token, nullptr));
364  EXPECT_EQ(RootClientTokenOwner::kNone,
365            config_.GetSettings().root_client_token_owner);
366
367  EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
368  EXPECT_TRUE(auth_.IsValidAuthToken(token, nullptr));
369  EXPECT_EQ(RootClientTokenOwner::kCloud,
370            config_.GetSettings().root_client_token_owner);
371}
372
373TEST_F(AuthManagerClaimTest, DoubleConfirm) {
374  auto token =
375      auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
376  EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
377  EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
378}
379
380TEST_F(AuthManagerClaimTest, DoubleClaim) {
381  auto token1 =
382      auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
383  auto token2 =
384      auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
385  EXPECT_TRUE(auth_.ConfirmClientAuthToken(token1, nullptr));
386  EXPECT_FALSE(auth_.ConfirmClientAuthToken(token2, nullptr));
387}
388
389TEST_F(AuthManagerClaimTest, TokenOverflow) {
390  auto token =
391      auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
392  for (size_t i = 0; i < 100; ++i)
393    auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
394  EXPECT_FALSE(auth_.ConfirmClientAuthToken(token, nullptr));
395}
396
397}  // namespace privet
398}  // namespace weave
399