Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

## 1.42.0 (2022-09-22)

### Features

* PKCE code verifier support ([#339](https://github.com/googleworkspace/apps-script-oauth2/pull/339))

### Bug Fixes

* "Prompt" property for auth URL in sample ([#317](https://github.com/googleworkspace/apps-script-oauth2/issues/317)) ([6da6876](https://github.com/googleworkspace/apps-script-oauth2/commit/6da68763a98586ae0bc916e5258ea7f0bebf4cb2))
* prevent samples from leaking OAuth client ID + Secret to users ([#379](https://github.com/googleworkspace/apps-script-oauth2/issues/379)) ([a5480c1](https://github.com/googleworkspace/apps-script-oauth2/commit/a5480c177386a807461b84d1b84627e272bc2355))
54 changes: 46 additions & 8 deletions dist/OAuth2.gs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ function createService(serviceName) {
/**
* Returns the redirect URI that will be used for a given script. Often this URI
* needs to be entered into a configuration screen of your OAuth provider.
* @param {string} [optScriptId] The script ID of your script, which can be
* @param {string=} optScriptId The script ID of your script, which can be
* found in the Script Editor UI under "File > Project properties". Defaults
* to the script ID of the script being executed.
* @return {string} The redirect URI.
*/
function getRedirectUri(optScriptId) {
var scriptId = optScriptId || ScriptApp.getScriptId();
return 'https://script.google.com/macros/d/' + encodeURIComponent(scriptId) +
'/usercallback';
'/usercallback';
}

/**
Expand Down Expand Up @@ -228,7 +228,7 @@ Service_.prototype.setCodeVerififer = function(codeVerifier) {
};

/**
* Sets teh code verifier to a randomly generated challenge string.
* Sets the code verifier to a randomly generated challenge string.
* @return {!Service_} This service, for chaining
*/
Service_.prototype.generateCodeVerifier = function() {
Expand Down Expand Up @@ -724,10 +724,35 @@ Service_.prototype.parseToken_ = function(content) {
} else {
throw new Error('Unknown token format: ' + this.tokenFormat_);
}
token.granted_time = getTimeInSeconds_(new Date());
this.ensureExpiresAtSet_(token);
return token;
};

/**
* Adds expiresAt annotations on the token if not set.
* @param {string} token A token.
* @private
*/
Service_.prototype.ensureExpiresAtSet_ = function(token) {
// handle prior migrations
if (token.expiresAt !== undefined) {
return;
}

// granted_time was added in prior versions of this library
var grantedTime = token.granted_time || getTimeInSeconds_(new Date());
var expiresIn = token.expires_in_sec || token.expires_in || token.expires;
if (expiresIn) {
var expiresAt = grantedTime + Number(expiresIn);
token.expiresAt = expiresAt;
}
var refreshTokenExpiresIn = token.refresh_token_expires_in;
if (refreshTokenExpiresIn) {
var refreshTokenExpiresAt = grantedTime + Number(refreshTokenExpiresIn);
token.refreshTokenExpiresAt = refreshTokenExpiresAt;
}
};

/**
* Refreshes a token that has expired. This is only possible if offline access
* was requested when the token was authorized.
Expand All @@ -754,6 +779,11 @@ Service_.prototype.refresh = function() {
if (!newToken.refresh_token) {
newToken.refresh_token = token.refresh_token;
}
this.ensureExpiresAtSet_(token);
// Propagate refresh token expiry if new token omits it
if (newToken.refreshTokenExpiresAt === undefined) {
newToken.refreshTokenExpiresAt = token.refreshTokenExpiresAt;
}
this.saveToken_(newToken);
});
};
Expand Down Expand Up @@ -805,6 +835,13 @@ Service_.prototype.isExpired_ = function(token) {
var now = getTimeInSeconds_(new Date());

// Check the authorization token's expiration.
if (token.expiresAt) {
if (token.expiresAt - now < Service_.EXPIRATION_BUFFER_SECONDS_) {
expired = true;
}
}

// Previous code path, provided for migration purpose, can be removed later
var expiresIn = token.expires_in_sec || token.expires_in || token.expires;
if (expiresIn) {
var expiresTime = token.granted_time + Number(expiresIn);
Expand Down Expand Up @@ -833,13 +870,14 @@ Service_.prototype.isExpired_ = function(token) {
*/
Service_.prototype.canRefresh_ = function(token) {
if (!token.refresh_token) return false;
var expiresIn = token.refresh_token_expires_in;
if (!expiresIn) {
this.ensureExpiresAtSet_(token);
if (token.refreshTokenExpiresAt === undefined) {
return true;
} else {
var expiresTime = token.granted_time + Number(expiresIn);
var now = getTimeInSeconds_(new Date());
return expiresTime - now > Service_.EXPIRATION_BUFFER_SECONDS_;
return (
token.refreshTokenExpiresAt - now > Service_.EXPIRATION_BUFFER_SECONDS_
);
}
};

Expand Down
Loading