| OLD | NEW |
| (Empty) |
| 1 <!-- | |
| 2 Copyright 2014 Google Inc | |
| 3 | |
| 4 Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 you may not use this file except in compliance with the License. | |
| 6 You may obtain a copy of the License at | |
| 7 | |
| 8 https://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | |
| 10 Unless required by applicable law or agreed to in writing, software | |
| 11 distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 See the License for the specific language governing permissions and | |
| 14 limitations under the License. | |
| 15 --> | |
| 16 | |
| 17 <link rel="import" href="../polymer/polymer.html"> | |
| 18 <link rel="import" href="../google-apis/google-js-api.html"> | |
| 19 | |
| 20 <script> | |
| 21 (function() { | |
| 22 | |
| 23 /** | |
| 24 * Enum of attributes to be passed through to the login API call. | |
| 25 * @readonly | |
| 26 * @enum {string} | |
| 27 */ | |
| 28 var ProxyLoginAttributes = { | |
| 29 'appPackageName': 'apppackagename', | |
| 30 'clientId': 'clientid', | |
| 31 'cookiePolicy': 'cookiepolicy', | |
| 32 'hostedDomain': 'hostedDomain', | |
| 33 'openidPrompt': 'prompt', | |
| 34 'requestVisibleActions': 'requestvisibleactions' | |
| 35 }; | |
| 36 | |
| 37 /** | |
| 38 * AuthEngine does all interactions with gapi.auth2 | |
| 39 * | |
| 40 * It is tightly coupled with <google-signin-aware> element | |
| 41 * The elements configure AuthEngine. | |
| 42 * AuthEngine propagates all authentication events to all google-signin-awar
e elements | |
| 43 * | |
| 44 * API used: https://developers.google.com/identity/sign-in/web/reference | |
| 45 * | |
| 46 */ | |
| 47 var AuthEngine = { | |
| 48 | |
| 49 /** | |
| 50 * oauth2 argument, set by google-signin-aware | |
| 51 */ | |
| 52 _clientId: null, | |
| 53 | |
| 54 get clientId() { | |
| 55 return this._clientId; | |
| 56 }, | |
| 57 | |
| 58 set clientId(val) { | |
| 59 if (this._clientId && val && val != this._clientId) { | |
| 60 throw new Error('clientId cannot change. Values do not match. New: ' +
val + ' Old:' + this._clientId); | |
| 61 } | |
| 62 if (val && val != this._clientId) { | |
| 63 this._clientId = val; | |
| 64 this.initAuth2(); | |
| 65 } | |
| 66 }, | |
| 67 | |
| 68 /** | |
| 69 * oauth2 argument, set by google-signin-aware | |
| 70 */ | |
| 71 _cookiePolicy: 'single_host_origin', | |
| 72 | |
| 73 get cookiePolicy() { | |
| 74 return this._cookiePolicy; | |
| 75 }, | |
| 76 | |
| 77 set cookiePolicy(val) { | |
| 78 if (val) { | |
| 79 this._cookiePolicy = val; | |
| 80 } | |
| 81 }, | |
| 82 | |
| 83 /** | |
| 84 * oauth2 argument, set by google-signin-aware | |
| 85 */ | |
| 86 _appPackageName: '', | |
| 87 | |
| 88 get appPackageName() { | |
| 89 return this._appPackageName; | |
| 90 }, | |
| 91 | |
| 92 set appPackageName(val) { | |
| 93 if (this._appPackageName && val && val != this._appPackageName) { | |
| 94 throw new Error('appPackageName cannot change. Values do not match. Ne
w: ' + val + ' Old: ' + this._appPackageName); | |
| 95 } | |
| 96 if (val) { | |
| 97 this._appPackageName = val; | |
| 98 } | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * oauth2 argument, set by google-signin-aware | |
| 103 */ | |
| 104 _requestVisibleActions: '', | |
| 105 | |
| 106 get requestVisibleactions() { | |
| 107 return this._requestVisibleActions; | |
| 108 }, | |
| 109 | |
| 110 set requestVisibleactions(val) { | |
| 111 if (this._requestVisibleActions && val && val != this._requestVisibleAct
ions) { | |
| 112 throw new Error('requestVisibleactions cannot change. Values do not ma
tch. New: ' + val + ' Old: ' + this._requestVisibleActions); | |
| 113 } | |
| 114 if (val) | |
| 115 this._requestVisibleActions = val; | |
| 116 }, | |
| 117 | |
| 118 /** | |
| 119 * oauth2 argument, set by google-signin-aware | |
| 120 */ | |
| 121 _hostedDomain: '', | |
| 122 | |
| 123 get hostedDomain() { | |
| 124 return this._hostedDomain; | |
| 125 }, | |
| 126 | |
| 127 set hostedDomain(val) { | |
| 128 if (this._hostedDomain && val && val != this._hostedDomain) { | |
| 129 throw new Error('hostedDomain cannot change. Values do not match. New:
' + val + ' Old: ' + this._hostedDomain); | |
| 130 } | |
| 131 if (val) | |
| 132 this._hostedDomain = val; | |
| 133 }, | |
| 134 | |
| 135 /** | |
| 136 * oauth2 argument, set by google-signin-aware | |
| 137 */ | |
| 138 _openidPrompt: '', | |
| 139 | |
| 140 get openidPrompt() { | |
| 141 return this._openidPrompt; | |
| 142 }, | |
| 143 | |
| 144 set openidPrompt(val) { | |
| 145 if (typeof val !== 'string') { | |
| 146 throw new Error( | |
| 147 'openidPrompt must be a string. Received ' + typeof val); | |
| 148 } | |
| 149 if (val) { | |
| 150 var values = val.split(' '); | |
| 151 values = values.map(function(v) { | |
| 152 return v.trim(); | |
| 153 }); | |
| 154 values = values.filter(function(v) { | |
| 155 return v; | |
| 156 }); | |
| 157 var validValues = {none: 0, login: 0, consent: 0, select_account: 0}; | |
| 158 values.forEach(function(v) { | |
| 159 if (v == 'none' && values.length > 1) { | |
| 160 throw new Error( | |
| 161 'none cannot be combined with other openidPrompt values'); | |
| 162 } | |
| 163 if (!(v in validValues)) { | |
| 164 throw new Error( | |
| 165 'invalid openidPrompt value ' + v + | |
| 166 '. Valid values: ' + Object.keys(validValues).join(', ')); | |
| 167 } | |
| 168 }); | |
| 169 } | |
| 170 this._openidPrompt = val; | |
| 171 }, | |
| 172 | |
| 173 /** Is offline access currently enabled in the google-signin-aware element
? */ | |
| 174 _offline: false, | |
| 175 | |
| 176 get offline() { | |
| 177 return this._offline; | |
| 178 }, | |
| 179 | |
| 180 set offline(val) { | |
| 181 this._offline = val; | |
| 182 this.updateAdditionalAuth(); | |
| 183 }, | |
| 184 | |
| 185 /** Should we force a re-prompt for offline access? */ | |
| 186 _offlineAlwaysPrompt: false, | |
| 187 | |
| 188 get offlineAlwaysPrompt() { | |
| 189 return this._offlineAlwaysPrompt; | |
| 190 }, | |
| 191 | |
| 192 set offlineAlwaysPrompt(val) { | |
| 193 this._offlineAlwaysPrompt = val; | |
| 194 this.updateAdditionalAuth(); | |
| 195 }, | |
| 196 | |
| 197 /** Have we already gotten offline access from Google during this session?
*/ | |
| 198 offlineGranted: false, | |
| 199 | |
| 200 /** <google-js-api> */ | |
| 201 _apiLoader: null, | |
| 202 | |
| 203 /** an array of wanted scopes. oauth2 argument */ | |
| 204 _requestedScopeArray: [], | |
| 205 | |
| 206 /** _requestedScopeArray as string */ | |
| 207 get requestedScopes() { | |
| 208 return this._requestedScopeArray.join(' '); | |
| 209 }, | |
| 210 | |
| 211 /** Is auth library initalized? */ | |
| 212 _initialized: false, | |
| 213 | |
| 214 /** Is user signed in? */ | |
| 215 _signedIn: false, | |
| 216 | |
| 217 /** Currently granted scopes */ | |
| 218 _grantedScopeArray: [], | |
| 219 | |
| 220 /** True if additional authorization is required */ | |
| 221 _needAdditionalAuth: true, | |
| 222 | |
| 223 /** True if have google+ scopes */ | |
| 224 _hasPlusScopes: false, | |
| 225 | |
| 226 /** | |
| 227 * array of <google-signin-aware> | |
| 228 * state changes are broadcast to them | |
| 229 */ | |
| 230 signinAwares: [], | |
| 231 | |
| 232 init: function() { | |
| 233 this._apiLoader = document.createElement('google-js-api'); | |
| 234 this._apiLoader.addEventListener('js-api-load', this.loadAuth2.bind(this
)); | |
| 235 if (Polymer.Element) { | |
| 236 document.body.appendChild(this._apiLoader); | |
| 237 } | |
| 238 }, | |
| 239 | |
| 240 loadAuth2: function() { | |
| 241 gapi.load('auth2', this.initAuth2.bind(this)); | |
| 242 }, | |
| 243 | |
| 244 initAuth2: function() { | |
| 245 if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId)
{ | |
| 246 return; | |
| 247 } | |
| 248 var auth = gapi.auth2.init({ | |
| 249 'client_id': this.clientId, | |
| 250 'cookie_policy': this.cookiePolicy, | |
| 251 'scope': this.requestedScopes, | |
| 252 'hosted_domain': this.hostedDomain | |
| 253 }); | |
| 254 | |
| 255 auth['currentUser'].listen(this.handleUserUpdate.bind(this)); | |
| 256 | |
| 257 auth.then( | |
| 258 function onFulfilled() { | |
| 259 // Let the current user listener trigger the changes. | |
| 260 }, | |
| 261 function onRejected(error) { | |
| 262 console.error(error); | |
| 263 } | |
| 264 ); | |
| 265 }, | |
| 266 | |
| 267 handleUserUpdate: function(newPrimaryUser) { | |
| 268 // update and broadcast currentUser | |
| 269 var isSignedIn = newPrimaryUser.isSignedIn(); | |
| 270 if (isSignedIn != this._signedIn) { | |
| 271 this._signedIn = isSignedIn; | |
| 272 for (var i=0; i<this.signinAwares.length; i++) { | |
| 273 this.signinAwares[i]._setSignedIn(isSignedIn); | |
| 274 } | |
| 275 } | |
| 276 // update and broadcast initialized property the first time the isSigned
In property is set. | |
| 277 if(!this._initialized) { | |
| 278 for (var i=0; i<this.signinAwares.length; i++) { | |
| 279 this.signinAwares[i]._setInitialized(true); | |
| 280 } | |
| 281 this._initialized = true; | |
| 282 } | |
| 283 | |
| 284 | |
| 285 // update granted scopes | |
| 286 this._grantedScopeArray = this.strToScopeArray( | |
| 287 newPrimaryUser.getGrantedScopes()); | |
| 288 // console.log(this._grantedScopeArray); | |
| 289 this.updateAdditionalAuth(); | |
| 290 | |
| 291 var response = newPrimaryUser.getAuthResponse(); | |
| 292 for (var i=0; i<this.signinAwares.length; i++) { | |
| 293 this.signinAwares[i]._updateScopeStatus(response); | |
| 294 } | |
| 295 }, | |
| 296 | |
| 297 setOfflineCode: function(code) { | |
| 298 for (var i=0; i<this.signinAwares.length; i++) { | |
| 299 this.signinAwares[i]._updateOfflineCode(code); | |
| 300 } | |
| 301 }, | |
| 302 | |
| 303 /** convert scope string to scope array */ | |
| 304 strToScopeArray: function(str) { | |
| 305 if (!str) { | |
| 306 return []; | |
| 307 } | |
| 308 // remove extra spaces, then split | |
| 309 var scopes = str.replace(/\ +/g, ' ').trim().split(' '); | |
| 310 for (var i=0; i<scopes.length; i++) { | |
| 311 scopes[i] = scopes[i].toLowerCase(); | |
| 312 // Handle scopes that will be deprecated but are still returned with
their old value | |
| 313 if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.profile')
{ | |
| 314 scopes[i] = 'profile'; | |
| 315 } | |
| 316 if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.email') { | |
| 317 scopes[i] = 'email'; | |
| 318 } | |
| 319 } | |
| 320 // return with duplicates filtered out | |
| 321 return scopes.filter( function(value, index, self) { | |
| 322 return self.indexOf(value) === index; | |
| 323 }); | |
| 324 }, | |
| 325 | |
| 326 /** true if scopes have google+ scopes */ | |
| 327 isPlusScope: function(scope) { | |
| 328 return (scope.indexOf('/auth/games') > -1) | |
| 329 || (scope.indexOf('auth/plus.') > -1 && scope.indexOf('auth/plus.me'
) < 0); | |
| 330 }, | |
| 331 | |
| 332 /** true if scopes have been granted */ | |
| 333 hasGrantedScopes: function(scopeStr) { | |
| 334 var scopes = this.strToScopeArray(scopeStr); | |
| 335 for (var i=0; i< scopes.length; i++) { | |
| 336 if (this._grantedScopeArray.indexOf(scopes[i]) === -1) | |
| 337 return false; | |
| 338 } | |
| 339 return true; | |
| 340 }, | |
| 341 | |
| 342 /** request additional scopes */ | |
| 343 requestScopes: function(newScopeStr) { | |
| 344 var newScopes = this.strToScopeArray(newScopeStr); | |
| 345 var scopesUpdated = false; | |
| 346 for (var i=0; i<newScopes.length; i++) { | |
| 347 if (this._requestedScopeArray.indexOf(newScopes[i]) === -1) { | |
| 348 this._requestedScopeArray.push(newScopes[i]); | |
| 349 scopesUpdated = true; | |
| 350 } | |
| 351 } | |
| 352 if (scopesUpdated) { | |
| 353 this.updateAdditionalAuth(); | |
| 354 this.updatePlusScopes(); | |
| 355 } | |
| 356 }, | |
| 357 | |
| 358 /** update status of _needAdditionalAuth */ | |
| 359 updateAdditionalAuth: function() { | |
| 360 var needMoreAuth = false; | |
| 361 if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted)
{ | |
| 362 needMoreAuth = true; | |
| 363 } else { | |
| 364 for (var i=0; i<this._requestedScopeArray.length; i++) { | |
| 365 if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) ==
= -1) { | |
| 366 needMoreAuth = true; | |
| 367 break; | |
| 368 } | |
| 369 } | |
| 370 } | |
| 371 if (this._needAdditionalAuth != needMoreAuth) { | |
| 372 this._needAdditionalAuth = needMoreAuth; | |
| 373 // broadcast new value | |
| 374 for (var i=0; i<this.signinAwares.length; i++) { | |
| 375 this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth); | |
| 376 } | |
| 377 } | |
| 378 }, | |
| 379 | |
| 380 updatePlusScopes: function() { | |
| 381 var hasPlusScopes = false; | |
| 382 for (var i = 0; i < this._requestedScopeArray.length; i++) { | |
| 383 if (this.isPlusScope(this._requestedScopeArray[i])) { | |
| 384 hasPlusScopes = true; | |
| 385 break; | |
| 386 } | |
| 387 } | |
| 388 if (this._hasPlusScopes != hasPlusScopes) { | |
| 389 this._hasPlusScopes = hasPlusScopes; | |
| 390 for (var i=0; i<this.signinAwares.length; i++) { | |
| 391 this.signinAwares[i]._setHasPlusScopes(hasPlusScopes); | |
| 392 } | |
| 393 } | |
| 394 }, | |
| 395 /** | |
| 396 * attached <google-signin-aware> | |
| 397 * @param {!GoogleSigninAwareElement} aware element to add | |
| 398 */ | |
| 399 attachSigninAware: function(aware) { | |
| 400 if (this.signinAwares.indexOf(aware) == -1) { | |
| 401 this.signinAwares.push(aware); | |
| 402 // Initialize aware properties | |
| 403 aware._setNeedAdditionalAuth(this._needAdditionalAuth); | |
| 404 aware._setInitialized(this._initialized); | |
| 405 aware._setSignedIn(this._signedIn); | |
| 406 aware._setHasPlusScopes(this._hasPlusScopes); | |
| 407 } else { | |
| 408 console.warn('signinAware attached more than once', aware); | |
| 409 } | |
| 410 }, | |
| 411 | |
| 412 detachSigninAware: function(aware) { | |
| 413 var index = this.signinAwares.indexOf(aware); | |
| 414 if (index != -1) { | |
| 415 this.signinAwares.splice(index, 1); | |
| 416 } else { | |
| 417 console.warn('Trying to detach unattached signin-aware'); | |
| 418 } | |
| 419 }, | |
| 420 | |
| 421 /** returns scopes not granted */ | |
| 422 getMissingScopes: function() { | |
| 423 return this._requestedScopeArray.filter( function(scope) { | |
| 424 return this._grantedScopeArray.indexOf(scope) === -1; | |
| 425 }.bind(this)).join(' '); | |
| 426 }, | |
| 427 | |
| 428 assertAuthInitialized: function() { | |
| 429 if (!this.clientId) { | |
| 430 throw new Error("AuthEngine not initialized. clientId has not been con
figured."); | |
| 431 } | |
| 432 if (!('gapi' in window)) { | |
| 433 throw new Error("AuthEngine not initialized. gapi has not loaded."); | |
| 434 } | |
| 435 if (!('auth2' in window.gapi)) { | |
| 436 throw new Error("AuthEngine not initialized. auth2 not loaded."); | |
| 437 } | |
| 438 }, | |
| 439 | |
| 440 /** pops up sign-in dialog */ | |
| 441 signIn: function() { | |
| 442 this.assertAuthInitialized(); | |
| 443 var params = { | |
| 444 'scope': this.getMissingScopes() | |
| 445 }; | |
| 446 | |
| 447 // Proxy specific attributes through to the signIn options. | |
| 448 Object.keys(ProxyLoginAttributes).forEach(function(key) { | |
| 449 if (this[key] && this[key] !== '') { | |
| 450 params[ProxyLoginAttributes[key]] = this[key]; | |
| 451 } | |
| 452 }, this); | |
| 453 | |
| 454 var promise; | |
| 455 var user = gapi.auth2.getAuthInstance()['currentUser'].get(); | |
| 456 if (!(this.offline || this.offlineAlwaysPrompt)) { | |
| 457 if (user.getGrantedScopes()) { | |
| 458 // additional auth, skip multiple account dialog | |
| 459 promise = user.grant(params); | |
| 460 } else { | |
| 461 // initial signin | |
| 462 promise = gapi.auth2.getAuthInstance().signIn(params); | |
| 463 } | |
| 464 } else { | |
| 465 params.redirect_uri = 'postmessage'; | |
| 466 if (this.offlineAlwaysPrompt) { | |
| 467 params.approval_prompt = 'force'; | |
| 468 } | |
| 469 | |
| 470 // Despite being documented at https://goo.gl/tiO0Bk | |
| 471 // It doesn't seem like user.grantOfflineAccess() actually exists in | |
| 472 // the current version of the Google Sign-In JS client we're using | |
| 473 // through GoogleWebComponents. So in the offline case, we will not | |
| 474 // distinguish between a first auth and an additional one. | |
| 475 promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params); | |
| 476 } | |
| 477 promise.then( | |
| 478 function onFulfilled(response) { | |
| 479 // If login was offline, response contains one string "code" | |
| 480 // Otherwise it contains the user object already | |
| 481 var newUser; | |
| 482 if (response.code) { | |
| 483 AuthEngine.offlineGranted = true; | |
| 484 newUser = gapi.auth2.getAuthInstance()['currentUser'].get(); | |
| 485 AuthEngine.setOfflineCode(response.code); | |
| 486 } else { | |
| 487 newUser = response; | |
| 488 } | |
| 489 | |
| 490 var authResponse = newUser.getAuthResponse(); | |
| 491 // Let the current user listener trigger the changes. | |
| 492 }, | |
| 493 function onRejected(error) { | |
| 494 // Access denied is not an error, user hit cancel | |
| 495 if ("Access denied." !== error.reason) { | |
| 496 this.signinAwares.forEach(function(awareInstance) { | |
| 497 awareInstance.errorNotify(error); | |
| 498 }); | |
| 499 } | |
| 500 }.bind(this) | |
| 501 ); | |
| 502 }, | |
| 503 | |
| 504 /** signs user out */ | |
| 505 signOut: function() { | |
| 506 this.assertAuthInitialized(); | |
| 507 gapi.auth2.getAuthInstance().signOut().then( | |
| 508 function onFulfilled() { | |
| 509 // Let the current user listener trigger the changes. | |
| 510 }, | |
| 511 function onRejected(error) { | |
| 512 console.error(error); | |
| 513 } | |
| 514 ); | |
| 515 } | |
| 516 }; | |
| 517 | |
| 518 AuthEngine.init(); | |
| 519 | |
| 520 /** | |
| 521 `google-signin-aware` is used to enable authentication in custom elements by | |
| 522 interacting with a google-signin element that needs to be present somewhere | |
| 523 on the page. | |
| 524 | |
| 525 The `scopes` attribute allows you to specify which scope permissions are require
d | |
| 526 (e.g do you want to allow interaction with the Google Drive API). | |
| 527 | |
| 528 The `google-signin-aware-success` event is triggered when a user successfully | |
| 529 authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, succ
essful | |
| 530 authentication will also trigger the `google-signin-offline-success`event. | |
| 531 The `google-signin-aware-signed-out` event is triggered when a user explicitly | |
| 532 signs out via the google-signin element. | |
| 533 | |
| 534 You can bind to `isAuthorized` property to monitor authorization state. | |
| 535 ##### Example | |
| 536 | |
| 537 <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google
-signin-aware> | |
| 538 | |
| 539 | |
| 540 ##### Example with offline | |
| 541 <template id="awareness" is="dom-bind"> | |
| 542 <google-signin-aware | |
| 543 scopes="https://www.googleapis.com/auth/drive" | |
| 544 offline | |
| 545 on-google-signin-aware-success="handleSignin" | |
| 546 on-google-signin-offline-success="handleOffline"></google-signin-aware
> | |
| 547 <\/template> | |
| 548 <script> | |
| 549 var aware = document.querySelector('#awareness'); | |
| 550 aware.handleSignin = function(response) { | |
| 551 var user = gapi.auth2.getAuthInstance()['currentUser'].get(); | |
| 552 console.log('User name: ' + user.getBasicProfile().getName()); | |
| 553 }; | |
| 554 aware.handleOffline = function(response) { | |
| 555 console.log('Offline code received: ' + response.detail.code); | |
| 556 // Here you would POST response.detail.code to your webserver, which can | |
| 557 // exchange the authorization code for an access token. More info at: | |
| 558 // https://developers.google.com/identity/protocols/OAuth2WebServer | |
| 559 }; | |
| 560 <\/script> | |
| 561 */ | |
| 562 Polymer({ | |
| 563 | |
| 564 is: 'google-signin-aware', | |
| 565 | |
| 566 /** | |
| 567 * Fired when this scope has been authorized | |
| 568 * @param {Object} result Authorization result. | |
| 569 * @event google-signin-aware-success | |
| 570 */ | |
| 571 | |
| 572 /** | |
| 573 * Fired when an offline authorization is successful. | |
| 574 * @param {{code: string}} detail - | |
| 575 * code: The one-time authorization code from Google. | |
| 576 * Your application can exchange this for an `access_token` and `r
efresh_token` | |
| 577 * @event google-signin-offline-success | |
| 578 */ | |
| 579 | |
| 580 /** | |
| 581 * Fired when this scope is not authorized | |
| 582 * @event google-signin-aware-signed-out | |
| 583 */ | |
| 584 | |
| 585 /** | |
| 586 * Fired when there is an error during the signin flow. | |
| 587 * @param {Object} detail The error object returned from the OAuth 2 flow. | |
| 588 * @event google-signin-aware-error | |
| 589 */ | |
| 590 | |
| 591 /** | |
| 592 * This block is needed so the previous @param is not assigned to the next
property. | |
| 593 */ | |
| 594 | |
| 595 properties: { | |
| 596 /** | |
| 597 * App package name for android over-the-air installs. | |
| 598 * See the relevant [docs](https://developers.google.com/+/web/signin/an
droid-app-installs) | |
| 599 */ | |
| 600 appPackageName: { | |
| 601 type: String, | |
| 602 observer: '_appPackageNameChanged' | |
| 603 }, | |
| 604 | |
| 605 /** | |
| 606 * a Google Developers clientId reference | |
| 607 */ | |
| 608 clientId: { | |
| 609 type: String, | |
| 610 observer: '_clientIdChanged' | |
| 611 }, | |
| 612 | |
| 613 /** | |
| 614 * The cookie policy defines what URIs have access to the session cookie | |
| 615 * remembering the user's sign-in state. | |
| 616 * See the relevant [docs](https://developers.google.com/+/web/signin/re
ference#determining_a_value_for_cookie_policy) for more information. | |
| 617 * @default 'single_host_origin' | |
| 618 */ | |
| 619 cookiePolicy: { | |
| 620 type: String, | |
| 621 observer: '_cookiePolicyChanged' | |
| 622 }, | |
| 623 | |
| 624 /** | |
| 625 * The app activity types you want to write on behalf of the user | |
| 626 * (e.g http://schemas.google.com/AddActivity) | |
| 627 * | |
| 628 */ | |
| 629 requestVisibleActions: { | |
| 630 type: String, | |
| 631 observer: '_requestVisibleActionsChanged' | |
| 632 }, | |
| 633 | |
| 634 /** | |
| 635 * The Google Apps domain to which users must belong to sign in. | |
| 636 * See the relevant [docs](https://developers.google.com/identity/sign-i
n/web/reference) for more information. | |
| 637 */ | |
| 638 hostedDomain: { | |
| 639 type: String, | |
| 640 observer: '_hostedDomainChanged' | |
| 641 }, | |
| 642 | |
| 643 /** | |
| 644 * Allows for offline `access_token` retrieval during the signin process
. | |
| 645 * See also `offlineAlwaysPrompt`. You only need to set one of the two;
if both | |
| 646 * are set, the behavior of `offlineAlwaysPrompt` will override `offline
`. | |
| 647 */ | |
| 648 offline: { | |
| 649 type: Boolean, | |
| 650 value: false, | |
| 651 observer: '_offlineChanged' | |
| 652 }, | |
| 653 | |
| 654 /** | |
| 655 * Works the same as `offline` with the addition that it will always | |
| 656 * force a re-prompt to the user, guaranteeing that you will get a | |
| 657 * refresh_token even if the user has already granted offline access to | |
| 658 * this application. You only need to set one of `offline` or | |
| 659 * `offlineAlwaysPrompt`, not both. | |
| 660 */ | |
| 661 offlineAlwaysPrompt: { | |
| 662 type: Boolean, | |
| 663 value: false, | |
| 664 observer: '_offlineAlwaysPromptChanged' | |
| 665 }, | |
| 666 | |
| 667 /** | |
| 668 * The scopes to provide access to (e.g https://www.googleapis.com/auth/
drive) | |
| 669 * and should be space-delimited. | |
| 670 */ | |
| 671 scopes: { | |
| 672 type: String, | |
| 673 value: 'profile', | |
| 674 observer: '_scopesChanged' | |
| 675 }, | |
| 676 | |
| 677 /** | |
| 678 * Space-delimited, case-sensitive list of strings that | |
| 679 * specifies whether the the user is prompted for reauthentication | |
| 680 * and/or consent. The defined values are: | |
| 681 * none: do not display authentication or consent pages. | |
| 682 * This value is mutually exclusive with the rest. | |
| 683 * login: always prompt the user for reauthentication. | |
| 684 * consent: always show consent screen. | |
| 685 * select_account: always show account selection page. | |
| 686 * This enables a user who has multiple accounts to select amongst | |
| 687 * the multiple accounts that they might have current sessions for. | |
| 688 * For more information, see "prompt" parameter description in | |
| 689 * https://openid.net/specs/openid-connect-basic-1_0.html#RequestParamet
ers | |
| 690 */ | |
| 691 openidPrompt: { | |
| 692 type: String, | |
| 693 value: '', | |
| 694 observer: '_openidPromptChanged' | |
| 695 }, | |
| 696 | |
| 697 /** | |
| 698 * True when the auth library has been initialized, and signedIn propert
y value is set from the first api response. | |
| 699 */ | |
| 700 initialized: { | |
| 701 type: Boolean, | |
| 702 notify: true, | |
| 703 readOnly: true | |
| 704 }, | |
| 705 | |
| 706 /** | |
| 707 * True if user is signed in | |
| 708 */ | |
| 709 signedIn: { | |
| 710 type: Boolean, | |
| 711 notify: true, | |
| 712 readOnly: true | |
| 713 }, | |
| 714 | |
| 715 /** | |
| 716 * True if authorizations for *this* element have been granted | |
| 717 */ | |
| 718 isAuthorized: { | |
| 719 type: Boolean, | |
| 720 notify: true, | |
| 721 readOnly: true, | |
| 722 value: false | |
| 723 }, | |
| 724 | |
| 725 /** | |
| 726 * True if additional authorizations for *any* element are required | |
| 727 */ | |
| 728 needAdditionalAuth: { | |
| 729 type: Boolean, | |
| 730 notify: true, | |
| 731 readOnly: true | |
| 732 }, | |
| 733 | |
| 734 /** | |
| 735 * True if *any* element has google+ scopes | |
| 736 */ | |
| 737 hasPlusScopes: { | |
| 738 type: Boolean, | |
| 739 value: false, | |
| 740 notify: true, | |
| 741 readOnly: true | |
| 742 } | |
| 743 }, | |
| 744 | |
| 745 attached: function() { | |
| 746 AuthEngine.attachSigninAware(this); | |
| 747 }, | |
| 748 | |
| 749 detached: function() { | |
| 750 AuthEngine.detachSigninAware(this); | |
| 751 }, | |
| 752 | |
| 753 /** pops up the authorization dialog */ | |
| 754 signIn: function() { | |
| 755 AuthEngine.signIn(); | |
| 756 }, | |
| 757 | |
| 758 /** signs user out */ | |
| 759 signOut: function() { | |
| 760 AuthEngine.signOut(); | |
| 761 }, | |
| 762 | |
| 763 errorNotify: function(error) { | |
| 764 this.fire('google-signin-aware-error', error); | |
| 765 }, | |
| 766 | |
| 767 _appPackageNameChanged: function(newName, oldName) { | |
| 768 AuthEngine.appPackageName = newName; | |
| 769 }, | |
| 770 | |
| 771 _clientIdChanged: function(newId, oldId) { | |
| 772 AuthEngine.clientId = newId; | |
| 773 }, | |
| 774 | |
| 775 _cookiePolicyChanged: function(newPolicy, oldPolicy) { | |
| 776 AuthEngine.cookiePolicy = newPolicy; | |
| 777 }, | |
| 778 | |
| 779 _requestVisibleActionsChanged: function(newVal, oldVal) { | |
| 780 AuthEngine.requestVisibleActions = newVal; | |
| 781 }, | |
| 782 | |
| 783 _hostedDomainChanged: function(newVal, oldVal) { | |
| 784 AuthEngine.hostedDomain = newVal; | |
| 785 }, | |
| 786 | |
| 787 _offlineChanged: function(newVal, oldVal) { | |
| 788 AuthEngine.offline = newVal; | |
| 789 }, | |
| 790 | |
| 791 _offlineAlwaysPromptChanged: function(newVal, oldVal) { | |
| 792 AuthEngine.offlineAlwaysPrompt = newVal; | |
| 793 }, | |
| 794 | |
| 795 _scopesChanged: function(newVal, oldVal) { | |
| 796 AuthEngine.requestScopes(newVal); | |
| 797 this._updateScopeStatus(undefined); | |
| 798 }, | |
| 799 | |
| 800 _openidPromptChanged: function(newVal, oldVal) { | |
| 801 AuthEngine.openidPrompt = newVal; | |
| 802 }, | |
| 803 | |
| 804 _updateScopeStatus: function(user) { | |
| 805 var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.sc
opes); | |
| 806 if (newAuthorized !== this.isAuthorized) { | |
| 807 this._setIsAuthorized(newAuthorized); | |
| 808 if (newAuthorized) { | |
| 809 this.fire('google-signin-aware-success', user); | |
| 810 } | |
| 811 else { | |
| 812 this.fire('google-signin-aware-signed-out', user); | |
| 813 } | |
| 814 } | |
| 815 }, | |
| 816 | |
| 817 _updateOfflineCode: function(code) { | |
| 818 if (code) { | |
| 819 this.fire('google-signin-offline-success', {code: code}); | |
| 820 } | |
| 821 } | |
| 822 }); | |
| 823 })(); | |
| 824 </script> | |
| OLD | NEW |