1 // Copyright 2014 The Chromium 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.
5 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
10 #include "base/bind_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/time/clock.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/chromeos/login/reauth_stats.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/pref_names.h"
20 #include "components/pref_registry/pref_registry_syncable.h"
21 #include "components/user_manager/user.h"
22 #include "components/user_manager/user_manager.h"
28 const int kDefaultSAMLOfflineSigninTimeLimit
= 14 * 24 * 60 * 60; // 14 days.
33 void SAMLOfflineSigninLimiter::RegisterProfilePrefs(
34 user_prefs::PrefRegistrySyncable
* registry
) {
35 registry
->RegisterIntegerPref(prefs::kSAMLOfflineSigninTimeLimit
,
36 kDefaultSAMLOfflineSigninTimeLimit
);
37 registry
->RegisterInt64Pref(prefs::kSAMLLastGAIASignInTime
, 0);
40 void SAMLOfflineSigninLimiter::SignedIn(UserContext::AuthFlow auth_flow
) {
41 PrefService
* prefs
= profile_
->GetPrefs();
42 const user_manager::User
* user
=
43 ProfileHelper::Get()->GetUserByProfile(profile_
);
48 const std::string
& user_id
= user
->email();
50 if (auth_flow
== UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML
) {
51 // The user went through online authentication and GAIA did not redirect to
52 // a SAML IdP. No limit applies in this case. Clear the time of last login
53 // with SAML and the flag enforcing online login, then return.
54 prefs
->ClearPref(prefs::kSAMLLastGAIASignInTime
);
55 user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id
, false);
59 if (auth_flow
== UserContext::AUTH_FLOW_GAIA_WITH_SAML
) {
60 // The user went through online authentication and GAIA did redirect to a
61 // SAML IdP. Update the time of last login with SAML and clear the flag
62 // enforcing online login. The flag will be set again when the limit
63 // expires. If the limit already expired (e.g. because it was set to zero),
64 // the flag will be set again immediately.
65 user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id
, false);
66 prefs
->SetInt64(prefs::kSAMLLastGAIASignInTime
,
67 clock_
->Now().ToInternalValue());
70 // Start listening for pref changes.
71 pref_change_registrar_
.Init(prefs
);
72 pref_change_registrar_
.Add(prefs::kSAMLOfflineSigninTimeLimit
,
73 base::Bind(&SAMLOfflineSigninLimiter::UpdateLimit
,
74 base::Unretained(this)));
76 // Arm the |offline_signin_limit_timer_| if a limit is in force.
80 void SAMLOfflineSigninLimiter::Shutdown() {
81 pref_change_registrar_
.RemoveAll();
82 offline_signin_limit_timer_
.reset();
85 SAMLOfflineSigninLimiter::SAMLOfflineSigninLimiter(Profile
* profile
,
88 clock_(clock
? clock
: &default_clock_
) {
91 SAMLOfflineSigninLimiter::~SAMLOfflineSigninLimiter() {
94 void SAMLOfflineSigninLimiter::UpdateLimit() {
95 // Stop the |offline_signin_limit_timer_|.
96 offline_signin_limit_timer_
.reset();
98 PrefService
* prefs
= pref_change_registrar_
.prefs();
99 const base::TimeDelta offline_signin_time_limit
=
100 base::TimeDelta::FromSeconds(
101 prefs
->GetInteger(prefs::kSAMLOfflineSigninTimeLimit
));
102 base::Time last_gaia_signin_time
= base::Time::FromInternalValue(
103 prefs
->GetInt64(prefs::kSAMLLastGAIASignInTime
));
104 if (offline_signin_time_limit
< base::TimeDelta() ||
105 last_gaia_signin_time
.is_null()) {
106 // If no limit is in force, return.
110 const base::Time now
= clock_
->Now();
111 if (last_gaia_signin_time
> now
) {
112 // If the time of last login with SAML lies in the future, set it to the
115 last_gaia_signin_time
= now
;
116 prefs
->SetInt64(prefs::kSAMLLastGAIASignInTime
, now
.ToInternalValue());
119 const base::TimeDelta time_since_last_gaia_signin
=
120 now
- last_gaia_signin_time
;
121 if (time_since_last_gaia_signin
>= offline_signin_time_limit
) {
122 // If the limit already expired, set the flag enforcing online login
123 // immediately and return.
128 // Arm |offline_signin_limit_timer_| so that it sets the flag enforcing online
129 // login when the limit expires.
130 offline_signin_limit_timer_
.reset(
131 new base::OneShotTimer
<SAMLOfflineSigninLimiter
>);
132 offline_signin_limit_timer_
->Start(
134 offline_signin_time_limit
- time_since_last_gaia_signin
,
136 &SAMLOfflineSigninLimiter::ForceOnlineLogin
);
139 void SAMLOfflineSigninLimiter::ForceOnlineLogin() {
140 const user_manager::User
* user
=
141 ProfileHelper::Get()->GetUserByProfile(profile_
);
147 user_manager::UserManager::Get()->SaveForceOnlineSignin(user
->email(), true);
148 RecordReauthReason(user
->email(), ReauthReason::SAML_REAUTH_POLICY
);
149 offline_signin_limit_timer_
.reset();
152 } // namespace chromeos