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

Side by Side Diff: chrome/browser/resources/gaia_auth/background.js

Issue 447013003: Use GAIA headers to distinguish between GAIA and SAML IdP cookies (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clarified comment. Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chromeos/login/saml/saml_browsertest.cc ('k') | google_apis/gaia/fake_gaia.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * A background script of the auth extension that bridges the communication 7 * A background script of the auth extension that bridges the communication
8 * between the main and injected scripts. 8 * between the main and injected scripts.
9 * 9 *
10 * Here is an overview of the communication flow when SAML is being used: 10 * Here is an overview of the communication flow when SAML is being used:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 return this.bridges_[details.tabId].onBeforeSendHeaders(details); 51 return this.bridges_[details.tabId].onBeforeSendHeaders(details);
52 else 52 else
53 return {requestHeaders: details.requestHeaders}; 53 return {requestHeaders: details.requestHeaders};
54 }.bind(this), 54 }.bind(this),
55 {urls: ['*://*/*'], types: ['sub_frame']}, 55 {urls: ['*://*/*'], types: ['sub_frame']},
56 ['blocking', 'requestHeaders']); 56 ['blocking', 'requestHeaders']);
57 57
58 chrome.webRequest.onHeadersReceived.addListener( 58 chrome.webRequest.onHeadersReceived.addListener(
59 function(details) { 59 function(details) {
60 if (this.bridges_[details.tabId]) 60 if (this.bridges_[details.tabId])
61 this.bridges_[details.tabId].onHeadersReceived(details); 61 return this.bridges_[details.tabId].onHeadersReceived(details);
62 }.bind(this), 62 }.bind(this),
63 {urls: ['*://*/*'], types: ['sub_frame']}, 63 {urls: ['*://*/*'], types: ['sub_frame']},
64 ['responseHeaders']); 64 ['blocking', 'responseHeaders']);
65 65
66 chrome.webRequest.onCompleted.addListener( 66 chrome.webRequest.onCompleted.addListener(
67 function(details) { 67 function(details) {
68 if (this.bridges_[details.tabId]) 68 if (this.bridges_[details.tabId])
69 this.bridges_[details.tabId].onCompleted(details); 69 this.bridges_[details.tabId].onCompleted(details);
70 }.bind(this), 70 }.bind(this),
71 {urls: ['*://*/*'], types: ['sub_frame']}, 71 {urls: ['*://*/*'], types: ['sub_frame']},
72 ['responseHeaders']); 72 ['responseHeaders']);
73 }, 73 },
74 74
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 onInsecureRequest: function(url) { 253 onInsecureRequest: function(url) {
254 if (!this.blockInsecureContent_) 254 if (!this.blockInsecureContent_)
255 return {}; 255 return {};
256 this.channelMain_.send({name: 'onInsecureContentBlocked', url: url}); 256 this.channelMain_.send({name: 'onInsecureContentBlocked', url: url});
257 return {cancel: true}; 257 return {cancel: true};
258 }, 258 },
259 259
260 /** 260 /**
261 * Handler or webRequest.onHeadersReceived. It reads the authenticated user 261 * Handler or webRequest.onHeadersReceived. It reads the authenticated user
262 * email from google-accounts-signin-header. 262 * email from google-accounts-signin-header.
263 * @return {!Object} Modified request headers.
263 */ 264 */
264 onHeadersReceived: function(details) { 265 onHeadersReceived: function(details) {
265 if (!this.isDesktopFlow_ || 266 var headers = details.responseHeaders;
266 !this.gaiaUrl_ || 267
267 details.url.lastIndexOf(this.gaiaUrl_) != 0) { 268 if (this.isDesktopFlow_ &&
269 this.gaiaUrl_ &&
270 details.url.lastIndexOf(this.gaiaUrl_) == 0) {
268 // TODO(xiyuan, guohui): CrOS should reuse the logic below for reading the 271 // TODO(xiyuan, guohui): CrOS should reuse the logic below for reading the
269 // email for SAML users and cut off the /ListAccount call. 272 // email for SAML users and cut off the /ListAccount call.
270 return; 273 for (var i = 0; headers && i < headers.length; ++i) {
274 if (headers[i].name.toLowerCase() == 'google-accounts-signin') {
275 var headerValues = headers[i].value.toLowerCase().split(',');
276 var signinDetails = {};
277 headerValues.forEach(function(e) {
278 var pair = e.split('=');
279 signinDetails[pair[0].trim()] = pair[1].trim();
280 });
281 // Remove "" around.
282 this.email_ = signinDetails['email'].slice(1, -1);
283 this.sessionIndex_ = signinDetails['sessionindex'];
284 break;
285 }
286 }
271 } 287 }
272 288
273 var headers = details.responseHeaders; 289 if (!this.isDesktopFlow_) {
274 for (var i = 0; headers && i < headers.length; ++i) { 290 // Check whether GAIA headers indicating the start or end of a SAML
275 if (headers[i].name.toLowerCase() == 'google-accounts-signin') { 291 // redirect are present. If so, synthesize cookies to mark these points.
276 var headerValues = headers[i].value.toLowerCase().split(','); 292 for (var i = 0; headers && i < headers.length; ++i) {
277 var signinDetails = {}; 293 if (headers[i].name.toLowerCase() == 'google-accounts-saml') {
278 headerValues.forEach(function(e) { 294 var action = headers[i].value.toLowerCase();
279 var pair = e.split('='); 295 if (action == 'start') {
280 signinDetails[pair[0].trim()] = pair[1].trim(); 296 // GAIA is redirecting to a SAML IdP. Any cookies contained in the
281 }); 297 // current |headers| were set by GAIA. Any cookies set in future
282 // Remove "" around. 298 // requests will be coming from the IdP. Append a cookie to the
283 this.email_ = signinDetails['email'].slice(1, -1); 299 // current |headers| that marks the point at which the redirect
284 this.sessionIndex_ = signinDetails['sessionindex']; 300 // occurred.
285 return; 301 headers.push({name: 'Set-Cookie',
302 value: 'google-accounts-saml-start=now'});
303 return {responseHeaders: headers};
304 } else if (action == 'end') {
305 // The SAML IdP has redirected back to GAIA. Add a cookie that marks
306 // the point at which the redirect occurred occurred. It is
307 // important that this cookie be prepended to the current |headers|
308 // because any cookies contained in the |headers| were already set
309 // by GAIA, not the IdP. Due to limitations in the webRequest API,
310 // it is not trivial to prepend a cookie:
311 //
312 // The webRequest API only allows for deleting and appending
313 // headers. To prepend a cookie (C), three steps are needed:
314 // 1) Delete any headers that set cookies (e.g., A, B).
315 // 2) Append a header which sets the cookie (C).
316 // 3) Append the original headers (A, B).
317 //
318 // Due to a further limitation of the webRequest API, it is not
319 // possible to delete a header in step 1) and append an identical
320 // header in step 3). To work around this, a trailing semicolon is
321 // added to each header before appending it. Trailing semicolons are
322 // ignored by Chrome in cookie headers, causing the modified headers
323 // to actually set the original cookies.
324 var otherHeaders = [];
325 var cookies = [{name: 'Set-Cookie',
326 value: 'google-accounts-saml-end=now'}];
327 for (var j = 0; j < headers.length; ++j) {
328 if (headers[j].name.toLowerCase().indexOf('set-cookie') == 0) {
329 var header = headers[j];
330 header.value += ';';
331 cookies.push(header);
332 } else {
333 otherHeaders.push(headers[j]);
334 }
335 }
336 return {responseHeaders: otherHeaders.concat(cookies)};
337 }
338 }
286 } 339 }
287 } 340 }
341
342 return {};
288 }, 343 },
289 344
290 /** 345 /**
291 * Handler for webRequest.onBeforeSendHeaders. 346 * Handler for webRequest.onBeforeSendHeaders.
292 * @return {!Object} Modified request headers. 347 * @return {!Object} Modified request headers.
293 */ 348 */
294 onBeforeSendHeaders: function(details) { 349 onBeforeSendHeaders: function(details) {
295 if (!this.isDesktopFlow_ && this.gaiaUrl_ && 350 if (!this.isDesktopFlow_ && this.gaiaUrl_ &&
296 details.url.indexOf(this.gaiaUrl_) == 0) { 351 details.url.indexOf(this.gaiaUrl_) == 0) {
297 details.requestHeaders.push({ 352 details.requestHeaders.push({
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 }, 419 },
365 420
366 onPageLoaded_: function(msg) { 421 onPageLoaded_: function(msg) {
367 if (this.channelMain_) 422 if (this.channelMain_)
368 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url}); 423 this.channelMain_.send({name: 'onAuthPageLoaded', url: msg.url});
369 } 424 }
370 }; 425 };
371 426
372 var backgroundBridgeManager = new BackgroundBridgeManager(); 427 var backgroundBridgeManager = new BackgroundBridgeManager();
373 backgroundBridgeManager.run(); 428 backgroundBridgeManager.run();
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/saml/saml_browsertest.cc ('k') | google_apis/gaia/fake_gaia.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698