Changed AuthManager::CreateAccessToken and AuthManager::ParseAccessToken With this API we can handle expiration checks inside of AuthManager BUG=25768507 Change-Id: I2fa5d428be6f0772d8b2656eb2bee71824f0d308 Reviewed-on: https://weave-review.googlesource.com/2030 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc index 51d7592..27a5e7e 100644 --- a/src/privet/auth_manager.cc +++ b/src/privet/auth_manager.cc
@@ -135,25 +135,53 @@ AuthManager::~AuthManager() {} -// Returns "[hmac]scope:id:time". -std::vector<uint8_t> AuthManager::CreateAccessToken(const UserInfo& user_info) { - std::string data_str{CreateTokenData(user_info, Now())}; +// Returns "[hmac]scope:id:expiration_time". +std::vector<uint8_t> AuthManager::CreateAccessToken(const UserInfo& user_info, + base::TimeDelta ttl) const { + std::string data_str{CreateTokenData(user_info, Now() + ttl)}; std::vector<uint8_t> data{data_str.begin(), data_str.end()}; std::vector<uint8_t> hash{HmacSha256(secret_, data)}; hash.insert(hash.end(), data.begin(), data.end()); return hash; } -// Parses "base64([hmac]scope:id:time)". -UserInfo AuthManager::ParseAccessToken(const std::vector<uint8_t>& token, - base::Time* time) const { - if (token.size() <= kSha256OutputSize) - return UserInfo{}; +// TODO(vitalybuka): Switch to Macaroon? +// Parses "base64([hmac]scope:id:expriration_time)". +bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token, + UserInfo* user_info, + ErrorPtr* error) const { + if (token.size() <= kSha256OutputSize) { + Error::AddToPrintf(error, FROM_HERE, errors::kDomain, + errors::kInvalidAuthorization, "Invalid token size: %zu", + token.size()); + return false; + } std::vector<uint8_t> hash(token.begin(), token.begin() + kSha256OutputSize); std::vector<uint8_t> data(token.begin() + kSha256OutputSize, token.end()); - if (hash != HmacSha256(secret_, data)) - return UserInfo{}; - return SplitTokenData(std::string(data.begin(), data.end()), time); + if (hash != HmacSha256(secret_, data)) { + Error::AddTo(error, FROM_HERE, errors::kDomain, + errors::kInvalidAuthorization, "Invalid signature"); + return false; + } + + base::Time time; + UserInfo info = SplitTokenData(std::string(data.begin(), data.end()), &time); + if (info.scope() == AuthScope::kNone) { + Error::AddTo(error, FROM_HERE, errors::kDomain, + errors::kInvalidAuthorization, "Invalid token data"); + return false; + } + + if (time < clock_->Now()) { + Error::AddTo(error, FROM_HERE, errors::kDomain, + errors::kAuthorizationExpired, "Token is expired"); + return false; + } + + if (user_info) + *user_info = info; + + return true; } std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken(
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h index a74e43b..8b99254 100644 --- a/src/privet/auth_manager.h +++ b/src/privet/auth_manager.h
@@ -33,9 +33,12 @@ base::Clock* clock = nullptr); ~AuthManager(); - std::vector<uint8_t> CreateAccessToken(const UserInfo& user_info); - UserInfo ParseAccessToken(const std::vector<uint8_t>& token, - base::Time* time) const; + std::vector<uint8_t> CreateAccessToken(const UserInfo& user_info, + base::TimeDelta ttl) const; + + bool ParseAccessToken(const std::vector<uint8_t>& token, + UserInfo* user_info, + ErrorPtr* error) const; const std::vector<uint8_t>& GetSecret() const { return secret_; } const std::vector<uint8_t>& GetCertificateFingerprint() const {
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc index a571d4f..2685be5 100644 --- a/src/privet/auth_manager_unittest.cc +++ b/src/privet/auth_manager_unittest.cc
@@ -58,65 +58,79 @@ } TEST_F(AuthManagerTest, CreateAccessToken) { - EXPECT_EQ( - "OUH2L2npY+Gzwjf9AnqigGSK3hxIVR+xX8/Cnu4DGf8wOjA6MTQxMDAwMDAwMA==", - Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kNone, 123}))); - EXPECT_EQ( - "iZx0qgEHFF5lq+Q503GtgU0d6gLQ9TlLsU+DcFbZb2QxOjIzNDoxNDEwMDAwMDAw", - Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 234}))); - EXPECT_EQ("cWkAHxSBYtTFV3Va/9mcynR8iFZo2qr+8+WewmumF74zOjI1NzoxNDEwMDAwMDAw", + EXPECT_EQ("OUH2L2npY+Gzwjf9AnqigGSK3hxIVR+xX8/Cnu4DGf8wOjA6MTQxMDAwMDAwMA==", Base64Encode( - auth_.CreateAccessToken(UserInfo{AuthScope::kManager, 257}))); - EXPECT_EQ( - "s3GnCThkQXIzGQoPDlJoiehQiJ5yy4SYUVQzMN2kY0o0OjQ1NjoxNDEwMDAwMDAw", - Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}))); + auth_.CreateAccessToken(UserInfo{AuthScope::kNone, 123}, {}))); + EXPECT_EQ("iZx0qgEHFF5lq+Q503GtgU0d6gLQ9TlLsU+DcFbZb2QxOjIzNDoxNDEwMDAwMDAw", + Base64Encode(auth_.CreateAccessToken( + UserInfo{AuthScope::kViewer, 234}, {}))); + EXPECT_EQ("cWkAHxSBYtTFV3Va/9mcynR8iFZo2qr+8+WewmumF74zOjI1NzoxNDEwMDAwMDAw", + Base64Encode(auth_.CreateAccessToken( + UserInfo{AuthScope::kManager, 257}, {}))); + EXPECT_EQ("s3GnCThkQXIzGQoPDlJoiehQiJ5yy4SYUVQzMN2kY0o0OjQ1NjoxNDEwMDAwMDAw", + Base64Encode( + auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}, {}))); auto new_time = clock_.Now() + base::TimeDelta::FromDays(11); EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time)); - EXPECT_EQ( - "qAmlJykiPTnFljfOKSf3BUII9YZG8/ttzD76q+fII1YyOjM0NToxNDEwOTUwNDAw", - Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kUser, 345}))); + EXPECT_EQ("qAmlJykiPTnFljfOKSf3BUII9YZG8/ttzD76q+fII1YyOjM0NToxNDEwOTUwNDAw", + Base64Encode( + auth_.CreateAccessToken(UserInfo{AuthScope::kUser, 345}, {}))); } TEST_F(AuthManagerTest, CreateSameToken) { - EXPECT_EQ(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}), - auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555})); + EXPECT_EQ(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}, {}), + auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}, {})); } TEST_F(AuthManagerTest, CreateTokenDifferentScope) { - EXPECT_NE(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 456}), - auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456})); + EXPECT_NE(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 456}, {}), + auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}, {})); } TEST_F(AuthManagerTest, CreateTokenDifferentUser) { - EXPECT_NE(auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}), - auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 789})); + EXPECT_NE(auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}, {}), + auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 789}, {})); } TEST_F(AuthManagerTest, CreateTokenDifferentTime) { - auto token = auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567}); + auto token = auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567}, {}); EXPECT_CALL(clock_, Now()) .WillRepeatedly(Return(base::Time::FromTimeT(1400000000))); - EXPECT_NE(token, auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567})); + EXPECT_NE(token, + auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567}, {})); } TEST_F(AuthManagerTest, CreateTokenDifferentInstance) { - EXPECT_NE( - auth_.CreateAccessToken(UserInfo{AuthScope::kUser, 123}), - AuthManager({}, {}).CreateAccessToken(UserInfo{AuthScope::kUser, 123})); + EXPECT_NE(auth_.CreateAccessToken(UserInfo{AuthScope::kUser, 123}, {}), + AuthManager({}, {}).CreateAccessToken( + UserInfo{AuthScope::kUser, 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, 5}); + auto token = auth.CreateAccessToken(UserInfo{AuthScope::kUser, 5}, + base::TimeDelta::FromSeconds(i)); base::Time time2; - EXPECT_EQ(AuthScope::kNone, auth_.ParseAccessToken(token, nullptr).scope()); - EXPECT_EQ(AuthScope::kUser, auth.ParseAccessToken(token, &time2).scope()); - EXPECT_EQ(5u, auth.ParseAccessToken(token, &time2).user_id()); - // Token timestamp resolution is one second. - EXPECT_GE(1, std::abs((clock_.Now() - time2).InSeconds())); + 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(5u, user_info.user_id()); + + EXPECT_CALL(clock_, Now()) + .WillRepeatedly(Return(kStartTime + base::TimeDelta::FromSeconds(i))); + EXPECT_TRUE(auth.ParseAccessToken(token, &user_info, nullptr)); + + EXPECT_CALL(clock_, Now()) + .WillRepeatedly( + Return(kStartTime + base::TimeDelta::FromSeconds(i + 1))); + EXPECT_FALSE(auth.ParseAccessToken(token, &user_info, nullptr)); } }
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h index 8cede23..bc7ec93 100644 --- a/src/privet/mock_delegates.h +++ b/src/privet/mock_delegates.h
@@ -62,9 +62,10 @@ class MockSecurityDelegate : public SecurityDelegate { public: - MOCK_METHOD1(CreateAccessToken, std::string(const UserInfo&)); - MOCK_CONST_METHOD2(ParseAccessToken, - UserInfo(const std::string&, base::Time*)); + MOCK_CONST_METHOD2(CreateAccessToken, + std::string(const UserInfo&, base::TimeDelta)); + MOCK_CONST_METHOD3(ParseAccessToken, + bool(const std::string&, UserInfo*, ErrorPtr*)); MOCK_CONST_METHOD0(GetPairingTypes, std::set<PairingType>()); MOCK_CONST_METHOD0(GetCryptoTypes, std::set<CryptoType>()); MOCK_METHOD1(ClaimRootClientAuthToken, std::string(ErrorPtr*)); @@ -83,7 +84,7 @@ MOCK_METHOD0(CreateSessionId, std::string()); MockSecurityDelegate() { - EXPECT_CALL(*this, CreateAccessToken(_)) + EXPECT_CALL(*this, CreateAccessToken(_, _)) .WillRepeatedly(Return("GuestAccessToken")); EXPECT_CALL(*this, ClaimRootClientAuthToken(_)) @@ -92,9 +93,10 @@ EXPECT_CALL(*this, ConfirmClientAuthToken("DerivedClientAuthToken", _)) .WillRepeatedly(Return(true)); - EXPECT_CALL(*this, ParseAccessToken(_, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()), - Return(UserInfo{AuthScope::kViewer, 1234567}))); + EXPECT_CALL(*this, ParseAccessToken(_, _, _)) + .WillRepeatedly( + DoAll(SetArgPointee<1>(UserInfo{AuthScope::kViewer, 1234567}), + Return(true))); EXPECT_CALL(*this, GetPairingTypes()) .WillRepeatedly(Return(std::set<PairingType>{
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc index d7e68bb..0af431b 100644 --- a/src/privet/privet_handler.cc +++ b/src/privet/privet_handler.cc
@@ -121,10 +121,6 @@ const int kAccessTokenExpirationSeconds = 3600; -// Threshold to reduce probability of expiration because of clock difference -// between device and client. Value is just a guess. -const int kAccessTokenExpirationThresholdSeconds = 300; - template <class Container> std::unique_ptr<base::ListValue> ToValue(const Container& list) { std::unique_ptr<base::ListValue> value_list(new base::ListValue()); @@ -518,23 +514,8 @@ } UserInfo user_info; if (token != kAuthTypeAnonymousValue) { - base::Time time; - user_info = security_->ParseAccessToken(token, &time); - if (user_info.scope() == AuthScope::kNone) { - Error::AddToPrintf(&error, FROM_HERE, errors::kDomain, - errors::kInvalidAuthorization, - "Invalid access token: %s", token.c_str()); + if (!security_->ParseAccessToken(token, &user_info, &error)) return ReturnError(*error, callback); - } - time += base::TimeDelta::FromSeconds(kAccessTokenExpirationSeconds); - time += - base::TimeDelta::FromSeconds(kAccessTokenExpirationThresholdSeconds); - if (time < clock_->Now()) { - Error::AddToPrintf(&error, FROM_HERE, errors::kDomain, - errors::kAuthorizationExpired, "Token expired: %s", - token.c_str()); - return ReturnError(*error, callback); - } } if (handler->second.scope > user_info.scope()) { @@ -740,9 +721,11 @@ } base::DictionaryValue output; - output.SetString(kAuthAccessTokenKey, - security_->CreateAccessToken( - UserInfo{requested_auth_scope, ++last_user_id_})); + output.SetString( + kAuthAccessTokenKey, + security_->CreateAccessToken( + UserInfo{requested_auth_scope, ++last_user_id_}, + base::TimeDelta::FromSeconds(kAccessTokenExpirationSeconds))); output.SetString(kAuthTokenTypeKey, kAuthorizationHeaderPrefix); output.SetInteger(kAuthExpiresInKey, kAccessTokenExpirationSeconds); output.SetString(kAuthScopeKey, EnumToString(requested_auth_scope));
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc index c4180b9..53f1a05 100644 --- a/src/privet/privet_handler_unittest.cc +++ b/src/privet/privet_handler_unittest.cc
@@ -196,9 +196,12 @@ TEST_F(PrivetHandlerTest, ExpiredAuth) { auth_header_ = "Privet 123"; - EXPECT_CALL(security_, ParseAccessToken(_, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time()), - Return(UserInfo{AuthScope::kOwner, 1}))); + EXPECT_CALL(security_, ParseAccessToken(_, _, _)) + .WillRepeatedly(DoAll(WithArgs<2>(Invoke([](ErrorPtr* error) { + Error::AddTo(error, FROM_HERE, errors::kDomain, + "authorizationExpired", ""); + })), + Return(false))); EXPECT_PRED2(IsEqualError, CodeWithReason(403, "authorizationExpired"), HandleRequest("/privet/info", "{}")); } @@ -400,7 +403,7 @@ TEST_F(PrivetHandlerTest, AuthPairing) { EXPECT_CALL(security_, IsValidPairingCode("testToken")) .WillRepeatedly(Return(true)); - EXPECT_CALL(security_, CreateAccessToken(_)) + EXPECT_CALL(security_, CreateAccessToken(_, _)) .WillRepeatedly(Return("OwnerAccessToken")); const char kInput[] = R"({ 'mode': 'pairing', @@ -421,9 +424,9 @@ void SetUp() override { PrivetHandlerTest::SetUp(); auth_header_ = "Privet 123"; - EXPECT_CALL(security_, ParseAccessToken(_, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()), - Return(UserInfo{AuthScope::kOwner, 1}))); + EXPECT_CALL(security_, ParseAccessToken(_, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(UserInfo{AuthScope::kOwner, 1}), + Return(true))); } }; @@ -597,9 +600,9 @@ } TEST_F(PrivetHandlerSetupTest, GcdSetupAsMaster) { - EXPECT_CALL(security_, ParseAccessToken(_, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()), - Return(UserInfo{AuthScope::kManager, 1}))); + EXPECT_CALL(security_, ParseAccessToken(_, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(UserInfo{AuthScope::kManager, 1}), + Return(true))); const char kInput[] = R"({ 'gcd': { 'ticketId': 'testTicket',
diff --git a/src/privet/security_delegate.h b/src/privet/security_delegate.h index d8090bd..fdf9a84 100644 --- a/src/privet/security_delegate.h +++ b/src/privet/security_delegate.h
@@ -22,11 +22,13 @@ virtual ~SecurityDelegate() {} // Creates access token for the given scope, user id and |time|. - virtual std::string CreateAccessToken(const UserInfo& user_info) = 0; + virtual std::string CreateAccessToken(const UserInfo& user_info, + base::TimeDelta ttl) const = 0; - // Validates |token| and returns scope and user id parsed from that. - virtual UserInfo ParseAccessToken(const std::string& token, - base::Time* time) const = 0; + // Validates |token| and returns scope, user id parsed from that. + virtual bool ParseAccessToken(const std::string& token, + UserInfo* user_info, + ErrorPtr* error) const = 0; // Returns list of pairing methods by device. virtual std::set<PairingType> GetPairingTypes() const = 0;
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc index 46212f4..d2b7b35 100644 --- a/src/privet/security_manager.cc +++ b/src/privet/security_manager.cc
@@ -109,19 +109,23 @@ ClosePendingSession(pending_sessions_.begin()->first); } -// Returns "base64([hmac]scope:id:time)". -std::string SecurityManager::CreateAccessToken(const UserInfo& user_info) { - return Base64Encode(auth_manager_->CreateAccessToken(user_info)); +std::string SecurityManager::CreateAccessToken(const UserInfo& user_info, + base::TimeDelta ttl) const { + return Base64Encode(auth_manager_->CreateAccessToken(user_info, ttl)); } -// Parses "base64([hmac]scope:id:time)". -UserInfo SecurityManager::ParseAccessToken(const std::string& token, - base::Time* time) const { +bool SecurityManager::ParseAccessToken(const std::string& token, + UserInfo* user_info, + ErrorPtr* error) const { std::vector<uint8_t> decoded; - if (!Base64Decode(token, &decoded)) - return UserInfo{}; + if (!Base64Decode(token, &decoded)) { + Error::AddToPrintf(error, FROM_HERE, errors::kDomain, + errors::kInvalidAuthorization, + "Invalid token encoding: %s", token.c_str()); + return false; + } - return auth_manager_->ParseAccessToken(decoded, time); + return auth_manager_->ParseAccessToken(decoded, user_info, error); } std::set<PairingType> SecurityManager::GetPairingTypes() const {
diff --git a/src/privet/security_manager.h b/src/privet/security_manager.h index 2505099..f65f7bd 100644 --- a/src/privet/security_manager.h +++ b/src/privet/security_manager.h
@@ -60,9 +60,11 @@ ~SecurityManager() override; // SecurityDelegate methods - std::string CreateAccessToken(const UserInfo& user_info) override; - UserInfo ParseAccessToken(const std::string& token, - base::Time* time) const override; + std::string CreateAccessToken(const UserInfo& user_info, + base::TimeDelta ttl) const override; + bool ParseAccessToken(const std::string& token, + UserInfo* user_info, + ErrorPtr* error) const override; std::set<PairingType> GetPairingTypes() const override; std::set<CryptoType> GetCryptoTypes() const override; std::string ClaimRootClientAuthToken(ErrorPtr* error) override;
diff --git a/src/privet/security_manager_unittest.cc b/src/privet/security_manager_unittest.cc index 7c26026..f48ec7f 100644 --- a/src/privet/security_manager_unittest.cc +++ b/src/privet/security_manager_unittest.cc
@@ -103,7 +103,8 @@ provider::test::FakeTaskRunner task_runner_; test::MockClock clock_; AuthManager auth_manager_{ - {}, + {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}, { 59, 47, 77, 247, 129, 187, 188, 158, 172, 105, 246, 93, 102, 83, 8, 138, 176, 141, 37, 63, 223, 40, 153, 121, 134, 23, 120, 106, 24, 205, @@ -117,56 +118,19 @@ &task_runner_}; }; -TEST_F(SecurityManagerTest, IsBase64) { - EXPECT_TRUE( - IsBase64(security_.CreateAccessToken(UserInfo{AuthScope::kUser, 7}))); -} - -TEST_F(SecurityManagerTest, CreateSameToken) { - EXPECT_EQ(security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}), - security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555})); -} - -TEST_F(SecurityManagerTest, CreateTokenDifferentScope) { - EXPECT_NE(security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 456}), - security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456})); -} - -TEST_F(SecurityManagerTest, CreateTokenDifferentUser) { - EXPECT_NE(security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}), - security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 789})); -} - -TEST_F(SecurityManagerTest, CreateTokenDifferentTime) { - auto token = security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567}); - EXPECT_CALL(clock_, Now()) - .WillRepeatedly(Return(base::Time::FromTimeT(1400000000))); - EXPECT_NE(token, - security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567})); -} - -TEST_F(SecurityManagerTest, CreateTokenDifferentInstance) { - AuthManager auth{{}, {}, &clock_}; - EXPECT_NE(security_.CreateAccessToken(UserInfo{AuthScope::kUser, 123}), - SecurityManager(&auth, {}, "", false, &task_runner_) - .CreateAccessToken(UserInfo{AuthScope::kUser, 123})); +TEST_F(SecurityManagerTest, CreateAccessToken) { + EXPECT_EQ("TV18I+N7cDPah7Nq6o7pl5H7DjDu5nCDf/cbdE4FZFEyOjc6MTQxMDAwMDA2MA==", + security_.CreateAccessToken(UserInfo{AuthScope::kUser, 7}, + base::TimeDelta::FromMinutes(1))); } TEST_F(SecurityManagerTest, ParseAccessToken) { - // Multiple attempts with random secrets. - for (size_t i = 0; i < 1000; ++i) { - AuthManager auth{{}, {}, &clock_}; - SecurityManager security{&auth, {}, "", false, &task_runner_}; - - std::string token = - security.CreateAccessToken(UserInfo{AuthScope::kUser, 5}); - base::Time time2; - EXPECT_EQ(AuthScope::kUser, - security.ParseAccessToken(token, &time2).scope()); - EXPECT_EQ(5u, security.ParseAccessToken(token, &time2).user_id()); - // Token timestamp resolution is one second. - EXPECT_GE(1, std::abs((clock_.Now() - time2).InSeconds())); - } + UserInfo info; + EXPECT_TRUE(security_.ParseAccessToken( + "MMe7FE+EMyG4OnD2457dF5Nqh9Uiaq2iRWRzkSOW+SAzOjk6MTQxMDAwMDkwMA==", &info, + nullptr)); + EXPECT_EQ(AuthScope::kManager, info.scope()); + EXPECT_EQ(9u, info.user_id()); } TEST_F(SecurityManagerTest, PairingNoSession) {