Skip to content

Commit

Permalink
Adding support for OAuth 1.0, which handles callback URLs differently…
Browse files Browse the repository at this point in the history
… and doesn't use an oauth_verifier.
  • Loading branch information
Eric Koleda committed Apr 3, 2015
1 parent c0c195b commit a3fb1f1
Showing 1 changed file with 59 additions and 24 deletions.
83 changes: 59 additions & 24 deletions Service.gs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var Service_ = function(serviceName) {
this.serviceName_ = serviceName;
this.paramLocation_ = 'auth-header';
this.method_ = 'get';
this.oauthVersion_ = '1.0a';
};

/**
Expand Down Expand Up @@ -93,6 +94,17 @@ Service_.prototype.setMethod = function(method) {
return this;
};

/**
* Sets the specific OAuth version to use. The default is '1.0a'.
* @param {string} oauthVersion The OAuth version. Allowed values are '1.0a'
* and '1.0'.
* @return {Service_} This service, for chaining.
*/
Service_.prototype.setOAuthVersion = function(oauthVersion) {
this.oauthVersion_ = oauthVersion;
return this;
};

/**
* Sets the project key of the script that contains the authorization callback
* function (required). The project key can be found in the Script Editor UI
Expand Down Expand Up @@ -188,9 +200,13 @@ Service_.prototype.authorize = function() {
var token = this.getRequestToken_();
this.saveToken_(token);

return buildUrl_(this.authorizationUrl_, {
var oauthParams = {
oauth_token: token.public
});
};
if (this.oauthVersion_ == '1.0') {
oauthParams['oauth_callback'] = this.getCallbackUrl_();
}
return buildUrl_(this.authorizationUrl_, oauthParams);
};

/**
Expand All @@ -201,8 +217,15 @@ Service_.prototype.authorize = function() {
* @return {boolean} True if authorization was granted, false if it was denied.
*/
Service_.prototype.handleCallback = function(callbackRequest) {
var requestToken = callbackRequest.parameter.oauth_token;
var verifier = callbackRequest.parameter.oauth_verifier;
if (!verifier) {
var token = this.getToken_();

if (requestToken && requestToken != token.public) {
throw 'Error handling callback: token mismatch'
}

if (this.oauthVersion_ == '1.0a' && !verifier) {
return false;
}

Expand Down Expand Up @@ -260,26 +283,16 @@ Service_.prototype.getRequestToken_ = function() {
validate_({
'Request Token URL': this.requestTokenUrl_,
'Method': this.method_,
'Callback Function Name': this.callbackFunctionName_,
'Service Name': this.serviceName_,
'Project Key': this.projectKey_
});
var url = this.requestTokenUrl_;
var params = {
method: this.method_,
muteHttpExceptions: true
};
var stateToken = ScriptApp.newStateToken()
.withMethod(this.callbackFunctionName_)
.withArgument('serviceName', this.serviceName_)
.withTimeout(3600)
.createToken();
var callbackUrl = buildUrl_(getCallbackUrl(this.projectKey_), {
state: stateToken
});
var oauthParams = {
oauth_callback: callbackUrl
};
var oauthParams = {};
if (this.oauthVersion_ == '1.0a') {
oauthParams['oauth_callback'] = this.getCallbackUrl_();
}

var response = this.fetchInternal_(url, params, null, oauthParams);
if (response.getResponseCode() != 200) {
Expand All @@ -293,13 +306,12 @@ Service_.prototype.getRequestToken_ = function() {

/**
* Get a new access token.
* @param {string} verifier The value of the `oauth_verifier` URL parameter in
* the callback.
* @param {string} opt_verifier The value of the `oauth_verifier` URL parameter
* in the callback. Not used by OAuth version '1.0'.
* @returns {Object} An access token.
*/
Service_.prototype.getAccessToken_ = function(verifier) {
Service_.prototype.getAccessToken_ = function(opt_verifier) {
validate_({
'OAuth Verifier': verifier,
'Access Token URL': this.accessTokenUrl_,
'Method': this.method_
});
Expand All @@ -309,9 +321,11 @@ Service_.prototype.getAccessToken_ = function(verifier) {
muteHttpExceptions: true
};
var token = this.getToken_();
var oauthParams = {
oauth_verifier: verifier
};

var oauthParams = {};
if (opt_verifier) {
oauthParams['oauth_verifier'] = opt_verifier;
}

var response = this.fetchInternal_(url, params, token, oauthParams);
if (response.getResponseCode() != 200) {
Expand Down Expand Up @@ -453,3 +467,24 @@ Service_.prototype.getToken_ = function() {
Service_.prototype.getPropertyKey_ = function() {
return 'oauth1.' + this.serviceName_;
};

/**
* Gets a callback URL to use for the OAuth flow.
* @return {string} A callback URL.
* @private
*/
Service_.prototype.getCallbackUrl_ = function() {
validate_({
'Callback Function Name': this.callbackFunctionName_,
'Service Name': this.serviceName_,
'Project Key': this.projectKey_
});
var stateToken = ScriptApp.newStateToken()
.withMethod(this.callbackFunctionName_)
.withArgument('serviceName', this.serviceName_)
.withTimeout(3600)
.createToken();
return buildUrl_(getCallbackUrl(this.projectKey_), {
state: stateToken
});
};

0 comments on commit a3fb1f1

Please sign in to comment.