15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind_helpers.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/prefs/pref_service.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/clock.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/profiles/profile_helper.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/pref_names.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user.h" 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace chromeos { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kDefaultSAMLOfflineSigninTimeLimit = 14 * 24 * 60 * 60; // 14 days. 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SAMLOfflineSigninLimiter::RegisterProfilePrefs( 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterIntegerPref( 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kSAMLOfflineSigninTimeLimit, 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kDefaultSAMLOfflineSigninTimeLimit, 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterInt64Pref( 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs::kSAMLLastGAIASignInTime, 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SAMLOfflineSigninLimiter::SignedIn(UserContext::AuthFlow auth_flow) { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* prefs = profile_->GetPrefs(); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const user_manager::User* user = 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ProfileHelper::Get()->GetUserByProfile(profile_); 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!user) { 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& user_id = user->email(); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML) { 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The user went through online authentication and GAIA did not redirect to 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // a SAML IdP. No limit applies in this case. Clear the time of last login 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // with SAML and the flag enforcing online login, then return. 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->ClearPref(prefs::kSAMLLastGAIASignInTime); 596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id, false); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (auth_flow == UserContext::AUTH_FLOW_GAIA_WITH_SAML) { 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The user went through online authentication and GAIA did redirect to a 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // SAML IdP. Update the time of last login with SAML and clear the flag 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // enforcing online login. The flag will be set again when the limit 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // expires. If the limit already expired (e.g. because it was set to zero), 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the flag will be set again immediately. 696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager::Get()->SaveForceOnlineSignin(user_id, false); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->SetInt64(prefs::kSAMLLastGAIASignInTime, 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) clock_->Now().ToInternalValue()); 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Start listening for pref changes. 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_change_registrar_.Init(prefs); 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_change_registrar_.Add(prefs::kSAMLOfflineSigninTimeLimit, 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&SAMLOfflineSigninLimiter::UpdateLimit, 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this))); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Arm the |offline_signin_limit_timer_| if a limit is in force. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateLimit(); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SAMLOfflineSigninLimiter::Shutdown() { 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_change_registrar_.RemoveAll(); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_limit_timer_.reset(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SAMLOfflineSigninLimiter::SAMLOfflineSigninLimiter(Profile* profile, 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Clock* clock) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) clock_(clock ? clock : &default_clock_) { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SAMLOfflineSigninLimiter::~SAMLOfflineSigninLimiter() { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SAMLOfflineSigninLimiter::UpdateLimit() { 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Stop the |offline_signin_limit_timer_|. 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_limit_timer_.reset(); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* prefs = pref_change_registrar_.prefs(); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::TimeDelta offline_signin_time_limit = 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta::FromSeconds( 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->GetInteger(prefs::kSAMLOfflineSigninTimeLimit)); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time last_gaia_signin_time = base::Time::FromInternalValue( 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->GetInt64(prefs::kSAMLLastGAIASignInTime)); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (offline_signin_time_limit < base::TimeDelta() || 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_gaia_signin_time.is_null()) { 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If no limit is in force, return. 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Time now = clock_->Now(); 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (last_gaia_signin_time > now) { 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the time of last login with SAML lies in the future, set it to the 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // current time. 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_gaia_signin_time = now; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prefs->SetInt64(prefs::kSAMLLastGAIASignInTime, now.ToInternalValue()); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::TimeDelta time_since_last_gaia_signin = 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) now - last_gaia_signin_time; 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (time_since_last_gaia_signin >= offline_signin_time_limit) { 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the limit already expired, set the flag enforcing online login 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // immediately and return. 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ForceOnlineLogin(); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Arm |offline_signin_limit_timer_| so that it sets the flag enforcing online 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // login when the limit expires. 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_limit_timer_.reset( 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new base::OneShotTimer<SAMLOfflineSigninLimiter>); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_limit_timer_->Start( 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_time_limit - time_since_last_gaia_signin, 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this, 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &SAMLOfflineSigninLimiter::ForceOnlineLogin); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SAMLOfflineSigninLimiter::ForceOnlineLogin() { 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile_); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!user) { 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) user_manager::UserManager::Get()->SaveForceOnlineSignin(user->email(), true); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offline_signin_limit_timer_.reset(); 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace chromeos 155