| <!-- |
| Copyright 2014 Google Inc |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| https://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <link rel="import" href="../polymer/polymer.html"> |
| <link rel="import" href="../google-apis/google-js-api.html"> |
| |
| <script> |
| (function() { |
| |
| /** |
| * Enum of attributes to be passed through to the login API call. |
| * @readonly |
| * @enum {string} |
| */ |
| var ProxyLoginAttributes = { |
| 'appPackageName': 'apppackagename', |
| 'clientId': 'clientid', |
| 'cookiePolicy': 'cookiepolicy', |
| 'hostedDomain': 'hostedDomain', |
| 'openidPrompt': 'prompt', |
| 'requestVisibleActions': 'requestvisibleactions' |
| }; |
| |
| /** |
| * AuthEngine does all interactions with gapi.auth2 |
| * |
| * It is tightly coupled with <google-signin-aware> element |
| * The elements configure AuthEngine. |
| * AuthEngine propagates all authentication events to all google-signin-aware elements |
| * |
| * API used: https://developers.google.com/identity/sign-in/web/reference |
| * |
| */ |
| var AuthEngine = { |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _clientId: null, |
| |
| get clientId() { |
| return this._clientId; |
| }, |
| |
| set clientId(val) { |
| if (this._clientId && val && val != this._clientId) { |
| throw new Error('clientId cannot change. Values do not match. New: ' + val + ' Old:' + this._clientId); |
| } |
| if (val && val != this._clientId) { |
| this._clientId = val; |
| this.initAuth2(); |
| } |
| }, |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _cookiePolicy: 'single_host_origin', |
| |
| get cookiePolicy() { |
| return this._cookiePolicy; |
| }, |
| |
| set cookiePolicy(val) { |
| if (val) { |
| this._cookiePolicy = val; |
| } |
| }, |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _appPackageName: '', |
| |
| get appPackageName() { |
| return this._appPackageName; |
| }, |
| |
| set appPackageName(val) { |
| if (this._appPackageName && val && val != this._appPackageName) { |
| throw new Error('appPackageName cannot change. Values do not match. New: ' + val + ' Old: ' + this._appPackageName); |
| } |
| if (val) { |
| this._appPackageName = val; |
| } |
| }, |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _requestVisibleActions: '', |
| |
| get requestVisibleactions() { |
| return this._requestVisibleActions; |
| }, |
| |
| set requestVisibleactions(val) { |
| if (this._requestVisibleActions && val && val != this._requestVisibleActions) { |
| throw new Error('requestVisibleactions cannot change. Values do not match. New: ' + val + ' Old: ' + this._requestVisibleActions); |
| } |
| if (val) |
| this._requestVisibleActions = val; |
| }, |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _hostedDomain: '', |
| |
| get hostedDomain() { |
| return this._hostedDomain; |
| }, |
| |
| set hostedDomain(val) { |
| if (this._hostedDomain && val && val != this._hostedDomain) { |
| throw new Error('hostedDomain cannot change. Values do not match. New: ' + val + ' Old: ' + this._hostedDomain); |
| } |
| if (val) |
| this._hostedDomain = val; |
| }, |
| |
| /** |
| * oauth2 argument, set by google-signin-aware |
| */ |
| _openidPrompt: '', |
| |
| get openidPrompt() { |
| return this._openidPrompt; |
| }, |
| |
| set openidPrompt(val) { |
| if (typeof val !== 'string') { |
| throw new Error( |
| 'openidPrompt must be a string. Received ' + typeof val); |
| } |
| if (val) { |
| var values = val.split(' '); |
| values = values.map(function(v) { |
| return v.trim(); |
| }); |
| values = values.filter(function(v) { |
| return v; |
| }); |
| var validValues = {none: 0, login: 0, consent: 0, select_account: 0}; |
| values.forEach(function(v) { |
| if (v == 'none' && values.length > 1) { |
| throw new Error( |
| 'none cannot be combined with other openidPrompt values'); |
| } |
| if (!(v in validValues)) { |
| throw new Error( |
| 'invalid openidPrompt value ' + v + |
| '. Valid values: ' + Object.keys(validValues).join(', ')); |
| } |
| }); |
| } |
| this._openidPrompt = val; |
| }, |
| |
| /** Is offline access currently enabled in the google-signin-aware element? */ |
| _offline: false, |
| |
| get offline() { |
| return this._offline; |
| }, |
| |
| set offline(val) { |
| this._offline = val; |
| this.updateAdditionalAuth(); |
| }, |
| |
| /** Should we force a re-prompt for offline access? */ |
| _offlineAlwaysPrompt: false, |
| |
| get offlineAlwaysPrompt() { |
| return this._offlineAlwaysPrompt; |
| }, |
| |
| set offlineAlwaysPrompt(val) { |
| this._offlineAlwaysPrompt = val; |
| this.updateAdditionalAuth(); |
| }, |
| |
| /** Have we already gotten offline access from Google during this session? */ |
| offlineGranted: false, |
| |
| /** <google-js-api> */ |
| _apiLoader: null, |
| |
| /** an array of wanted scopes. oauth2 argument */ |
| _requestedScopeArray: [], |
| |
| /** _requestedScopeArray as string */ |
| get requestedScopes() { |
| return this._requestedScopeArray.join(' '); |
| }, |
| |
| /** Is auth library initalized? */ |
| _initialized: false, |
| |
| /** Is user signed in? */ |
| _signedIn: false, |
| |
| /** Currently granted scopes */ |
| _grantedScopeArray: [], |
| |
| /** True if additional authorization is required */ |
| _needAdditionalAuth: true, |
| |
| /** True if have google+ scopes */ |
| _hasPlusScopes: false, |
| |
| /** |
| * array of <google-signin-aware> |
| * state changes are broadcast to them |
| */ |
| signinAwares: [], |
| |
| init: function() { |
| this._apiLoader = document.createElement('google-js-api'); |
| this._apiLoader.addEventListener('js-api-load', this.loadAuth2.bind(this)); |
| if (Polymer.Element) { |
| document.body.appendChild(this._apiLoader); |
| } |
| }, |
| |
| loadAuth2: function() { |
| gapi.load('auth2', this.initAuth2.bind(this)); |
| }, |
| |
| initAuth2: function() { |
| if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId) { |
| return; |
| } |
| var auth = gapi.auth2.init({ |
| 'client_id': this.clientId, |
| 'cookie_policy': this.cookiePolicy, |
| 'scope': this.requestedScopes, |
| 'hosted_domain': this.hostedDomain |
| }); |
| |
| auth['currentUser'].listen(this.handleUserUpdate.bind(this)); |
| |
| auth.then( |
| function onFulfilled() { |
| // Let the current user listener trigger the changes. |
| }, |
| function onRejected(error) { |
| console.error(error); |
| } |
| ); |
| }, |
| |
| handleUserUpdate: function(newPrimaryUser) { |
| // update and broadcast currentUser |
| var isSignedIn = newPrimaryUser.isSignedIn(); |
| if (isSignedIn != this._signedIn) { |
| this._signedIn = isSignedIn; |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._setSignedIn(isSignedIn); |
| } |
| } |
| // update and broadcast initialized property the first time the isSignedIn property is set. |
| if(!this._initialized) { |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._setInitialized(true); |
| } |
| this._initialized = true; |
| } |
| |
| |
| // update granted scopes |
| this._grantedScopeArray = this.strToScopeArray( |
| newPrimaryUser.getGrantedScopes()); |
| // console.log(this._grantedScopeArray); |
| this.updateAdditionalAuth(); |
| |
| var response = newPrimaryUser.getAuthResponse(); |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._updateScopeStatus(response); |
| } |
| }, |
| |
| setOfflineCode: function(code) { |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._updateOfflineCode(code); |
| } |
| }, |
| |
| /** convert scope string to scope array */ |
| strToScopeArray: function(str) { |
| if (!str) { |
| return []; |
| } |
| // remove extra spaces, then split |
| var scopes = str.replace(/\ +/g, ' ').trim().split(' '); |
| for (var i=0; i<scopes.length; i++) { |
| scopes[i] = scopes[i].toLowerCase(); |
| // Handle scopes that will be deprecated but are still returned with their old value |
| if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.profile') { |
| scopes[i] = 'profile'; |
| } |
| if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.email') { |
| scopes[i] = 'email'; |
| } |
| } |
| // return with duplicates filtered out |
| return scopes.filter( function(value, index, self) { |
| return self.indexOf(value) === index; |
| }); |
| }, |
| |
| /** true if scopes have google+ scopes */ |
| isPlusScope: function(scope) { |
| return (scope.indexOf('/auth/games') > -1) |
| || (scope.indexOf('auth/plus.') > -1 && scope.indexOf('auth/plus.me') < 0); |
| }, |
| |
| /** true if scopes have been granted */ |
| hasGrantedScopes: function(scopeStr) { |
| var scopes = this.strToScopeArray(scopeStr); |
| for (var i=0; i< scopes.length; i++) { |
| if (this._grantedScopeArray.indexOf(scopes[i]) === -1) |
| return false; |
| } |
| return true; |
| }, |
| |
| /** request additional scopes */ |
| requestScopes: function(newScopeStr) { |
| var newScopes = this.strToScopeArray(newScopeStr); |
| var scopesUpdated = false; |
| for (var i=0; i<newScopes.length; i++) { |
| if (this._requestedScopeArray.indexOf(newScopes[i]) === -1) { |
| this._requestedScopeArray.push(newScopes[i]); |
| scopesUpdated = true; |
| } |
| } |
| if (scopesUpdated) { |
| this.updateAdditionalAuth(); |
| this.updatePlusScopes(); |
| } |
| }, |
| |
| /** update status of _needAdditionalAuth */ |
| updateAdditionalAuth: function() { |
| var needMoreAuth = false; |
| if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted) { |
| needMoreAuth = true; |
| } else { |
| for (var i=0; i<this._requestedScopeArray.length; i++) { |
| if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) === -1) { |
| needMoreAuth = true; |
| break; |
| } |
| } |
| } |
| if (this._needAdditionalAuth != needMoreAuth) { |
| this._needAdditionalAuth = needMoreAuth; |
| // broadcast new value |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth); |
| } |
| } |
| }, |
| |
| updatePlusScopes: function() { |
| var hasPlusScopes = false; |
| for (var i = 0; i < this._requestedScopeArray.length; i++) { |
| if (this.isPlusScope(this._requestedScopeArray[i])) { |
| hasPlusScopes = true; |
| break; |
| } |
| } |
| if (this._hasPlusScopes != hasPlusScopes) { |
| this._hasPlusScopes = hasPlusScopes; |
| for (var i=0; i<this.signinAwares.length; i++) { |
| this.signinAwares[i]._setHasPlusScopes(hasPlusScopes); |
| } |
| } |
| }, |
| /** |
| * attached <google-signin-aware> |
| * @param {!GoogleSigninAwareElement} aware element to add |
| */ |
| attachSigninAware: function(aware) { |
| if (this.signinAwares.indexOf(aware) == -1) { |
| this.signinAwares.push(aware); |
| // Initialize aware properties |
| aware._setNeedAdditionalAuth(this._needAdditionalAuth); |
| aware._setInitialized(this._initialized); |
| aware._setSignedIn(this._signedIn); |
| aware._setHasPlusScopes(this._hasPlusScopes); |
| } else { |
| console.warn('signinAware attached more than once', aware); |
| } |
| }, |
| |
| detachSigninAware: function(aware) { |
| var index = this.signinAwares.indexOf(aware); |
| if (index != -1) { |
| this.signinAwares.splice(index, 1); |
| } else { |
| console.warn('Trying to detach unattached signin-aware'); |
| } |
| }, |
| |
| /** returns scopes not granted */ |
| getMissingScopes: function() { |
| return this._requestedScopeArray.filter( function(scope) { |
| return this._grantedScopeArray.indexOf(scope) === -1; |
| }.bind(this)).join(' '); |
| }, |
| |
| assertAuthInitialized: function() { |
| if (!this.clientId) { |
| throw new Error("AuthEngine not initialized. clientId has not been configured."); |
| } |
| if (!('gapi' in window)) { |
| throw new Error("AuthEngine not initialized. gapi has not loaded."); |
| } |
| if (!('auth2' in window.gapi)) { |
| throw new Error("AuthEngine not initialized. auth2 not loaded."); |
| } |
| }, |
| |
| /** pops up sign-in dialog */ |
| signIn: function() { |
| this.assertAuthInitialized(); |
| var params = { |
| 'scope': this.getMissingScopes() |
| }; |
| |
| // Proxy specific attributes through to the signIn options. |
| Object.keys(ProxyLoginAttributes).forEach(function(key) { |
| if (this[key] && this[key] !== '') { |
| params[ProxyLoginAttributes[key]] = this[key]; |
| } |
| }, this); |
| |
| var promise; |
| var user = gapi.auth2.getAuthInstance()['currentUser'].get(); |
| if (!(this.offline || this.offlineAlwaysPrompt)) { |
| if (user.getGrantedScopes()) { |
| // additional auth, skip multiple account dialog |
| promise = user.grant(params); |
| } else { |
| // initial signin |
| promise = gapi.auth2.getAuthInstance().signIn(params); |
| } |
| } else { |
| params.redirect_uri = 'postmessage'; |
| if (this.offlineAlwaysPrompt) { |
| params.approval_prompt = 'force'; |
| } |
| |
| // Despite being documented at https://goo.gl/tiO0Bk |
| // It doesn't seem like user.grantOfflineAccess() actually exists in |
| // the current version of the Google Sign-In JS client we're using |
| // through GoogleWebComponents. So in the offline case, we will not |
| // distinguish between a first auth and an additional one. |
| promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params); |
| } |
| promise.then( |
| function onFulfilled(response) { |
| // If login was offline, response contains one string "code" |
| // Otherwise it contains the user object already |
| var newUser; |
| if (response.code) { |
| AuthEngine.offlineGranted = true; |
| newUser = gapi.auth2.getAuthInstance()['currentUser'].get(); |
| AuthEngine.setOfflineCode(response.code); |
| } else { |
| newUser = response; |
| } |
| |
| var authResponse = newUser.getAuthResponse(); |
| // Let the current user listener trigger the changes. |
| }, |
| function onRejected(error) { |
| // Access denied is not an error, user hit cancel |
| if ("Access denied." !== error.reason) { |
| this.signinAwares.forEach(function(awareInstance) { |
| awareInstance.errorNotify(error); |
| }); |
| } |
| }.bind(this) |
| ); |
| }, |
| |
| /** signs user out */ |
| signOut: function() { |
| this.assertAuthInitialized(); |
| gapi.auth2.getAuthInstance().signOut().then( |
| function onFulfilled() { |
| // Let the current user listener trigger the changes. |
| }, |
| function onRejected(error) { |
| console.error(error); |
| } |
| ); |
| } |
| }; |
| |
| AuthEngine.init(); |
| |
| /** |
| `google-signin-aware` is used to enable authentication in custom elements by |
| interacting with a google-signin element that needs to be present somewhere |
| on the page. |
| |
| The `scopes` attribute allows you to specify which scope permissions are required |
| (e.g do you want to allow interaction with the Google Drive API). |
| |
| The `google-signin-aware-success` event is triggered when a user successfully |
| authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, successful |
| authentication will also trigger the `google-signin-offline-success`event. |
| The `google-signin-aware-signed-out` event is triggered when a user explicitly |
| signs out via the google-signin element. |
| |
| You can bind to `isAuthorized` property to monitor authorization state. |
| ##### Example |
| |
| <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google-signin-aware> |
| |
| |
| ##### Example with offline |
| <template id="awareness" is="dom-bind"> |
| <google-signin-aware |
| scopes="https://www.googleapis.com/auth/drive" |
| offline |
| on-google-signin-aware-success="handleSignin" |
| on-google-signin-offline-success="handleOffline"></google-signin-aware> |
| <\/template> |
| <script> |
| var aware = document.querySelector('#awareness'); |
| aware.handleSignin = function(response) { |
| var user = gapi.auth2.getAuthInstance()['currentUser'].get(); |
| console.log('User name: ' + user.getBasicProfile().getName()); |
| }; |
| aware.handleOffline = function(response) { |
| console.log('Offline code received: ' + response.detail.code); |
| // Here you would POST response.detail.code to your webserver, which can |
| // exchange the authorization code for an access token. More info at: |
| // https://developers.google.com/identity/protocols/OAuth2WebServer |
| }; |
| <\/script> |
| */ |
| Polymer({ |
| |
| is: 'google-signin-aware', |
| |
| /** |
| * Fired when this scope has been authorized |
| * @param {Object} result Authorization result. |
| * @event google-signin-aware-success |
| */ |
| |
| /** |
| * Fired when an offline authorization is successful. |
| * @param {{code: string}} detail - |
| * code: The one-time authorization code from Google. |
| * Your application can exchange this for an `access_token` and `refresh_token` |
| * @event google-signin-offline-success |
| */ |
| |
| /** |
| * Fired when this scope is not authorized |
| * @event google-signin-aware-signed-out |
| */ |
| |
| /** |
| * Fired when there is an error during the signin flow. |
| * @param {Object} detail The error object returned from the OAuth 2 flow. |
| * @event google-signin-aware-error |
| */ |
| |
| /** |
| * This block is needed so the previous @param is not assigned to the next property. |
| */ |
| |
| properties: { |
| /** |
| * App package name for android over-the-air installs. |
| * See the relevant [docs](https://developers.google.com/+/web/signin/android-app-installs) |
| */ |
| appPackageName: { |
| type: String, |
| observer: '_appPackageNameChanged' |
| }, |
| |
| /** |
| * a Google Developers clientId reference |
| */ |
| clientId: { |
| type: String, |
| observer: '_clientIdChanged' |
| }, |
| |
| /** |
| * The cookie policy defines what URIs have access to the session cookie |
| * remembering the user's sign-in state. |
| * See the relevant [docs](https://developers.google.com/+/web/signin/reference#determining_a_value_for_cookie_policy) for more information. |
| * @default 'single_host_origin' |
| */ |
| cookiePolicy: { |
| type: String, |
| observer: '_cookiePolicyChanged' |
| }, |
| |
| /** |
| * The app activity types you want to write on behalf of the user |
| * (e.g http://schemas.google.com/AddActivity) |
| * |
| */ |
| requestVisibleActions: { |
| type: String, |
| observer: '_requestVisibleActionsChanged' |
| }, |
| |
| /** |
| * The Google Apps domain to which users must belong to sign in. |
| * See the relevant [docs](https://developers.google.com/identity/sign-in/web/reference) for more information. |
| */ |
| hostedDomain: { |
| type: String, |
| observer: '_hostedDomainChanged' |
| }, |
| |
| /** |
| * Allows for offline `access_token` retrieval during the signin process. |
| * See also `offlineAlwaysPrompt`. You only need to set one of the two; if both |
| * are set, the behavior of `offlineAlwaysPrompt` will override `offline`. |
| */ |
| offline: { |
| type: Boolean, |
| value: false, |
| observer: '_offlineChanged' |
| }, |
| |
| /** |
| * Works the same as `offline` with the addition that it will always |
| * force a re-prompt to the user, guaranteeing that you will get a |
| * refresh_token even if the user has already granted offline access to |
| * this application. You only need to set one of `offline` or |
| * `offlineAlwaysPrompt`, not both. |
| */ |
| offlineAlwaysPrompt: { |
| type: Boolean, |
| value: false, |
| observer: '_offlineAlwaysPromptChanged' |
| }, |
| |
| /** |
| * The scopes to provide access to (e.g https://www.googleapis.com/auth/drive) |
| * and should be space-delimited. |
| */ |
| scopes: { |
| type: String, |
| value: 'profile', |
| observer: '_scopesChanged' |
| }, |
| |
| /** |
| * Space-delimited, case-sensitive list of strings that |
| * specifies whether the the user is prompted for reauthentication |
| * and/or consent. The defined values are: |
| * none: do not display authentication or consent pages. |
| * This value is mutually exclusive with the rest. |
| * login: always prompt the user for reauthentication. |
| * consent: always show consent screen. |
| * select_account: always show account selection page. |
| * This enables a user who has multiple accounts to select amongst |
| * the multiple accounts that they might have current sessions for. |
| * For more information, see "prompt" parameter description in |
| * https://openid.net/specs/openid-connect-basic-1_0.html#RequestParameters |
| */ |
| openidPrompt: { |
| type: String, |
| value: '', |
| observer: '_openidPromptChanged' |
| }, |
| |
| /** |
| * True when the auth library has been initialized, and signedIn property value is set from the first api response. |
| */ |
| initialized: { |
| type: Boolean, |
| notify: true, |
| readOnly: true |
| }, |
| |
| /** |
| * True if user is signed in |
| */ |
| signedIn: { |
| type: Boolean, |
| notify: true, |
| readOnly: true |
| }, |
| |
| /** |
| * True if authorizations for *this* element have been granted |
| */ |
| isAuthorized: { |
| type: Boolean, |
| notify: true, |
| readOnly: true, |
| value: false |
| }, |
| |
| /** |
| * True if additional authorizations for *any* element are required |
| */ |
| needAdditionalAuth: { |
| type: Boolean, |
| notify: true, |
| readOnly: true |
| }, |
| |
| /** |
| * True if *any* element has google+ scopes |
| */ |
| hasPlusScopes: { |
| type: Boolean, |
| value: false, |
| notify: true, |
| readOnly: true |
| } |
| }, |
| |
| attached: function() { |
| AuthEngine.attachSigninAware(this); |
| }, |
| |
| detached: function() { |
| AuthEngine.detachSigninAware(this); |
| }, |
| |
| /** pops up the authorization dialog */ |
| signIn: function() { |
| AuthEngine.signIn(); |
| }, |
| |
| /** signs user out */ |
| signOut: function() { |
| AuthEngine.signOut(); |
| }, |
| |
| errorNotify: function(error) { |
| this.fire('google-signin-aware-error', error); |
| }, |
| |
| _appPackageNameChanged: function(newName, oldName) { |
| AuthEngine.appPackageName = newName; |
| }, |
| |
| _clientIdChanged: function(newId, oldId) { |
| AuthEngine.clientId = newId; |
| }, |
| |
| _cookiePolicyChanged: function(newPolicy, oldPolicy) { |
| AuthEngine.cookiePolicy = newPolicy; |
| }, |
| |
| _requestVisibleActionsChanged: function(newVal, oldVal) { |
| AuthEngine.requestVisibleActions = newVal; |
| }, |
| |
| _hostedDomainChanged: function(newVal, oldVal) { |
| AuthEngine.hostedDomain = newVal; |
| }, |
| |
| _offlineChanged: function(newVal, oldVal) { |
| AuthEngine.offline = newVal; |
| }, |
| |
| _offlineAlwaysPromptChanged: function(newVal, oldVal) { |
| AuthEngine.offlineAlwaysPrompt = newVal; |
| }, |
| |
| _scopesChanged: function(newVal, oldVal) { |
| AuthEngine.requestScopes(newVal); |
| this._updateScopeStatus(undefined); |
| }, |
| |
| _openidPromptChanged: function(newVal, oldVal) { |
| AuthEngine.openidPrompt = newVal; |
| }, |
| |
| _updateScopeStatus: function(user) { |
| var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.scopes); |
| if (newAuthorized !== this.isAuthorized) { |
| this._setIsAuthorized(newAuthorized); |
| if (newAuthorized) { |
| this.fire('google-signin-aware-success', user); |
| } |
| else { |
| this.fire('google-signin-aware-signed-out', user); |
| } |
| } |
| }, |
| |
| _updateOfflineCode: function(code) { |
| if (code) { |
| this.fire('google-signin-offline-success', {code: code}); |
| } |
| } |
| }); |
| })(); |
| </script> |