| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/net/gaia/gaia_authenticator.h" | 5 #include "chrome/common/net/gaia/gaia_authenticator.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 } | 44 } |
| 45 | 45 |
| 46 GaiaAuthenticator::~GaiaAuthenticator() { | 46 GaiaAuthenticator::~GaiaAuthenticator() { |
| 47 delete channel_; | 47 delete channel_; |
| 48 } | 48 } |
| 49 | 49 |
| 50 // mutex_ must be entered before calling this function. | 50 // mutex_ must be entered before calling this function. |
| 51 GaiaAuthenticator::AuthParams GaiaAuthenticator::MakeParams( | 51 GaiaAuthenticator::AuthParams GaiaAuthenticator::MakeParams( |
| 52 const string& user_name, | 52 const string& user_name, |
| 53 const string& password, | 53 const string& password, |
| 54 SaveCredentials should_save_credentials, | |
| 55 const string& captcha_token, | 54 const string& captcha_token, |
| 56 const string& captcha_value, | 55 const string& captcha_value) { |
| 57 SignIn try_first) { | |
| 58 AuthParams params; | 56 AuthParams params; |
| 59 params.request_id = ++request_count_; | 57 params.request_id = ++request_count_; |
| 60 params.email = user_name; | 58 params.email = user_name; |
| 61 params.password = password; | 59 params.password = password; |
| 62 params.should_save_credentials = should_save_credentials; | |
| 63 params.captcha_token = captcha_token; | 60 params.captcha_token = captcha_token; |
| 64 params.captcha_value = captcha_value; | 61 params.captcha_value = captcha_value; |
| 65 params.authenticator = this; | 62 params.authenticator = this; |
| 66 params.try_first = try_first; | |
| 67 return params; | 63 return params; |
| 68 } | 64 } |
| 69 | 65 |
| 70 bool GaiaAuthenticator::Authenticate(const string& user_name, | 66 bool GaiaAuthenticator::Authenticate(const string& user_name, |
| 71 const string& password, | 67 const string& password, |
| 72 SaveCredentials should_save_credentials, | |
| 73 const string& captcha_token, | 68 const string& captcha_token, |
| 74 const string& captcha_value, | 69 const string& captcha_value) { |
| 75 SignIn try_first) { | |
| 76 DCHECK_EQ(MessageLoop::current(), message_loop_); | 70 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 77 | 71 |
| 78 AuthParams const params = | 72 AuthParams const params = |
| 79 MakeParams(user_name, password, should_save_credentials, captcha_token, | 73 MakeParams(user_name, password, captcha_token, captcha_value); |
| 80 captcha_value, try_first); | |
| 81 return AuthenticateImpl(params); | 74 return AuthenticateImpl(params); |
| 82 } | 75 } |
| 83 | 76 |
| 84 bool GaiaAuthenticator::AuthenticateWithLsid(const string& lsid, | 77 bool GaiaAuthenticator::AuthenticateWithLsid(const string& lsid) { |
| 85 bool long_lived) { | |
| 86 auth_results_.lsid = lsid; | 78 auth_results_.lsid = lsid; |
| 87 // We need to lookup the email associated with this LSID cookie in order to | 79 // We need to lookup the email associated with this LSID cookie in order to |
| 88 // update |auth_results_| with the correct values. | 80 // update |auth_results_| with the correct values. |
| 89 if (LookupEmail(&auth_results_)) { | 81 if (LookupEmail(&auth_results_)) { |
| 90 auth_results_.email = auth_results_.primary_email; | 82 auth_results_.email = auth_results_.primary_email; |
| 91 return IssueAuthToken(&auth_results_, service_id_, long_lived); | 83 return IssueAuthToken(&auth_results_, service_id_); |
| 92 } | 84 } |
| 93 return false; | 85 return false; |
| 94 } | 86 } |
| 95 | 87 |
| 96 | |
| 97 bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params) { | 88 bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params) { |
| 98 DCHECK_EQ(MessageLoop::current(), message_loop_); | 89 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 99 AuthResults results; | 90 AuthResults results; |
| 100 const bool succeeded = AuthenticateImpl(params, &results); | 91 const bool succeeded = AuthenticateImpl(params, &results); |
| 101 if (params.request_id == request_count_) { | 92 if (params.request_id == request_count_) { |
| 102 auth_results_ = results; | 93 auth_results_ = results; |
| 103 GaiaAuthEvent event = { succeeded ? GaiaAuthEvent::GAIA_AUTH_SUCCEEDED | 94 GaiaAuthEvent event = { succeeded ? GaiaAuthEvent::GAIA_AUTH_SUCCEEDED |
| 104 : GaiaAuthEvent::GAIA_AUTH_FAILED, | 95 : GaiaAuthEvent::GAIA_AUTH_FAILED, |
| 105 results.auth_error, this }; | 96 results.auth_error, this }; |
| 106 channel_->NotifyListeners(event); | 97 channel_->NotifyListeners(event); |
| 107 } | 98 } |
| 108 return succeeded; | 99 return succeeded; |
| 109 } | 100 } |
| 110 | 101 |
| 111 // This method makes an HTTP request to the Gaia server, and calls other | 102 // This method makes an HTTP request to the Gaia server, and calls other |
| 112 // methods to help parse the response. If authentication succeeded, then | 103 // methods to help parse the response. If authentication succeeded, then |
| 113 // Gaia-issued cookies are available in the respective variables; if | 104 // Gaia-issued cookies are available in the respective variables; if |
| 114 // authentication failed, then the exact error is available as an enum. If the | 105 // authentication failed, then the exact error is available as an enum. If the |
| 115 // client wishes to save the credentials, the last parameter must be true. | 106 // client wishes to save the credentials, the last parameter must be true. |
| 116 // If a subsequent request is made with fresh credentials, the saved credentials | 107 // If a subsequent request is made with fresh credentials, the saved credentials |
| 117 // are wiped out; any subsequent request to the zero-parameter overload of this | 108 // are wiped out; any subsequent request to the zero-parameter overload of this |
| 118 // method preserves the saved credentials. | 109 // method preserves the saved credentials. |
| 119 bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params, | 110 bool GaiaAuthenticator::AuthenticateImpl(const AuthParams& params, |
| 120 AuthResults* results) { | 111 AuthResults* results) { |
| 121 DCHECK_EQ(MessageLoop::current(), message_loop_); | 112 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 122 results->credentials_saved = params.should_save_credentials; | |
| 123 results->auth_error = ConnectionUnavailable; | 113 results->auth_error = ConnectionUnavailable; |
| 124 // Save credentials if so requested. | 114 results->email = params.email.data(); |
| 125 if (params.should_save_credentials != DONT_SAVE_CREDENTIALS) { | 115 results->password = params.password; |
| 126 results->email = params.email.data(); | |
| 127 results->password = params.password; | |
| 128 } else { // Explicitly clear previously-saved credentials. | |
| 129 results->email = ""; | |
| 130 results->password = ""; | |
| 131 } | |
| 132 | 116 |
| 133 // The aim of this code is to start failing requests if due to a logic error | 117 // The aim of this code is to start failing requests if due to a logic error |
| 134 // in the program we're hammering GAIA. | 118 // in the program we're hammering GAIA. |
| 135 #if defined(OS_WIN) | 119 #if defined(OS_WIN) |
| 136 __time32_t now = _time32(0); | 120 __time32_t now = _time32(0); |
| 137 #else // defined(OS_WIN) | 121 #else // defined(OS_WIN) |
| 138 time_t now = time(0); | 122 time_t now = time(0); |
| 139 #endif // defined(OS_WIN) | 123 #endif // defined(OS_WIN) |
| 140 | 124 |
| 141 if (now > next_allowed_auth_attempt_time_) { | 125 if (now > next_allowed_auth_attempt_time_) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 return false; | 169 return false; |
| 186 } | 170 } |
| 187 | 171 |
| 188 // Parse reply in two different ways, depending on if request failed or | 172 // Parse reply in two different ways, depending on if request failed or |
| 189 // succeeded. | 173 // succeeded. |
| 190 if (RC_FORBIDDEN == server_response_code) { | 174 if (RC_FORBIDDEN == server_response_code) { |
| 191 ExtractAuthErrorFrom(message_text, results); | 175 ExtractAuthErrorFrom(message_text, results); |
| 192 return false; | 176 return false; |
| 193 } else if (RC_REQUEST_OK == server_response_code) { | 177 } else if (RC_REQUEST_OK == server_response_code) { |
| 194 ExtractTokensFrom(message_text, results); | 178 ExtractTokensFrom(message_text, results); |
| 195 const bool old_gaia = | 179 if (!IssueAuthToken(results, service_id_)) { |
| 196 results->auth_token.empty() && !results->lsid.empty(); | |
| 197 const bool long_lived_token = | |
| 198 params.should_save_credentials == PERSIST_TO_DISK; | |
| 199 if ((old_gaia || long_lived_token) && | |
| 200 !IssueAuthToken(results, service_id_, long_lived_token)) | |
| 201 return false; | 180 return false; |
| 181 } |
| 202 | 182 |
| 203 return LookupEmail(results); | 183 return LookupEmail(results); |
| 204 } else { | 184 } else { |
| 205 results->auth_error = Unknown; | 185 results->auth_error = Unknown; |
| 206 return false; | 186 return false; |
| 207 } | 187 } |
| 208 } | 188 } |
| 209 | 189 |
| 210 bool GaiaAuthenticator::LookupEmail(AuthResults* results) { | 190 bool GaiaAuthenticator::LookupEmail(AuthResults* results) { |
| 211 DCHECK_EQ(MessageLoop::current(), message_loop_); | 191 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 233 ExtractAuthErrorFrom(message_text, results); | 213 ExtractAuthErrorFrom(message_text, results); |
| 234 return false; | 214 return false; |
| 235 } else if (RC_REQUEST_OK == server_response_code) { | 215 } else if (RC_REQUEST_OK == server_response_code) { |
| 236 typedef vector<pair<string, string> > Tokens; | 216 typedef vector<pair<string, string> > Tokens; |
| 237 Tokens tokens; | 217 Tokens tokens; |
| 238 base::SplitStringIntoKeyValuePairs(message_text, '=', '\n', &tokens); | 218 base::SplitStringIntoKeyValuePairs(message_text, '=', '\n', &tokens); |
| 239 for (Tokens::iterator i = tokens.begin(); i != tokens.end(); ++i) { | 219 for (Tokens::iterator i = tokens.begin(); i != tokens.end(); ++i) { |
| 240 if ("accountType" == i->first) { | 220 if ("accountType" == i->first) { |
| 241 // We never authenticate an email as a hosted account. | 221 // We never authenticate an email as a hosted account. |
| 242 DCHECK_EQ("GOOGLE", i->second); | 222 DCHECK_EQ("GOOGLE", i->second); |
| 243 results->signin = GMAIL_SIGNIN; | |
| 244 } else if ("email" == i->first) { | 223 } else if ("email" == i->first) { |
| 245 results->primary_email = i->second; | 224 results->primary_email = i->second; |
| 246 } | 225 } |
| 247 } | 226 } |
| 248 return true; | 227 return true; |
| 249 } | 228 } |
| 250 return false; | 229 return false; |
| 251 } | 230 } |
| 252 | 231 |
| 253 // We need to call this explicitly when we need to obtain a long-lived session | 232 // We need to call this explicitly when we need to obtain a long-lived session |
| 254 // token. | 233 // token. |
| 255 bool GaiaAuthenticator::IssueAuthToken(AuthResults* results, | 234 bool GaiaAuthenticator::IssueAuthToken(AuthResults* results, |
| 256 const string& service_id, | 235 const string& service_id) { |
| 257 bool long_lived) { | |
| 258 DCHECK_EQ(MessageLoop::current(), message_loop_); | 236 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 259 // Use the provided Gaia server, but change the path to what V1 expects. | 237 // Use the provided Gaia server, but change the path to what V1 expects. |
| 260 GURL url(gaia_url_); // Gaia server. | 238 GURL url(gaia_url_); // Gaia server. |
| 261 GURL::Replacements repl; | 239 GURL::Replacements repl; |
| 262 // Needs to stay in scope till GURL is out of scope. | 240 // Needs to stay in scope till GURL is out of scope. |
| 263 string path(kGaiaV1IssueAuthTokenPath); | 241 string path(kGaiaV1IssueAuthTokenPath); |
| 264 repl.SetPathStr(path); | 242 repl.SetPathStr(path); |
| 265 url = url.ReplaceComponents(repl); | 243 url = url.ReplaceComponents(repl); |
| 266 | 244 |
| 267 string post_body; | 245 string post_body; |
| 268 post_body += "LSID="; | 246 post_body += "LSID="; |
| 269 post_body += EscapeUrlEncodedData(results->lsid); | 247 post_body += EscapeUrlEncodedData(results->lsid); |
| 270 post_body += "&service=" + service_id; | 248 post_body += "&service=" + service_id; |
| 271 if (long_lived) { | 249 post_body += "&Session=true"; |
| 272 post_body += "&Session=true"; | |
| 273 } | |
| 274 | 250 |
| 275 unsigned long server_response_code; | 251 unsigned long server_response_code; |
| 276 string message_text; | 252 string message_text; |
| 277 if (!Post(url, post_body, &server_response_code, &message_text)) { | 253 if (!Post(url, post_body, &server_response_code, &message_text)) { |
| 278 return false; | 254 return false; |
| 279 } | 255 } |
| 280 | 256 |
| 281 // Check if we received a valid AuthToken; if not, ignore it. | 257 // Check if we received a valid AuthToken; if not, ignore it. |
| 282 if (RC_FORBIDDEN == server_response_code) { | 258 if (RC_FORBIDDEN == server_response_code) { |
| 283 // Server says we're not authenticated. | 259 // Server says we're not authenticated. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 void GaiaAuthenticator::SetUsername(const string& username) { | 352 void GaiaAuthenticator::SetUsername(const string& username) { |
| 377 DCHECK_EQ(MessageLoop::current(), message_loop_); | 353 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 378 auth_results_.email = username; | 354 auth_results_.email = username; |
| 379 } | 355 } |
| 380 | 356 |
| 381 void GaiaAuthenticator::RenewAuthToken(const string& auth_token) { | 357 void GaiaAuthenticator::RenewAuthToken(const string& auth_token) { |
| 382 DCHECK_EQ(MessageLoop::current(), message_loop_); | 358 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 383 DCHECK(!this->auth_token().empty()); | 359 DCHECK(!this->auth_token().empty()); |
| 384 auth_results_.auth_token = auth_token; | 360 auth_results_.auth_token = auth_token; |
| 385 } | 361 } |
| 386 void GaiaAuthenticator::SetAuthToken(const string& auth_token, | 362 void GaiaAuthenticator::SetAuthToken(const string& auth_token) { |
| 387 SaveCredentials save) { | |
| 388 DCHECK_EQ(MessageLoop::current(), message_loop_); | 363 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 389 auth_results_.auth_token = auth_token; | 364 auth_results_.auth_token = auth_token; |
| 390 auth_results_.credentials_saved = save; | |
| 391 } | 365 } |
| 392 | 366 |
| 393 bool GaiaAuthenticator::Authenticate(const string& user_name, | 367 bool GaiaAuthenticator::Authenticate(const string& user_name, |
| 394 const string& password, | 368 const string& password) { |
| 395 SaveCredentials should_save_credentials, | |
| 396 SignIn try_first) { | |
| 397 DCHECK_EQ(MessageLoop::current(), message_loop_); | 369 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 398 const string empty; | 370 const string empty; |
| 399 return Authenticate(user_name, password, should_save_credentials, empty, | 371 return Authenticate(user_name, password, empty, |
| 400 empty, try_first); | 372 empty); |
| 401 } | 373 } |
| 402 | 374 |
| 403 } // namepace gaia | 375 } // namepace gaia |
| 404 | 376 |
| OLD | NEW |