1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/sync/signin_manager.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h" 8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/net/gaia/token_service.h" 9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/prefs/pref_service.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/net/gaia/gaia_constants.h" 12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/pref_names.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char kGetInfoEmailKey[] = "email"; 16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 17731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSigninManager::SigninManager() 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : profile_(NULL), had_two_factor_error_(false) {} 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 20731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSigninManager::~SigninManager() {} 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::RegisterUserPrefs(PrefService* user_prefs) { 24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, ""); 25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::Initialize(Profile* profile) { 28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_ = profile; 29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen username_ = profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername); 30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->Initialize( 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GaiaConstants::kChromeSource, profile_); 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!username_.empty()) { 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->LoadTokensFromDB(); 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// If a username already exists, the user is logged in. 38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst std::string& SigninManager::GetUsername() { 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return username_; 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::SetUsername(const std::string& username) { 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen username_ = username; 44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Users must always sign out before they sign in again. 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::StartSignIn(const std::string& username, 48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const std::string& password, 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const std::string& login_token, 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const std::string& login_captcha) { 51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(username_.empty()); 52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if !defined(OS_CHROMEOS) 53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The Sign out should clear the token service credentials. 54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Note: In CHROMEOS we might have valid credentials but still need to 55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // set up 2-factor authentication. 56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(!profile_->GetTokenService()->AreCredentialsValid()); 57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif 58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen username_.assign(username); 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen password_.assign(password); 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch client_login_.reset(new GaiaAuthFetcher(this, 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GaiaConstants::kChromeSource, 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch profile_->GetRequestContext())); 64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen client_login_->StartClientLogin(username, 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen password, 66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen "", 67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen login_token, 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick login_captcha, 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GaiaAuthFetcher::HostedAccountsNotAllowed); 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SigninManager::ProvideSecondFactorAccessCode( 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& access_code) { 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!username_.empty() && !password_.empty() && 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick last_result_.data.empty()); 76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch client_login_.reset(new GaiaAuthFetcher(this, 784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GaiaConstants::kChromeSource, 794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch profile_->GetRequestContext())); 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick client_login_->StartClientLogin(username_, 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick access_code, 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick "", 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string(), 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string(), 854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch GaiaAuthFetcher::HostedAccountsNotAllowed); 86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::SignOut() { 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!profile_) 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen client_login_.reset(); 93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen last_result_ = ClientLoginResult(); 94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen username_.clear(); 95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen password_.clear(); 96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick had_two_factor_error_ = false; 97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); 98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetPrefs()->ScheduleSavePersistentPrefs(); 99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->ResetCredentialsInMemory(); 100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->EraseTokensFromDB(); 101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) { 104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen last_result_ = result; 105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Make a request for the canonical email address. 106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey); 107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::OnGetUserInfoSuccess(const std::string& key, 110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const std::string& value) { 111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(key == kGetInfoEmailKey); 112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen username_ = value; 114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); 115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetPrefs()->ScheduleSavePersistentPrefs(); 116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GoogleServiceSigninSuccessDetails details(username_, password_); 118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationService::current()->Notify( 119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::GOOGLE_SIGNIN_SUCCESSFUL, 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Source<Profile>(profile_), 121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen Details<const GoogleServiceSigninSuccessDetails>(&details)); 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen password_.clear(); // Don't need it anymore. 124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->UpdateCredentials(last_result_); 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(profile_->GetTokenService()->AreCredentialsValid()); 127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile_->GetTokenService()->StartFetchingTokens(); 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) { 131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(key == kGetInfoEmailKey); 132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen LOG(ERROR) << "Account is not associated with a valid email address. " 133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen << "Login failed."; 134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen OnClientLoginFailure(GoogleServiceAuthError( 135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) { 139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen LOG(ERROR) << "Unable to retreive the canonical email address. Login failed."; 140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen OnClientLoginFailure(error); 141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) { 144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationService::current()->Notify( 145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationType::GOOGLE_SIGNIN_FAILED, 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Source<Profile>(profile_), 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Details<const GoogleServiceAuthError>(&error)); 148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We don't sign-out if the password was valid and we're just dealing with 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // a second factor error, and we don't sign out if we're dealing with 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // an invalid access code (again, because the password was valid). 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool invalid_gaia = error.state() == 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS; 154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (error.state() == GoogleServiceAuthError::TWO_FACTOR || 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (had_two_factor_error_ && invalid_gaia)) { 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick had_two_factor_error_ = true; 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen SignOut(); 161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 162