Skip to content

Commit 81f5bef

Browse files
Maciek SlusarczykChromium LUCI CQ
authored andcommitted
Remove token rotation from TokenHandleUtil
The rotation mechanism has been added 20+ milestones ago(in M91) and all actively used Chromebooks should have it already rotated. In case it were not it will only lead to a single additional online reauth as a result of failed token handle check. The metric that captures token validation response time has been also added to the branch where token validation fails (because e.g. it has been changed from another device). Bug: b:274707666 Change-Id: I47cd349ab4fbb71b5cabb254d78910a455f5bd47 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4489265 Reviewed-by: Danila Kuzmin <dkuzmin@google.com> Reviewed-by: Kush Sinha <sinhak@chromium.org> Commit-Queue: Maciek Slusarczyk <mslus@chromium.org> Reviewed-by: Roman Sorokin <rsorokin@google.com> Cr-Commit-Position: refs/heads/main@{#1140097}
1 parent 0e0015d commit 81f5bef

File tree

5 files changed

+35
-89
lines changed

5 files changed

+35
-89
lines changed

chrome/browser/ash/login/password_change_browsertest.cc

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -589,45 +589,6 @@ IN_PROC_BROWSER_TEST_F(TokenAfterCrash, ValidToken) {
589589
->token_handle_backfill_tried_for_testing());
590590
}
591591

592-
class RotationTokenTest : public LoginManagerTest {
593-
public:
594-
RotationTokenTest() {
595-
login_mixin_.AppendRegularUsers(1);
596-
account_id_ = login_mixin_.users()[0].account_id;
597-
}
598-
599-
protected:
600-
LoginManagerMixin login_mixin_{&mixin_host_};
601-
AccountId account_id_;
602-
};
603-
604-
// Test verifies one-time rotation for the token handle.
605-
IN_PROC_BROWSER_TEST_F(RotationTokenTest, PRE_Rotated) {
606-
TokenHandleUtil::StoreTokenHandle(account_id_, kTokenHandle);
607-
608-
user_manager::KnownUser known_user(g_browser_process->local_state());
609-
// Emulate state before rotation.
610-
known_user.RemovePref(account_id_, "TokenHandleRotated");
611-
612-
// Focus should not trigger online login.
613-
LoginScreenTestApi::FocusUser(account_id_);
614-
ASSERT_FALSE(LoginScreenTestApi::IsForcedOnlineSignin(account_id_));
615-
616-
// Should be considered for rotation.
617-
EXPECT_TRUE(TokenHandleUtil::ShouldObtainHandle(account_id_));
618-
619-
login_mixin_.LoginWithDefaultContext(login_mixin_.users().back());
620-
login_mixin_.WaitForActiveSession();
621-
622-
// Emulate obtaining token handle.
623-
TokenHandleUtil::StoreTokenHandle(account_id_, kTokenHandle);
624-
}
625-
626-
IN_PROC_BROWSER_TEST_F(RotationTokenTest, Rotated) {
627-
// Token should not be considered for rotation..
628-
EXPECT_FALSE(TokenHandleUtil::ShouldObtainHandle(account_id_));
629-
}
630-
631592
class IgnoreOldTokenTest
632593
: public LoginManagerTest,
633594
public LocalStateMixin::Delegate,
@@ -651,10 +612,6 @@ class IgnoreOldTokenTest
651612
// rotated token.
652613
return;
653614
}
654-
655-
user_manager::KnownUser known_user(g_browser_process->local_state());
656-
// Emulate token was not rotated.
657-
known_user.RemovePref(account_id_, "TokenHandleRotated");
658615
}
659616

660617
// LoginManagerTest:
@@ -677,18 +634,18 @@ class IgnoreOldTokenTest
677634
LocalStateMixin local_state_mixin_{&mixin_host_, this};
678635
};
679636

680-
// Verify case when a user got token invalidated on a previous version and then
681-
// updated to the version when not rotated tokens are ignored for managed users.
637+
// Verify case when a user got token invalidated on a pre-rotated version and
638+
// then never re-authenticated. Such scenario should now lead to an online
639+
// sign-in and fetching a new token handle.
682640
IN_PROC_BROWSER_TEST_P(IgnoreOldTokenTest, PRE_IgnoreNotRotated) {
683641
ASSERT_TRUE(LoginScreenTestApi::IsForcedOnlineSignin(account_id_));
684642
}
685643

686-
// Old tokens should be ignored for managed users. Regular users should be
687-
// forced to go through online signin.
644+
// If any pre-rotated token handle is still left for either regular or managed
645+
// user it will verified as invalid and lead to online re-authenication.
688646
IN_PROC_BROWSER_TEST_P(IgnoreOldTokenTest, IgnoreNotRotated) {
689-
ASSERT_NE(TokenHandleUtil::HasToken(account_id_), IsManagedUser());
690-
ASSERT_NE(LoginScreenTestApi::IsForcedOnlineSignin(account_id_),
691-
IsManagedUser());
647+
ASSERT_TRUE(TokenHandleUtil::HasToken(account_id_));
648+
ASSERT_TRUE(LoginScreenTestApi::IsForcedOnlineSignin(account_id_));
692649
}
693650

694651
INSTANTIATE_TEST_SUITE_P(All, IgnoreOldTokenTest, testing::Bool());

chrome/browser/ash/login/signin/token_handle_fetcher.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <memory>
88

99
#include "base/functional/bind.h"
10-
#include "base/metrics/histogram_macros.h"
10+
#include "base/metrics/histogram_functions.h"
1111
#include "chrome/browser/ash/login/signin/token_handle_util.h"
1212
#include "chrome/browser/ash/profiles/profile_helper.h"
1313
#include "chrome/browser/profiles/profile.h"
@@ -146,7 +146,7 @@ void TokenHandleFetcher::OnGetTokenInfoResponse(
146146
}
147147
const base::TimeDelta duration =
148148
base::TimeTicks::Now() - tokeninfo_response_start_time_;
149-
UMA_HISTOGRAM_TIMES("Login.TokenObtainResponseTime", duration);
149+
base::UmaHistogramTimes("Login.TokenObtainResponseTime", duration);
150150
std::move(callback_).Run(account_id_, success);
151151
}
152152

chrome/browser/ash/login/signin/token_handle_util.cc

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include "base/json/values_util.h"
88
#include "base/memory/weak_ptr.h"
9-
#include "base/metrics/histogram_macros.h"
9+
#include "base/metrics/histogram_functions.h"
1010
#include "base/values.h"
1111
#include "chrome/browser/browser_process.h"
1212
#include "chrome/browser/profiles/profile.h"
@@ -20,7 +20,6 @@ namespace {
2020
const char kTokenHandlePref[] = "PasswordTokenHandle";
2121
const char kTokenHandleStatusPref[] = "TokenHandleStatus";
2222
const char kTokenHandleLastCheckedPref[] = "TokenHandleLastChecked";
23-
const char kTokenHandleRotated[] = "TokenHandleRotated";
2423

2524
const char kHandleStatusValid[] = "valid";
2625
const char kHandleStatusInvalid[] = "invalid";
@@ -102,15 +101,6 @@ TokenHandleUtil::~TokenHandleUtil() = default;
102101
// static
103102
bool TokenHandleUtil::HasToken(const AccountId& account_id) {
104103
user_manager::KnownUser known_user(g_browser_process->local_state());
105-
bool token_rotated =
106-
known_user.FindBoolPath(account_id, kTokenHandleRotated).value_or(false);
107-
if (!token_rotated && known_user.GetIsEnterpriseManaged(account_id)) {
108-
// Ignore not rotated token starting from M94 for enterprise users to avoid
109-
// blocking them on the login screen. Rotation started in M91.
110-
ClearTokenHandle(account_id);
111-
return false;
112-
}
113-
114104
const std::string* token =
115105
known_user.FindStringPath(account_id, kTokenHandlePref);
116106
return token && !token->empty();
@@ -134,11 +124,7 @@ bool TokenHandleUtil::IsRecentlyChecked(const AccountId& account_id) {
134124

135125
// static
136126
bool TokenHandleUtil::ShouldObtainHandle(const AccountId& account_id) {
137-
user_manager::KnownUser known_user(g_browser_process->local_state());
138-
bool token_rotated =
139-
known_user.FindBoolPath(account_id, kTokenHandleRotated).value_or(false);
140-
return !HasToken(account_id) || HasTokenStatusInvalid(account_id) ||
141-
!token_rotated;
127+
return !HasToken(account_id) || HasTokenStatusInvalid(account_id);
142128
}
143129

144130
// static
@@ -186,21 +172,10 @@ void TokenHandleUtil::StoreTokenHandle(const AccountId& account_id,
186172
known_user.SetStringPref(account_id, kTokenHandlePref, handle);
187173
known_user.SetStringPref(account_id, kTokenHandleStatusPref,
188174
kHandleStatusValid);
189-
known_user.SetBooleanPref(account_id, kTokenHandleRotated, true);
190175
known_user.SetPath(account_id, kTokenHandleLastCheckedPref,
191176
base::TimeToValue(base::Time::Now()));
192177
}
193178

194-
// static
195-
void TokenHandleUtil::ClearTokenHandle(const AccountId& account_id) {
196-
user_manager::KnownUser known_user(g_browser_process->local_state());
197-
198-
known_user.RemovePref(account_id, kTokenHandlePref);
199-
known_user.RemovePref(account_id, kTokenHandleStatusPref);
200-
known_user.RemovePref(account_id, kTokenHandleRotated);
201-
known_user.RemovePref(account_id, kTokenHandleLastCheckedPref);
202-
}
203-
204179
// static
205180
void TokenHandleUtil::SetInvalidTokenForTesting(const char* token) {
206181
g_invalid_token_for_testing = token;
@@ -237,18 +212,27 @@ TokenHandleUtil::TokenDelegate::~TokenDelegate() = default;
237212

238213
void TokenHandleUtil::TokenDelegate::OnOAuthError() {
239214
std::move(callback_).Run(account_id_, INVALID);
240-
NotifyDone();
215+
NotifyDone(/*request_completed=*/true);
241216
}
242217

243218
// Warning: NotifyDone() deletes `this`
244-
void TokenHandleUtil::TokenDelegate::NotifyDone() {
219+
void TokenHandleUtil::TokenDelegate::NotifyDone(bool request_completed) {
220+
if (request_completed) {
221+
RecordTokenCheckResponseTime();
222+
}
245223
if (owner_)
246224
owner_->OnValidationComplete(token_);
247225
}
248226

249227
void TokenHandleUtil::TokenDelegate::OnNetworkError(int response_code) {
250228
std::move(callback_).Run(account_id_, UNKNOWN);
251-
NotifyDone();
229+
NotifyDone(/*request_completed=*/response_code != -1);
230+
}
231+
232+
void TokenHandleUtil::TokenDelegate::RecordTokenCheckResponseTime() {
233+
const base::TimeDelta duration =
234+
base::TimeTicks::Now() - tokeninfo_response_start_time_;
235+
base::UmaHistogramTimes("Login.TokenCheckResponseTime", duration);
252236
}
253237

254238
void TokenHandleUtil::TokenDelegate::OnGetTokenInfoResponse(
@@ -260,11 +244,8 @@ void TokenHandleUtil::TokenDelegate::OnGetTokenInfoResponse(
260244
outcome = (*expires_in < 0) ? INVALID : VALID;
261245
}
262246

263-
const base::TimeDelta duration =
264-
base::TimeTicks::Now() - tokeninfo_response_start_time_;
265-
UMA_HISTOGRAM_TIMES("Login.TokenCheckResponseTime", duration);
266247
std::move(callback_).Run(account_id_, outcome);
267-
NotifyDone();
248+
NotifyDone(/*request_completed=*/true);
268249
}
269250

270251
} // namespace ash

chrome/browser/ash/login/signin/token_handle_util.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ class TokenHandleUtil {
5858
static void StoreTokenHandle(const AccountId& account_id,
5959
const std::string& handle);
6060

61-
static void ClearTokenHandle(const AccountId& account_id);
62-
6361
static void SetInvalidTokenForTesting(const char* token);
6462

6563
static void SetLastCheckedPrefForTesting(const AccountId& account_id,
@@ -81,12 +79,18 @@ class TokenHandleUtil {
8179

8280
~TokenDelegate() override;
8381

82+
// gaia::GaiaOAuthClient::Delegate overrides.
8483
void OnOAuthError() override;
8584
void OnNetworkError(int response_code) override;
8685
void OnGetTokenInfoResponse(const base::Value::Dict& token_info) override;
87-
void NotifyDone();
86+
87+
// Completes the validation request at the owner TokenHandleUtil. The bool
88+
// flag signals if we actually got any data from the Gaia endpoint.
89+
void NotifyDone(bool request_completed);
8890

8991
private:
92+
void RecordTokenCheckResponseTime();
93+
9094
base::WeakPtr<TokenHandleUtil> owner_;
9195
AccountId account_id_;
9296
std::string token_;

components/user_manager/known_user.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ const char kOnboardingCompletedVersion[] = "onboarding_completed_version";
109109
// Last screen shown in the onboarding flow.
110110
const char kPendingOnboardingScreen[] = "onboarding_screen_pending";
111111

112+
// Key of the obsolete token handle rotation flag.
113+
const char kTokenHandleRotatedObsolete[] = "TokenHandleRotated";
114+
112115
// List containing all the known user preferences keys.
113116
const char* kReservedKeys[] = {kCanonicalEmail,
114117
kGAIAIdKey,
@@ -139,6 +142,7 @@ const char* kObsoleteKeys[] = {
139142
kMinimalMigrationAttemptedObsolete,
140143
kGaiaIdMigrationObsolete,
141144
kOfflineSigninLimitObsolete,
145+
kTokenHandleRotatedObsolete,
142146
};
143147

144148
// Checks if values in |dict| correspond with |account_id| identity.

0 commit comments

Comments
 (0)