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

Side by Side Diff: lib/src/google-signin/google-signin-aware.html

Issue 1418513006: update elements and fix some bugs (Closed) Base URL: git@github.com:dart-lang/polymer_elements.git@master
Patch Set: code review updates Created 5 years, 1 month 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 <link rel="import" href="../polymer/polymer.html"> 1 <link rel="import" href="../polymer/polymer.html">
2 <link rel="import" href="../google-apis/google-js-api.html"> 2 <link rel="import" href="../google-apis/google-js-api.html">
3 3
4 <script> 4 <script>
5 (function() { 5 (function() {
6 6
7 /** 7 /**
8 * Enum of attributes to be passed through to the login API call. 8 * Enum of attributes to be passed through to the login API call.
9 * @readonly 9 * @readonly
10 * @enum {string} 10 * @enum {string}
11 */ 11 */
12 var ProxyLoginAttributes = { 12 var ProxyLoginAttributes = {
13 'appPackageName': 'apppackagename', 13 'appPackageName': 'apppackagename',
14 'clientId': 'clientid', 14 'clientId': 'clientid',
15 'cookiePolicy': 'cookiepolicy', 15 'cookiePolicy': 'cookiepolicy',
16 'requestVisibleActions': 'requestvisibleactions' 16 'requestVisibleActions': 'requestvisibleactions',
17 'hostedDomain': 'hostedDomain'
17 }; 18 };
18 19
19 /** 20 /**
20 * AuthEngine does all interactions with gapi.auth2 21 * AuthEngine does all interactions with gapi.auth2
21 * 22 *
22 * It is tightly coupled with <google-signin-aware> element 23 * It is tightly coupled with <google-signin-aware> element
23 * The elements configure AuthEngine. 24 * The elements configure AuthEngine.
24 * AuthEngine propagates all authentication events to all google-signin-awar e elements 25 * AuthEngine propagates all authentication events to all google-signin-awar e elements
25 * 26 *
26 * API used: https://developers.google.com/identity/sign-in/web/reference 27 * API used: https://developers.google.com/identity/sign-in/web/reference
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 }, 91 },
91 92
92 set requestVisibleactions(val) { 93 set requestVisibleactions(val) {
93 if (this._requestVisibleActions && val && val != this._requestVisibleAct ions) { 94 if (this._requestVisibleActions && val && val != this._requestVisibleAct ions) {
94 throw new Error('requestVisibleactions cannot change. Values do not ma tch. New: ' + val + ' Old: ' + this._requestVisibleActions); 95 throw new Error('requestVisibleactions cannot change. Values do not ma tch. New: ' + val + ' Old: ' + this._requestVisibleActions);
95 } 96 }
96 if (val) 97 if (val)
97 this._requestVisibleActions = val; 98 this._requestVisibleActions = val;
98 }, 99 },
99 100
101 /**
102 * oauth2 argument, set by google-signin-aware
103 */
104 _hostedDomain: '',
105
106 get hostedDomain() {
107 return this._hostedDomain;
108 },
109
110 set hostedDomain(val) {
111 if (this._hostedDomain && val && val != this._hostedDomain) {
112 throw new Error('hostedDomain cannot change. Values do not match. New: ' + val + ' Old: ' + this._hostedDomain);
113 }
114 if (val)
115 this._hostedDomain = val;
116 },
117
118 /** Is offline access currently enabled in the google-signin-aware element ? */
119 _offline: false,
120
121 get offline() {
122 return this._offline;
123 },
124
125 set offline(val) {
126 this._offline = val;
127 this.updateAdditionalAuth();
128 },
129
130 /** Should we force a re-prompt for offline access? */
131 _offlineAlwaysPrompt: false,
132
133 get offlineAlwaysPrompt() {
134 return this._offlineAlwaysPrompt;
135 },
136
137 set offlineAlwaysPrompt(val) {
138 this._offlineAlwaysPrompt = val;
139 this.updateAdditionalAuth();
140 },
141
142 /** Have we already gotten offline access from Google during this session? */
143 offlineGranted: false,
144
100 /** <google-js-api> */ 145 /** <google-js-api> */
101 _apiLoader: null, 146 _apiLoader: null,
102 147
103 /** an array of wanted scopes. oauth2 argument */ 148 /** an array of wanted scopes. oauth2 argument */
104 _requestedScopeArray: [], 149 _requestedScopeArray: [],
105 150
106 /** _requestedScopeArray as string */ 151 /** _requestedScopeArray as string */
107 get requestedScopes() { 152 get requestedScopes() {
108 return this._requestedScopeArray.join(' '); 153 return this._requestedScopeArray.join(' ');
109 }, 154 },
(...skipping 25 matching lines...) Expand all
135 gapi.load('auth2', this.initAuth2.bind(this)); 180 gapi.load('auth2', this.initAuth2.bind(this));
136 }, 181 },
137 182
138 initAuth2: function() { 183 initAuth2: function() {
139 if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId) { 184 if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId) {
140 return; 185 return;
141 } 186 }
142 var auth = gapi.auth2.init({ 187 var auth = gapi.auth2.init({
143 'client_id': this.clientId, 188 'client_id': this.clientId,
144 'cookie_policy': this.cookiePolicy, 189 'cookie_policy': this.cookiePolicy,
145 'scope': this.requestedScopes 190 'scope': this.requestedScopes,
191 'hosted_domain': this.hostedDomain
146 }); 192 });
147 193
148 auth.currentUser.listen(this.handleUserUpdate.bind(this)); 194 auth.currentUser.listen(this.handleUserUpdate.bind(this));
149 195
150 auth.then( 196 auth.then(
151 function success() { 197 function success() {
152 // Let the current user listener trigger the changes. 198 // Let the current user listener trigger the changes.
153 }, 199 },
154 function error(error) { 200 function error(error) {
155 console.error(error); 201 console.error(error);
(...skipping 16 matching lines...) Expand all
172 newPrimaryUser.getGrantedScopes()); 218 newPrimaryUser.getGrantedScopes());
173 // console.log(this._grantedScopeArray); 219 // console.log(this._grantedScopeArray);
174 this.updateAdditionalAuth(); 220 this.updateAdditionalAuth();
175 221
176 var response = newPrimaryUser.getAuthResponse(); 222 var response = newPrimaryUser.getAuthResponse();
177 for (var i=0; i<this.signinAwares.length; i++) { 223 for (var i=0; i<this.signinAwares.length; i++) {
178 this.signinAwares[i]._updateScopeStatus(response); 224 this.signinAwares[i]._updateScopeStatus(response);
179 } 225 }
180 }, 226 },
181 227
228 setOfflineCode: function(code) {
229 for (var i=0; i<this.signinAwares.length; i++) {
230 this.signinAwares[i]._updateOfflineCode(code);
231 }
232 },
233
182 /** convert scope string to scope array */ 234 /** convert scope string to scope array */
183 strToScopeArray: function(str) { 235 strToScopeArray: function(str) {
184 if (!str) { 236 if (!str) {
185 return []; 237 return [];
186 } 238 }
187 // remove extra spaces, then split 239 // remove extra spaces, then split
188 var scopes = str.replace(/\ +/g, ' ').trim().split(' '); 240 var scopes = str.replace(/\ +/g, ' ').trim().split(' ');
189 for (var i=0; i<scopes.length; i++) { 241 for (var i=0; i<scopes.length; i++) {
190 scopes[i] = scopes[i].toLowerCase(); 242 scopes[i] = scopes[i].toLowerCase();
191 // Handle scopes that will be deprecated but are still returned with their old value 243 // Handle scopes that will be deprecated but are still returned with their old value
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 } 282 }
231 if (scopesUpdated) { 283 if (scopesUpdated) {
232 this.updateAdditionalAuth(); 284 this.updateAdditionalAuth();
233 this.updatePlusScopes(); 285 this.updatePlusScopes();
234 } 286 }
235 }, 287 },
236 288
237 /** update status of _needAdditionalAuth */ 289 /** update status of _needAdditionalAuth */
238 updateAdditionalAuth: function() { 290 updateAdditionalAuth: function() {
239 var needMoreAuth = false; 291 var needMoreAuth = false;
240 for (var i=0; i<this._requestedScopeArray.length; i++) { 292 if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted) {
241 if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) === -1) { 293 needMoreAuth = true;
242 needMoreAuth = true; 294 } else {
243 break; 295 for (var i=0; i<this._requestedScopeArray.length; i++) {
296 if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) == = -1) {
297 needMoreAuth = true;
298 break;
299 }
244 } 300 }
245 } 301 }
246 if (this._needAdditionalAuth != needMoreAuth) { 302 if (this._needAdditionalAuth != needMoreAuth) {
247 this._needAdditionalAuth = needMoreAuth; 303 this._needAdditionalAuth = needMoreAuth;
248 // broadcast new value 304 // broadcast new value
249 for (var i=0; i<this.signinAwares.length; i++) { 305 for (var i=0; i<this.signinAwares.length; i++) {
250 this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth); 306 this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth);
251 } 307 }
252 } 308 }
253 }, 309 },
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 376
321 // Proxy specific attributes through to the signIn options. 377 // Proxy specific attributes through to the signIn options.
322 Object.keys(ProxyLoginAttributes).forEach(function(key) { 378 Object.keys(ProxyLoginAttributes).forEach(function(key) {
323 if (this[key] && this[key] !== '') { 379 if (this[key] && this[key] !== '') {
324 params[ProxyLoginAttributes[key]] = this[key]; 380 params[ProxyLoginAttributes[key]] = this[key];
325 } 381 }
326 }, this); 382 }, this);
327 383
328 var promise; 384 var promise;
329 var user = gapi.auth2.getAuthInstance().currentUser.get(); 385 var user = gapi.auth2.getAuthInstance().currentUser.get();
330 if (user.getGrantedScopes()) { 386 if (!(this.offline || this.offlineAlwaysPrompt)) {
331 // additional auth, skip multiple account dialog 387 if (user.getGrantedScopes()) {
332 promise = user.grant(params); 388 // additional auth, skip multiple account dialog
389 promise = user.grant(params);
390 } else {
391 // initial signin
392 promise = gapi.auth2.getAuthInstance().signIn(params);
393 }
333 } else { 394 } else {
334 // initial signin 395 params.redirect_uri = 'postmessage';
335 promise = gapi.auth2.getAuthInstance().signIn(params); 396 if (this.offlineAlwaysPrompt) {
397 params.approval_prompt = 'force';
398 }
399
400 // Despite being documented at https://goo.gl/tiO0Bk
401 // It doesn't seem like user.grantOfflineAccess() actually exists in
402 // the current version of the Google Sign-In JS client we're using
403 // through GoogleWebComponents. So in the offline case, we will not
404 // distinguish between a first auth and an additional one.
405 promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params);
336 } 406 }
337 promise.then( 407 promise.then(
338 function success(newUser) { 408 function success(response) {
409 // If login was offline, response contains one string "code"
410 // Otherwise it contains the user object already
411 var newUser;
412 if (response.code) {
413 AuthEngine.offlineGranted = true;
414 newUser = gapi.auth2.getAuthInstance().currentUser.get();
415 AuthEngine.setOfflineCode(response.code);
416 } else {
417 newUser = response;
418 }
419
339 var authResponse = newUser.getAuthResponse(); 420 var authResponse = newUser.getAuthResponse();
340 // Let the current user listener trigger the changes. 421 // Let the current user listener trigger the changes.
341 }, 422 },
342 function error(error) { 423 function error(error) {
343 if ("Access denied." == error.reason) { 424 if ("Access denied." == error.reason) {
344 // Access denied is not an error, user hit cancel 425 // Access denied is not an error, user hit cancel
345 return; 426 return;
346 } else { 427 } else {
347 console.error(error); 428 console.error(error);
348 } 429 }
(...skipping 19 matching lines...) Expand all
368 449
369 /** 450 /**
370 `google-signin-aware` is used to enable authentication in custom elements by 451 `google-signin-aware` is used to enable authentication in custom elements by
371 interacting with a google-signin element that needs to be present somewhere 452 interacting with a google-signin element that needs to be present somewhere
372 on the page. 453 on the page.
373 454
374 The `scopes` attribute allows you to specify which scope permissions are require d 455 The `scopes` attribute allows you to specify which scope permissions are require d
375 (e.g do you want to allow interaction with the Google Drive API). 456 (e.g do you want to allow interaction with the Google Drive API).
376 457
377 The `google-signin-aware-success` event is triggered when a user successfully 458 The `google-signin-aware-success` event is triggered when a user successfully
378 authenticates. The `google-signin-aware-signed-out` event is triggered 459 authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, succ essful
379 when a user explicitely signs out via the google-signin element. 460 authentication will also trigger the `google-signin-offline-success`event.
461 The `google-signin-aware-signed-out` event is triggered when a user explicitly
462 signs out via the google-signin element.
380 463
381 You can bind to `isAuthorized` property to monitor authorization state. 464 You can bind to `isAuthorized` property to monitor authorization state.
382 ##### Example 465 ##### Example
383 466
384 <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google -signin-aware> 467 <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google -signin-aware>
468
469
470 ##### Example with offline
471 <template id="awareness" is="dom-bind">
472 <google-signin-aware
473 scopes="https://www.googleapis.com/auth/drive"
474 offline
475 on-google-signin-aware-success="handleSignin"
476 on-google-signin-offline-success="handleOffline"></google-signin-aware >
477 <\/template>
478 <script>
479 var aware = document.querySelector('#awareness');
480 aware.handleSignin = function(response) {
481 var user = gapi.auth2.getAuthInstance().currentUser.get();
482 console.log('User name: ' + user.getBasicProfile().getName());
483 };
484 aware.handleOffline = function(response) {
485 console.log('Offline code received: ' + response.detail.code);
486 // Here you would POST response.detail.code to your webserver, which can
487 // exchange the authorization code for an access token. More info at:
488 // https://developers.google.com/identity/protocols/OAuth2WebServer
489 };
490 <\/script>
385 */ 491 */
386 Polymer({ 492 Polymer({
387 493
388 is: 'google-signin-aware', 494 is: 'google-signin-aware',
389 495
390 /** 496 /**
391 * Fired when this scope has been authorized 497 * Fired when this scope has been authorized
392 * @param {Object} result Authorization result. 498 * @param {Object} result Authorization result.
393 * @event google-signin-aware-success 499 * @event google-signin-aware-success
394 */ 500 */
395 /** 501 /**
502 * Fired when an offline authorization is successful.
503 * @param {Object} detail
504 * @param {string} detail.code The one-time authorization code from Google .
505 * Your application can exchange this for an `access_token` and `refre sh_token`
506 * @event google-signin-offline-success
507 */
508 /**
396 * Fired when this scope is not authorized 509 * Fired when this scope is not authorized
397 * @event google-signin-aware-signed-out 510 * @event google-signin-aware-signed-out
398 */ 511 */
399 properties: { 512 properties: {
400 /** 513 /**
401 * App package name for android over-the-air installs. 514 * App package name for android over-the-air installs.
402 * See the relevant [docs](https://developers.google.com/+/web/signin/an droid-app-installs) 515 * See the relevant [docs](https://developers.google.com/+/web/signin/an droid-app-installs)
403 */ 516 */
404 appPackageName: { 517 appPackageName: {
405 type: String, 518 type: String,
(...skipping 21 matching lines...) Expand all
427 /** 540 /**
428 * The app activity types you want to write on behalf of the user 541 * The app activity types you want to write on behalf of the user
429 * (e.g http://schemas.google.com/AddActivity) 542 * (e.g http://schemas.google.com/AddActivity)
430 * 543 *
431 */ 544 */
432 requestVisibleActions: { 545 requestVisibleActions: {
433 type: String, 546 type: String,
434 observer: '_requestVisibleActionsChanged' 547 observer: '_requestVisibleActionsChanged'
435 }, 548 },
436 549
550 /**
551 * The Google Apps domain to which users must belong to sign in.
552 * See the relevant [docs](https://developers.google.com/identity/sign-i n/web/reference) for more information.
553 */
554 hostedDomain: {
555 type: String,
556 observer: '_hostedDomainChanged'
557 },
558
559 /**
560 * Allows for offline `access_token` retrieval during the signin process .
561 * See also `offlineAlwaysPrompt`. You only need to set one of the two; if both
562 * are set, the behavior of `offlineAlwaysPrompt` will override `offline `.
563 */
564 offline: {
565 type: Boolean,
566 value: false,
567 observer: '_offlineChanged'
568 },
569
570 /**
571 * Works the same as `offline` with the addition that it will always
572 * force a re-prompt to the user, guaranteeing that you will get a
573 * refresh_token even if the user has already granted offline access to
574 * this application. You only need to set one of `offline` or
575 * `offlineAlwaysPrompt`, not both.
576 */
577 offlineAlwaysPrompt: {
578 type: Boolean,
579 value: false,
580 observer: '_offlineAlwaysPromptChanged'
581 },
582
437 /** 583 /**
438 * The scopes to provide access to (e.g https://www.googleapis.com/auth/ drive) 584 * The scopes to provide access to (e.g https://www.googleapis.com/auth/ drive)
439 * and should be space-delimited. 585 * and should be space-delimited.
440 */ 586 */
441 scopes: { 587 scopes: {
442 type: String, 588 type: String,
443 value: 'profile', 589 value: 'profile',
444 observer: '_scopesChanged' 590 observer: '_scopesChanged'
445 }, 591 },
446 592
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 }, 656 },
511 657
512 _cookiePolicyChanged: function(newPolicy, oldPolicy) { 658 _cookiePolicyChanged: function(newPolicy, oldPolicy) {
513 AuthEngine.cookiePolicy = newPolicy; 659 AuthEngine.cookiePolicy = newPolicy;
514 }, 660 },
515 661
516 _requestVisibleActionsChanged: function(newVal, oldVal) { 662 _requestVisibleActionsChanged: function(newVal, oldVal) {
517 AuthEngine.requestVisibleActions = newVal; 663 AuthEngine.requestVisibleActions = newVal;
518 }, 664 },
519 665
666 _hostedDomainChanged: function(newVal, oldVal) {
667 AuthEngine.hostedDomain = newVal;
668 },
669
670 _offlineChanged: function(newVal, oldVal) {
671 AuthEngine.offline = newVal;
672 },
673
674 _offlineAlwaysPromptChanged: function(newVal, oldVal) {
675 AuthEngine.offlineAlwaysPrompt = newVal;
676 },
677
520 _scopesChanged: function(newVal, oldVal) { 678 _scopesChanged: function(newVal, oldVal) {
521 AuthEngine.requestScopes(newVal); 679 AuthEngine.requestScopes(newVal);
522 this._updateScopeStatus(); 680 this._updateScopeStatus();
523 }, 681 },
524 682
525 _updateScopeStatus: function(user) { 683 _updateScopeStatus: function(user) {
526 var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.sc opes); 684 var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.sc opes);
527 if (newAuthorized !== this.isAuthorized) { 685 if (newAuthorized !== this.isAuthorized) {
528 this._setIsAuthorized(newAuthorized); 686 this._setIsAuthorized(newAuthorized);
529 if (newAuthorized) { 687 if (newAuthorized) {
530 this.fire('google-signin-aware-success', user); 688 this.fire('google-signin-aware-success', user);
531 } 689 }
532 else { 690 else {
533 this.fire('google-signin-aware-signed-out', user); 691 this.fire('google-signin-aware-signed-out', user);
534 } 692 }
535 } 693 }
694 },
695
696 _updateOfflineCode: function(code) {
697 if (code) {
698 this.fire('google-signin-offline-success', {code: code});
699 }
536 } 700 }
537 }); 701 });
538 })(); 702 })();
539 </script> 703 </script>
OLDNEW
« no previous file with comments | « lib/src/google-signin/google-signin.html ('k') | lib/src/google-streetview-pano/google-streetview-pano.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698