Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: chrome/common/net/gaia/gaia_authenticator2.cc

Issue 2834042: Add IssueAuthToken and unit tests to GaiaAuthenticator2. (Closed)
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_authenticator2.h" 5 #include "chrome/common/net/gaia/gaia_authenticator2.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/string_split.h" 9 #include "base/string_split.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 16 matching lines...) Expand all
27 // static 27 // static
28 const char GaiaAuthenticator2::kClientLoginCaptchaFormat[] = 28 const char GaiaAuthenticator2::kClientLoginCaptchaFormat[] =
29 "Email=%s&" 29 "Email=%s&"
30 "Passwd=%s&" 30 "Passwd=%s&"
31 "PersistentCookie=%s&" 31 "PersistentCookie=%s&"
32 "accountType=%s&" 32 "accountType=%s&"
33 "source=%s&" 33 "source=%s&"
34 "service=%s&" 34 "service=%s&"
35 "logintoken=%s&" 35 "logintoken=%s&"
36 "logincaptcha=%s"; 36 "logincaptcha=%s";
37 // static
38 const char GaiaAuthenticator2::kIssueAuthTokenFormat[] =
39 "SID=%s&"
40 "LSID=%s&"
41 "service=%s&"
42 "Session=true";
37 43
38 // static 44 // static
39 const char GaiaAuthenticator2::kCookiePersistence[] = "true"; 45 const char GaiaAuthenticator2::kCookiePersistence[] = "true";
40 // static 46 // static
41 const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE"; 47 const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE";
42 // static 48 // static
43 const char GaiaAuthenticator2::kChromeOSSource[] = "chromeos"; 49 const char GaiaAuthenticator2::kChromeOSSource[] = "chromeos";
44 // static 50 // static
45 // Service name for Gaia Contacts API. API is used to get user's image. 51 // Service name for Gaia Contacts API. API is used to get user's image.
46 const char GaiaAuthenticator2::kContactsService[] = "cp"; 52 const char GaiaAuthenticator2::kContactsService[] = "cp";
47 // static 53 // static
48 const char GaiaAuthenticator2::kSecondFactor[] = "Info=InvalidSecondFactor"; 54 const char GaiaAuthenticator2::kSecondFactor[] = "Info=InvalidSecondFactor";
49 55
50 // TODO(chron): These urls are also in auth_response_handler.h. 56 // TODO(chron): These urls are also in auth_response_handler.h.
51 // The URLs for different calls in the Google Accounts programmatic login API. 57 // The URLs for different calls in the Google Accounts programmatic login API.
52 const char GaiaAuthenticator2::kClientLoginUrl[] = 58 const char GaiaAuthenticator2::kClientLoginUrl[] =
53 "https://www.google.com/accounts/ClientLogin"; 59 "https://www.google.com/accounts/ClientLogin";
54 const char GaiaAuthenticator2::kIssueAuthTokenUrl[] = 60 const char GaiaAuthenticator2::kIssueAuthTokenUrl[] =
55 "https://www.google.com/accounts/IssueAuthToken"; 61 "https://www.google.com/accounts/IssueAuthToken";
56 // TODO(chron): Fix this URL not to hardcode source
57 // TODO(cmasone): make sure that using an http:// URL in the "continue"
58 // parameter here doesn't open the system up to attack long-term.
59 const char GaiaAuthenticator2::kTokenAuthUrl[] =
60 "https://www.google.com/accounts/TokenAuth?"
61 "continue=http://www.google.com/webhp&source=chromeos&auth=";
62 62
63 GaiaAuthenticator2::GaiaAuthenticator2(GaiaAuthConsumer* consumer, 63 GaiaAuthenticator2::GaiaAuthenticator2(GaiaAuthConsumer* consumer,
64 const std::string& source, 64 const std::string& source,
65 URLRequestContextGetter* getter) 65 URLRequestContextGetter* getter)
66 : consumer_(consumer), 66 : consumer_(consumer),
67 getter_(getter), 67 getter_(getter),
68 source_(source), 68 source_(source),
69 client_login_gurl_(kClientLoginUrl), 69 client_login_gurl_(kClientLoginUrl),
70 fetch_pending_(false){} 70 issue_auth_token_gurl_(kIssueAuthTokenUrl),
71 fetch_pending_(false) {}
71 72
72 GaiaAuthenticator2::~GaiaAuthenticator2() {} 73 GaiaAuthenticator2::~GaiaAuthenticator2() {}
73 74
74 bool GaiaAuthenticator2::HasPendingFetch() { 75 bool GaiaAuthenticator2::HasPendingFetch() {
75 return fetch_pending_; 76 return fetch_pending_;
76 } 77 }
77 78
78 void GaiaAuthenticator2::CancelRequest() { 79 void GaiaAuthenticator2::CancelRequest() {
79 fetcher_.reset(); 80 fetcher_.reset();
80 fetch_pending_ = false; 81 fetch_pending_ = false;
81 } 82 }
82 83
83 // static 84 // static
84 URLFetcher* GaiaAuthenticator2::CreateClientLoginFetcher( 85 URLFetcher* GaiaAuthenticator2::CreateGaiaFetcher(
85 URLRequestContextGetter* getter, 86 URLRequestContextGetter* getter,
86 const std::string& body, 87 const std::string& body,
87 const GURL& client_login_gurl, 88 const GURL& gaia_gurl,
88 URLFetcher::Delegate* delegate) { 89 URLFetcher::Delegate* delegate) {
89 90
90 URLFetcher* to_return = 91 URLFetcher* to_return =
91 URLFetcher::Create(0, 92 URLFetcher::Create(0,
92 client_login_gurl, 93 gaia_gurl,
93 URLFetcher::POST, 94 URLFetcher::POST,
94 delegate); 95 delegate);
95 to_return->set_request_context(getter); 96 to_return->set_request_context(getter);
96 to_return->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES); 97 to_return->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
97 to_return->set_upload_data("application/x-www-form-urlencoded", body); 98 to_return->set_upload_data("application/x-www-form-urlencoded", body);
98 return to_return; 99 return to_return;
99 } 100 }
100 101
101 std::string GaiaAuthenticator2::GenerateRequestBody( 102 // static
103 std::string GaiaAuthenticator2::MakeClientLoginBody(
102 const std::string& username, 104 const std::string& username,
103 const std::string& password, 105 const std::string& password,
104 const std::string& source, 106 const std::string& source,
105 const char* service, 107 const char* service,
106 const std::string& login_token, 108 const std::string& login_token,
107 const std::string& login_captcha) { 109 const std::string& login_captcha) {
108 110
109 if (login_token.empty() || login_captcha.empty()) { 111 if (login_token.empty() || login_captcha.empty()) {
110 return StringPrintf(kClientLoginFormat, 112 return StringPrintf(kClientLoginFormat,
111 UrlEncodeString(username).c_str(), 113 UrlEncodeString(username).c_str(),
112 UrlEncodeString(password).c_str(), 114 UrlEncodeString(password).c_str(),
113 kCookiePersistence, 115 kCookiePersistence,
114 kAccountType, 116 kAccountType,
115 source.c_str(), 117 source.c_str(),
116 service); 118 service);
117 } 119 }
118 120
119 return StringPrintf(kClientLoginCaptchaFormat, 121 return StringPrintf(kClientLoginCaptchaFormat,
120 UrlEncodeString(username).c_str(), 122 UrlEncodeString(username).c_str(),
121 UrlEncodeString(password).c_str(), 123 UrlEncodeString(password).c_str(),
122 kCookiePersistence, 124 kCookiePersistence,
123 kAccountType, 125 kAccountType,
124 source.c_str(), 126 source.c_str(),
125 service, 127 service,
126 UrlEncodeString(login_token).c_str(), 128 UrlEncodeString(login_token).c_str(),
127 UrlEncodeString(login_captcha).c_str()); 129 UrlEncodeString(login_captcha).c_str());
128 130
129 } 131 }
130 132
131 // Helper method that extracts tokens from a successful reply, and saves them 133 // static
132 // in the right fields. 134 std::string GaiaAuthenticator2::MakeIssueAuthTokenBody(
135 const std::string& sid,
136 const std::string& lsid,
137 const char* const service) {
138
139 return StringPrintf(kIssueAuthTokenFormat,
140 UrlEncodeString(sid).c_str(),
141 UrlEncodeString(lsid).c_str(),
142 service);
143 }
144
145 // Helper method that extracts tokens from a successful reply.
133 // static 146 // static
134 void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data, 147 void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data,
135 std::string* sid, 148 std::string* sid,
136 std::string* lsid, 149 std::string* lsid,
137 std::string* token) { 150 std::string* token) {
138 using std::vector; 151 using std::vector;
139 using std::pair; 152 using std::pair;
140 using std::string; 153 using std::string;
141 154
142 vector<pair<string, string> > tokens; 155 vector<pair<string, string> > tokens;
143 base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); 156 base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
144 for (vector<pair<string, string> >::iterator i = tokens.begin(); 157 for (vector<pair<string, string> >::iterator i = tokens.begin();
145 i != tokens.end(); ++i) { 158 i != tokens.end(); ++i) {
146 if (i->first == "SID") { 159 if (i->first == "SID") {
147 sid->assign(i->second); 160 sid->assign(i->second);
148 } else if (i->first == "LSID") { 161 } else if (i->first == "LSID") {
149 lsid->assign(i->second); 162 lsid->assign(i->second);
150 } else if (i->first == "Auth") { 163 } else if (i->first == "Auth") {
151 token->assign(i->second); 164 token->assign(i->second);
152 } 165 }
153 } 166 }
154 } 167 }
155 168
156 void GaiaAuthenticator2::StartClientLogin(const std::string& username, 169 void GaiaAuthenticator2::StartClientLogin(const std::string& username,
157 const std::string& password, 170 const std::string& password,
158 const char* service, 171 const char* const service,
159 const std::string& login_token, 172 const std::string& login_token,
160 const std::string& login_captcha) { 173 const std::string& login_captcha) {
161 174
175 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
176
162 // This class is thread agnostic, so be sure to call this only on the 177 // This class is thread agnostic, so be sure to call this only on the
163 // same thread each time. 178 // same thread each time.
164 LOG(INFO) << "Starting new ClientLogin fetch."; 179 LOG(INFO) << "Starting new ClientLogin fetch for:" << username;
165 180
166 // Must outlive fetcher_. 181 // Must outlive fetcher_.
167 request_body_ = GenerateRequestBody(username, 182 request_body_ = MakeClientLoginBody(username,
168 password, 183 password,
169 source_, 184 source_,
170 service, 185 service,
171 login_token, 186 login_token,
172 login_captcha); 187 login_captcha);
173 188 fetcher_.reset(CreateGaiaFetcher(getter_,
174 fetcher_.reset(CreateClientLoginFetcher(getter_, 189 request_body_,
175 request_body_, 190 client_login_gurl_,
176 client_login_gurl_, 191 this));
177 this));
178 fetch_pending_ = true; 192 fetch_pending_ = true;
179 fetcher_->Start(); 193 fetcher_->Start();
180 } 194 }
181 195
182 void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data, 196 void GaiaAuthenticator2::StartIssueAuthToken(const std::string& sid,
183 const URLRequestStatus& status, 197 const std::string& lsid,
184 int response_code) { 198 const char* const service) {
185 199
186 if (status.is_success() && response_code == RC_REQUEST_OK) { 200 DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
187 LOG(INFO) << "ClientLogin successful!";
188 std::string sid;
189 std::string lsid;
190 std::string token;
191 ParseClientLoginResponse(data, &sid, &lsid, &token);
192 consumer_->OnClientLoginSuccess(
193 GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data));
194 return;
195 }
196 201
197 GaiaAuthConsumer::ClientLoginError error; 202 LOG(INFO) << "Starting IssueAuthToken for: " << service;
203 requested_service_ = service;
204 request_body_ = MakeIssueAuthTokenBody(sid, lsid, service);
205 fetcher_.reset(CreateGaiaFetcher(getter_,
206 request_body_,
207 issue_auth_token_gurl_,
208 this));
209 fetch_pending_ = true;
210 fetcher_->Start();
211 }
212
213 GaiaAuthConsumer::GaiaAuthError GaiaAuthenticator2::GenerateAuthError(
214 const std::string& data,
215 const URLRequestStatus& status) {
216
217 GaiaAuthConsumer::GaiaAuthError error;
198 error.data = data; 218 error.data = data;
199 219
200 if (!status.is_success()) { 220 if (!status.is_success()) {
201 if (status.status() == URLRequestStatus::CANCELED) { 221 if (status.status() == URLRequestStatus::CANCELED) {
202 error.code = GaiaAuthConsumer::REQUEST_CANCELED; 222 error.code = GaiaAuthConsumer::REQUEST_CANCELED;
203 } else { 223 } else {
204 error.code = GaiaAuthConsumer::NETWORK_ERROR; 224 error.code = GaiaAuthConsumer::NETWORK_ERROR;
205 error.network_error = status.os_error(); 225 error.network_error = status.os_error();
206 LOG(WARNING) << "Could not reach Google Accounts servers: errno " 226 LOG(WARNING) << "Could not reach Google Accounts servers: errno "
207 << status.os_error(); 227 << status.os_error();
208 } 228 }
209 } else { 229 } else {
210 if (IsSecondFactorSuccess(data)) { 230 if (IsSecondFactorSuccess(data)) {
211 error.code = GaiaAuthConsumer::TWO_FACTOR; 231 error.code = GaiaAuthConsumer::TWO_FACTOR;
212 } else { 232 } else {
213 error.code = GaiaAuthConsumer::PERMISSION_DENIED; 233 error.code = GaiaAuthConsumer::PERMISSION_DENIED;
214 } 234 }
215 } 235 }
216 236
217 consumer_->OnClientLoginFailure(error); 237 return error;
238 }
239
240 void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data,
241 const URLRequestStatus& status,
242 int response_code) {
243
244 if (status.is_success() && response_code == RC_REQUEST_OK) {
245 LOG(INFO) << "ClientLogin successful!";
246 std::string sid;
247 std::string lsid;
248 std::string token;
249 ParseClientLoginResponse(data, &sid, &lsid, &token);
250 consumer_->OnClientLoginSuccess(
251 GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data));
252 return;
253 }
Zachary Kuznia 2010/07/06 03:33:23 Perhaps make this an "} else {" to make the flow o
254
255 consumer_->OnClientLoginFailure(GenerateAuthError(data, status));
256 }
257
258 void GaiaAuthenticator2::OnIssueAuthTokenFetched(
259 const std::string& data,
260 const URLRequestStatus& status,
261 int response_code) {
262 if (status.is_success() && response_code == RC_REQUEST_OK) {
263 // Only the bare token is returned in the body of this Gaia call
264 // without any padding.
265 consumer_->OnIssueAuthTokenSuccess(requested_service_, data);
266 } else {
267 consumer_->OnIssueAuthTokenFailure(requested_service_,
268 GenerateAuthError(data, status));
269 }
218 } 270 }
219 271
220 void GaiaAuthenticator2::OnURLFetchComplete(const URLFetcher* source, 272 void GaiaAuthenticator2::OnURLFetchComplete(const URLFetcher* source,
221 const GURL& url, 273 const GURL& url,
222 const URLRequestStatus& status, 274 const URLRequestStatus& status,
223 int response_code, 275 int response_code,
224 const ResponseCookies& cookies, 276 const ResponseCookies& cookies,
225 const std::string& data) { 277 const std::string& data) {
226 fetch_pending_ = false; 278 fetch_pending_ = false;
227 if (url == client_login_gurl_) { 279 if (url == client_login_gurl_) {
228 OnClientLoginFetched(data, status, response_code); 280 OnClientLoginFetched(data, status, response_code);
229 return; 281 } else if (url == issue_auth_token_gurl_) {
282 OnIssueAuthTokenFetched(data, status, response_code);
283 } else {
284 NOTREACHED();
230 } 285 }
231 NOTREACHED();
232 } 286 }
233 287
234 // static 288 // static
235 bool GaiaAuthenticator2::IsSecondFactorSuccess( 289 bool GaiaAuthenticator2::IsSecondFactorSuccess(
236 const std::string& alleged_error) { 290 const std::string& alleged_error) {
237 return alleged_error.find(kSecondFactor) != 291 return alleged_error.find(kSecondFactor) !=
238 std::string::npos; 292 std::string::npos;
239 } 293 }
OLDNEW
« no previous file with comments | « chrome/common/net/gaia/gaia_authenticator2.h ('k') | chrome/common/net/gaia/gaia_authenticator2_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698