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 "chromeos/login/auth/login_performer.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/user_metrics.h"
12 #include "base/metrics/user_metrics_action.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "chromeos/dbus/session_manager_client.h"
18 #include "chromeos/login/user_names.h"
19 #include "chromeos/login_event_recorder.h"
20 #include "chromeos/settings/cros_settings_names.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
22 #include "net/cookies/cookie_monster.h"
23 #include "net/cookies/cookie_store.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_getter.h"
27 using base::UserMetricsAction
;
31 LoginPerformer::LoginPerformer(scoped_refptr
<base::TaskRunner
> task_runner
,
33 bool disable_client_login
)
34 : delegate_(delegate
),
35 task_runner_(task_runner
),
36 online_attempt_host_(this),
37 last_login_failure_(AuthFailure::AuthFailureNone()),
38 password_changed_(false),
39 password_changed_callback_count_(0),
40 auth_mode_(AUTH_MODE_INTERNAL
),
41 disable_client_login_(disable_client_login
),
45 LoginPerformer::~LoginPerformer() {
46 DVLOG(1) << "Deleting LoginPerformer";
47 if (authenticator_
.get())
48 authenticator_
->SetConsumer(NULL
);
49 if (extended_authenticator_
.get())
50 extended_authenticator_
->SetConsumer(NULL
);
53 ////////////////////////////////////////////////////////////////////////////////
54 // LoginPerformer, AuthStatusConsumer implementation:
56 void LoginPerformer::OnAuthFailure(const AuthFailure
& failure
) {
57 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
58 base::RecordAction(UserMetricsAction("Login_Failure"));
60 UMA_HISTOGRAM_ENUMERATION("Login.FailureReason",
62 AuthFailure::NUM_FAILURE_REASONS
);
64 DVLOG(1) << "failure.reason " << failure
.reason();
65 DVLOG(1) << "failure.error.state " << failure
.error().state();
67 last_login_failure_
= failure
;
69 delegate_
->OnAuthFailure(failure
);
72 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
73 // happens during offline auth only.
78 void LoginPerformer::OnAuthSuccess(const UserContext
& user_context
) {
79 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
80 base::RecordAction(UserMetricsAction("Login_Success"));
81 VLOG(1) << "LoginSuccess hash: " << user_context
.GetUserIDHash();
83 // After delegate_->OnAuthSuccess(...) is called, delegate_ releases
84 // LoginPerformer ownership. LP now manages it's lifetime on its own.
85 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
86 delegate_
->OnAuthSuccess(user_context
);
89 void LoginPerformer::OnOffTheRecordAuthSuccess() {
90 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
91 base::RecordAction(UserMetricsAction("Login_GuestLoginSuccess"));
94 delegate_
->OnOffTheRecordAuthSuccess();
99 void LoginPerformer::OnPasswordChangeDetected() {
100 password_changed_
= true;
101 password_changed_callback_count_
++;
103 delegate_
->OnPasswordChangeDetected();
109 void LoginPerformer::OnChecked(const std::string
& user_id
, bool success
) {
111 // Delegate is reset in case of successful offline login.
112 // See ExistingUserConstoller::OnAuthSuccess().
113 // Case when user has changed password and enters old password
114 // does not block user from sign in yet.
117 delegate_
->OnOnlineChecked(user_id
, success
);
120 ////////////////////////////////////////////////////////////////////////////////
121 // LoginPerformer, public:
123 void LoginPerformer::NotifyWhitelistCheckFailure() {
125 delegate_
->WhiteListCheckFailed(user_context_
.GetUserID());
130 void LoginPerformer::PerformLogin(const UserContext
& user_context
,
131 AuthorizationMode auth_mode
) {
132 auth_mode_
= auth_mode
;
133 user_context_
= user_context
;
135 if (RunTrustedCheck(base::Bind(&LoginPerformer::DoPerformLogin
,
136 weak_factory_
.GetWeakPtr(),
141 DoPerformLogin(user_context_
, auth_mode
);
144 void LoginPerformer::DoPerformLogin(const UserContext
& user_context
,
145 AuthorizationMode auth_mode
) {
146 std::string email
= gaia::CanonicalizeEmail(user_context
.GetUserID());
147 bool wildcard_match
= false;
149 if (!IsUserWhitelisted(email
, &wildcard_match
)) {
150 NotifyWhitelistCheckFailure();
154 if (user_context
.GetAuthFlow() == UserContext::AUTH_FLOW_EASY_UNLOCK
)
155 SetupEasyUnlockUserFlow(user_context
.GetUserID());
157 switch (auth_mode_
) {
158 case AUTH_MODE_EXTENSION
: {
159 RunOnlineWhitelistCheck(
160 email
, wildcard_match
, user_context
.GetRefreshToken(),
161 base::Bind(&LoginPerformer::StartLoginCompletion
,
162 weak_factory_
.GetWeakPtr()),
163 base::Bind(&LoginPerformer::NotifyWhitelistCheckFailure
,
164 weak_factory_
.GetWeakPtr()));
167 case AUTH_MODE_INTERNAL
:
168 StartAuthentication();
173 void LoginPerformer::LoginAsSupervisedUser(const UserContext
& user_context
) {
174 DCHECK_EQ(chromeos::login::kSupervisedUserDomain
,
175 gaia::ExtractDomainName(user_context
.GetUserID()));
177 user_context_
= user_context
;
178 user_context_
.SetUserType(user_manager::USER_TYPE_SUPERVISED
);
180 if (RunTrustedCheck(base::Bind(&LoginPerformer::TrustedLoginAsSupervisedUser
,
181 weak_factory_
.GetWeakPtr(),
185 TrustedLoginAsSupervisedUser(user_context_
);
188 void LoginPerformer::TrustedLoginAsSupervisedUser(
189 const UserContext
& user_context
) {
190 if (!AreSupervisedUsersAllowed()) {
191 LOG(ERROR
) << "Login attempt of supervised user detected.";
192 delegate_
->WhiteListCheckFailed(user_context
.GetUserID());
196 SetupSupervisedUserFlow(user_context
.GetUserID());
197 UserContext user_context_copy
= TransformSupervisedKey(user_context
);
199 if (UseExtendedAuthenticatorForSupervisedUser(user_context
)) {
200 EnsureExtendedAuthenticator();
201 // TODO(antrim) : Replace empty callback with explicit method.
202 // http://crbug.com/351268
203 task_runner_
->PostTask(
205 base::Bind(&ExtendedAuthenticator::AuthenticateToMount
,
206 extended_authenticator_
.get(),
208 ExtendedAuthenticator::ResultCallback()));
211 EnsureAuthenticator();
212 task_runner_
->PostTask(FROM_HERE
,
213 base::Bind(&Authenticator::LoginAsSupervisedUser
,
214 authenticator_
.get(),
219 void LoginPerformer::LoginAsPublicSession(const UserContext
& user_context
) {
220 if (!CheckPolicyForUser(user_context
.GetUserID())) {
223 delegate_
->PolicyLoadFailed();
227 EnsureAuthenticator();
228 task_runner_
->PostTask(FROM_HERE
,
229 base::Bind(&Authenticator::LoginAsPublicSession
,
230 authenticator_
.get(),
234 void LoginPerformer::LoginOffTheRecord() {
235 EnsureAuthenticator();
236 task_runner_
->PostTask(
238 base::Bind(&Authenticator::LoginOffTheRecord
, authenticator_
.get()));
241 void LoginPerformer::LoginAsKioskAccount(const std::string
& app_user_id
,
242 bool use_guest_mount
) {
243 EnsureAuthenticator();
244 task_runner_
->PostTask(FROM_HERE
,
245 base::Bind(&Authenticator::LoginAsKioskAccount
,
246 authenticator_
.get(),
251 void LoginPerformer::RecoverEncryptedData(const std::string
& old_password
) {
252 task_runner_
->PostTask(FROM_HERE
,
253 base::Bind(&Authenticator::RecoverEncryptedData
,
254 authenticator_
.get(),
258 void LoginPerformer::ResyncEncryptedData() {
259 task_runner_
->PostTask(
261 base::Bind(&Authenticator::ResyncEncryptedData
, authenticator_
.get()));
264 ////////////////////////////////////////////////////////////////////////////////
265 // LoginPerformer, private:
267 void LoginPerformer::EnsureExtendedAuthenticator() {
268 if (extended_authenticator_
.get())
269 extended_authenticator_
->SetConsumer(NULL
);
270 extended_authenticator_
= ExtendedAuthenticator::Create(this);
273 void LoginPerformer::StartLoginCompletion() {
274 DVLOG(1) << "Login completion started";
275 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
276 content::BrowserContext
* browser_context
= GetSigninContext();
277 EnsureAuthenticator();
278 task_runner_
->PostTask(FROM_HERE
,
279 base::Bind(&chromeos::Authenticator::CompleteLogin
,
280 authenticator_
.get(),
283 user_context_
.ClearSecrets();
286 void LoginPerformer::StartAuthentication() {
287 DVLOG(1) << "Auth started";
288 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false);
290 EnsureAuthenticator();
291 content::BrowserContext
* browser_context
= GetSigninContext();
292 task_runner_
->PostTask(FROM_HERE
,
293 base::Bind(&Authenticator::AuthenticateToLogin
,
294 authenticator_
.get(),
295 base::Unretained(browser_context
),
297 if (!disable_client_login_
) {
298 // Make unobtrusive online check. It helps to determine password change
299 // state in the case when offline login fails.
300 online_attempt_host_
.Check(GetSigninRequestContext(), user_context_
);
305 user_context_
.ClearSecrets();
308 void LoginPerformer::EnsureAuthenticator() {
309 authenticator_
= CreateAuthenticator();
311 } // namespace chromeos