@@ -60,7 +60,7 @@ if (module) {
6060 module . exports = {
6161 createService : createService ,
6262 getRedirectUri : getRedirectUri
63- }
63+ } ;
6464}
6565
6666// Copyright 2014 Google Inc. All Rights Reserved.
@@ -81,6 +81,10 @@ if (module) {
8181 * @fileoverview Contains the Service_ class.
8282 */
8383
84+ // Disable JSHint warnings for the use of eval(), since it's required to prevent
85+ // scope issues in Apps Script.
86+ // jshint evil:true
87+
8488/**
8589 * Creates a new OAuth2 service.
8690 * @param {string } serviceName The name of the service.
@@ -148,6 +152,16 @@ Service_.prototype.setTokenHeaders = function(tokenHeaders) {
148152 return this ;
149153} ;
150154
155+ /**
156+ * Sets an additional function to invoke on the payload of the access token request.
157+ * @param Object tokenHandler A function to invoke on the payload of the request for an access token.
158+ * @return {Service_ } This service, for chaining.
159+ */
160+ Service_ . prototype . setTokenPayloadHandler = function ( tokenHandler ) {
161+ this . tokenPayloadHandler_ = tokenHandler ;
162+ return this ;
163+ } ;
164+
151165/**
152166 * Sets the project key of the script that contains the authorization callback function (required).
153167 * The project key can be found in the Script Editor UI under "File > Project properties".
@@ -235,7 +249,7 @@ Service_.prototype.setCache = function(cache) {
235249 */
236250Service_ . prototype . setScope = function ( scope , opt_separator ) {
237251 var separator = opt_separator || ' ' ;
238- this . params_ [ ' scope' ] = _ . isArray ( scope ) ? scope . join ( separator ) : scope ;
252+ this . params_ . scope = _ . isArray ( scope ) ? scope . join ( separator ) : scope ;
239253 return this ;
240254} ;
241255
@@ -352,16 +366,21 @@ Service_.prototype.handleCallback = function(callbackRequest) {
352366 if ( this . tokenHeaders_ ) {
353367 headers = _ . extend ( headers , this . tokenHeaders_ ) ;
354368 }
369+ var tokenPayload = {
370+ code : code ,
371+ client_id : this . clientId_ ,
372+ client_secret : this . clientSecret_ ,
373+ redirect_uri : redirectUri ,
374+ grant_type : 'authorization_code'
375+ } ;
376+ if ( this . tokenPayloadHandler_ ) {
377+ tokenPayload = this . tokenPayloadHandler_ ( tokenPayload ) ;
378+ Logger . log ( 'Token payload from tokenPayloadHandler: %s' , JSON . stringify ( tokenPayload ) ) ;
379+ }
355380 var response = UrlFetchApp . fetch ( this . tokenUrl_ , {
356381 method : 'post' ,
357382 headers : headers ,
358- payload : {
359- code : code ,
360- client_id : this . clientId_ ,
361- client_secret : this . clientSecret_ ,
362- redirect_uri : redirectUri ,
363- grant_type : 'authorization_code'
364- } ,
383+ payload : tokenPayload ,
365384 muteHttpExceptions : true
366385 } ) ;
367386 var token = this . getTokenFromResponse_ ( response ) ;
@@ -441,7 +460,7 @@ Service_.prototype.getLastError = function() {
441460Service_ . prototype . getTokenFromResponse_ = function ( response ) {
442461 var token = this . parseToken_ ( response . getContentText ( ) ) ;
443462 if ( response . getResponseCode ( ) != 200 || token . error ) {
444- var reason = [ token . error , token . error_description , token . error_uri ] . filter ( Boolean ) . join ( ', ' ) ;
463+ var reason = [ token . error , token . message , token . error_description , token . error_uri ] . filter ( Boolean ) . join ( ', ' ) ;
445464 if ( ! reason ) {
446465 reason = response . getResponseCode ( ) + ': ' + JSON . stringify ( token ) ;
447466 }
@@ -464,7 +483,7 @@ Service_.prototype.parseToken_ = function(content) {
464483 } catch ( e ) {
465484 throw 'Token response not valid JSON: ' + e ;
466485 }
467- } else if ( this . tokenFormat_ = TOKEN_FORMAT . FORM_URL_ENCODED ) {
486+ } else if ( this . tokenFormat_ == TOKEN_FORMAT . FORM_URL_ENCODED ) {
468487 token = content . split ( '&' ) . reduce ( function ( result , pair ) {
469488 var parts = pair . split ( '=' ) ;
470489 result [ decodeURIComponent ( parts [ 0 ] ) ] = decodeURIComponent ( parts [ 1 ] ) ;
@@ -497,15 +516,20 @@ Service_.prototype.refresh = function() {
497516 if ( this . tokenHeaders_ ) {
498517 headers = _ . extend ( headers , this . tokenHeaders_ ) ;
499518 }
500- var response = UrlFetchApp . fetch ( this . tokenUrl_ , {
501- method : 'post' ,
502- headers : headers ,
503- payload : {
519+ var tokenPayload = {
504520 refresh_token : token . refresh_token ,
505521 client_id : this . clientId_ ,
506522 client_secret : this . clientSecret_ ,
507523 grant_type : 'refresh_token'
508- } ,
524+ } ;
525+ if ( this . tokenPayloadHandler_ ) {
526+ tokenPayload = this . tokenPayloadHandler_ ( tokenPayload ) ;
527+ Logger . log ( 'Token payload from tokenPayloadHandler (refresh): %s' , JSON . stringify ( tokenPayload ) ) ;
528+ }
529+ var response = UrlFetchApp . fetch ( this . tokenUrl_ , {
530+ method : 'post' ,
531+ headers : headers ,
532+ payload : tokenPayload ,
509533 muteHttpExceptions : true
510534 } ) ;
511535 var newToken = this . getTokenFromResponse_ ( response ) ;
@@ -639,10 +663,10 @@ Service_.prototype.createJwt_ = function() {
639663 iat : Math . round ( now . getTime ( ) / 1000 )
640664 } ;
641665 if ( this . subject_ ) {
642- claimSet [ ' sub' ] = this . subject_ ;
666+ claimSet . sub = this . subject_ ;
643667 }
644- if ( this . params_ [ ' scope' ] ) {
645- claimSet [ ' scope' ] = this . params_ [ ' scope' ] ;
668+ if ( this . params_ . scope ) {
669+ claimSet . scope = this . params_ . scope ;
646670 }
647671 var toSign = Utilities . base64EncodeWebSafe ( JSON . stringify ( header ) ) + '.' + Utilities . base64EncodeWebSafe ( JSON . stringify ( claimSet ) ) ;
648672 var signatureBytes = Utilities . computeRsaSha256Signature ( toSign , this . privateKey_ ) ;
@@ -705,7 +729,7 @@ function validate_(params) {
705729 * @private
706730 */
707731function isEmpty_ ( value ) {
708- return value == null || value == undefined ||
732+ return value === null || value = == undefined ||
709733 ( ( _ . isObject ( value ) || _ . isString ( value ) ) && _ . isEmpty ( value ) ) ;
710734}
711735
0 commit comments