@@ -48,15 +48,15 @@ function createService(serviceName) {
48
48
/**
49
49
* Returns the redirect URI that will be used for a given script. Often this URI
50
50
* needs to be entered into a configuration screen of your OAuth provider.
51
- * @param {string } [ optScriptId] The script ID of your script, which can be
51
+ * @param {string= } optScriptId The script ID of your script, which can be
52
52
* found in the Script Editor UI under "File > Project properties". Defaults
53
53
* to the script ID of the script being executed.
54
54
* @return {string } The redirect URI.
55
55
*/
56
56
function getRedirectUri ( optScriptId ) {
57
57
var scriptId = optScriptId || ScriptApp . getScriptId ( ) ;
58
58
return 'https://script.google.com/macros/d/' + encodeURIComponent ( scriptId ) +
59
- '/usercallback' ;
59
+ '/usercallback' ;
60
60
}
61
61
62
62
/**
@@ -228,7 +228,7 @@ Service_.prototype.setCodeVerififer = function(codeVerifier) {
228
228
} ;
229
229
230
230
/**
231
- * Sets teh code verifier to a randomly generated challenge string.
231
+ * Sets the code verifier to a randomly generated challenge string.
232
232
* @return {!Service_ } This service, for chaining
233
233
*/
234
234
Service_ . prototype . generateCodeVerifier = function ( ) {
@@ -724,10 +724,35 @@ Service_.prototype.parseToken_ = function(content) {
724
724
} else {
725
725
throw new Error ( 'Unknown token format: ' + this . tokenFormat_ ) ;
726
726
}
727
- token . granted_time = getTimeInSeconds_ ( new Date ( ) ) ;
727
+ this . ensureExpiresAtSet_ ( token ) ;
728
728
return token ;
729
729
} ;
730
730
731
+ /**
732
+ * Adds expiresAt annotations on the token if not set.
733
+ * @param {string } token A token.
734
+ * @private
735
+ */
736
+ Service_ . prototype . ensureExpiresAtSet_ = function ( token ) {
737
+ // handle prior migrations
738
+ if ( token . expiresAt !== undefined ) {
739
+ return ;
740
+ }
741
+
742
+ // granted_time was added in prior versions of this library
743
+ var grantedTime = token . granted_time || getTimeInSeconds_ ( new Date ( ) ) ;
744
+ var expiresIn = token . expires_in_sec || token . expires_in || token . expires ;
745
+ if ( expiresIn ) {
746
+ var expiresAt = grantedTime + Number ( expiresIn ) ;
747
+ token . expiresAt = expiresAt ;
748
+ }
749
+ var refreshTokenExpiresIn = token . refresh_token_expires_in ;
750
+ if ( refreshTokenExpiresIn ) {
751
+ var refreshTokenExpiresAt = grantedTime + Number ( refreshTokenExpiresIn ) ;
752
+ token . refreshTokenExpiresAt = refreshTokenExpiresAt ;
753
+ }
754
+ } ;
755
+
731
756
/**
732
757
* Refreshes a token that has expired. This is only possible if offline access
733
758
* was requested when the token was authorized.
@@ -754,6 +779,11 @@ Service_.prototype.refresh = function() {
754
779
if ( ! newToken . refresh_token ) {
755
780
newToken . refresh_token = token . refresh_token ;
756
781
}
782
+ this . ensureExpiresAtSet_ ( token ) ;
783
+ // Propagate refresh token expiry if new token omits it
784
+ if ( newToken . refreshTokenExpiresAt === undefined ) {
785
+ newToken . refreshTokenExpiresAt = token . refreshTokenExpiresAt ;
786
+ }
757
787
this . saveToken_ ( newToken ) ;
758
788
} ) ;
759
789
} ;
@@ -805,6 +835,13 @@ Service_.prototype.isExpired_ = function(token) {
805
835
var now = getTimeInSeconds_ ( new Date ( ) ) ;
806
836
807
837
// Check the authorization token's expiration.
838
+ if ( token . expiresAt ) {
839
+ if ( token . expiresAt - now < Service_ . EXPIRATION_BUFFER_SECONDS_ ) {
840
+ expired = true ;
841
+ }
842
+ }
843
+
844
+ // Previous code path, provided for migration purpose, can be removed later
808
845
var expiresIn = token . expires_in_sec || token . expires_in || token . expires ;
809
846
if ( expiresIn ) {
810
847
var expiresTime = token . granted_time + Number ( expiresIn ) ;
@@ -833,13 +870,14 @@ Service_.prototype.isExpired_ = function(token) {
833
870
*/
834
871
Service_ . prototype . canRefresh_ = function ( token ) {
835
872
if ( ! token . refresh_token ) return false ;
836
- var expiresIn = token . refresh_token_expires_in ;
837
- if ( ! expiresIn ) {
873
+ this . ensureExpiresAtSet_ ( token ) ;
874
+ if ( token . refreshTokenExpiresAt === undefined ) {
838
875
return true ;
839
876
} else {
840
- var expiresTime = token . granted_time + Number ( expiresIn ) ;
841
877
var now = getTimeInSeconds_ ( new Date ( ) ) ;
842
- return expiresTime - now > Service_ . EXPIRATION_BUFFER_SECONDS_ ;
878
+ return (
879
+ token . refreshTokenExpiresAt - now > Service_ . EXPIRATION_BUFFER_SECONDS_
880
+ ) ;
843
881
}
844
882
} ;
845
883
0 commit comments