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 |