Skip to content

Instantly share code, notes, and snippets.

@KevinTCoughlin
Last active August 29, 2015 14:06
Show Gist options
  • Save KevinTCoughlin/b51ac04ea6f79e1708ba to your computer and use it in GitHub Desktop.
Save KevinTCoughlin/b51ac04ea6f79e1708ba to your computer and use it in GitHub Desktop.
Tumblr OAuth Client for Windows 8/8.1
(function () {
"use strict";
/**
* Tumblr OAuth Client
*/
WinJS.Namespace.define('TumblrOAuth', {
client: WinJS.Class.define(function (consumerKey, consumerSecret) {
this._consumerKey = consumerKey;
this._consumerSecret = consumerSecret;
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
if (!this._accessKey && localSettings.values["accessKey"]) {
this._accessKey = localSettings.values["accessKey"];
this._accessSecret = localSettings.values["accessSecret"];
}
}, {
_consumerKey: null,
_consumerSecret: null,
_accessKey: null,
_accessSecret: null,
_loginUrl: "https://www.tumblr.com/oauth/request_token",
_authUrl: "https://www.tumblr.com/oauth/authorize?oauth_token=",
_accessUrl: "https://www.tumblr.com/oauth/access_token",
isLoggedIn: function () {
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
return localSettings.values["accessKey"];
},
logout: function () {
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
localSettings.values.remove('accessKey');
localSettings.values.remove('accessSecret');
},
login: function () {
var self = this;
var loginDetail = {};
var localSettings = Windows.Storage.ApplicationData.current.localSettings;
var callback = Windows.Security.Authentication.Web.WebAuthenticationBroker.getCurrentApplicationCallbackUri().absoluteUri;
var callback = new Windows.Foundation.Uri(callback.substr(0, callback.length - 1));
loginDetail["oauth_callback"] = callback.absoluteUri;
var loginReq = this.getAuthRequest(this._loginUrl, "POST", loginDetail, "text", "oauth_callback");
return loginReq.then(function (r) {
var loginResponse = r.split('&');
for (var r in loginResponse) {
var parts = loginResponse[r].split('=');
switch (parts[0]) {
case 'oauth_token':
self._accessKey = parts[1];
break;
case 'oauth_token_secret':
self._accessSecret = parts[1];
}
}
if (!self._accessKey) {
throw r.response;
}
return true;
})
.then(function () {
var url = self._authUrl + self._accessKey;
return Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
Windows.Security.Authentication.Web.WebAuthenticationOptions.none,
new Windows.Foundation.Uri(url), callback);
})
.then(function (WABResult) {
loginDetail.WAB = WABResult;
return loginDetail;
})
.then(function (details) {
var result = details.WAB.responseData;
var accessDetail = {};
if (!result || result.length === 0) {
return false;
}
var pieces = new Windows.Foundation.Uri(result).queryParsed;
for (var p = 0; p < pieces.size; p++) {
var entry = pieces.getAt(p);
switch (entry.name) {
case "oauth_token":
self._accessKey = entry.value;
break;
case "oauth_verifier":
accessDetail.oauth_verifier = entry.value;
break;
}
}
return self.getAuthRequest(self._accessUrl, "POST", accessDetail, "text", "oauth_verifier");
})
.then(function (responseData) {
if (typeof (responseData) != "string") {
responseData = "";
}
var pieces = responseData.split('&');
for (var p in pieces) {
var part = pieces[p];
var parts = part.split('=');
switch (parts[0]) {
case 'oauth_token':
self._accessKey = parts[1];
localSettings.values["accessKey"] = self._accessKey;
break;
case 'oauth_token_secret':
self._accessSecret = parts[1];
localSettings.values["accessSecret"] = self._accessSecret;
break;
}
}
return true;
});
},
generateHeader: function (url, method, params, addToHeader) {
var epoch = Math.round(new Date().getTime() / 1000);
var nonce = Math.random();
var sig = this.generateSignature(url, method, nonce, epoch, params);
var sigHeader = "OAuth ";
if (addToHeader === "oauth_callback") {
sigHeader += (addToHeader + "=\"" + encodeURIComponent(params[addToHeader]) + "\", ");
}
sigHeader += "oauth_consumer_key=\"" + this._consumerKey + "\", oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"" + epoch + "\", ";
if (this._accessKey) {
sigHeader += "oauth_token=\"" + this._accessKey + "\", ";
}
if (addToHeader == "oauth_verifier") {
sigHeader += (addToHeader + "=\"" + encodeURIComponent(params[addToHeader]) + "\", ");
}
sigHeader += "oauth_version=\"1.0\", oauth_signature=\"" + encodeURIComponent(sig) + "\"";
return sigHeader;
},
generateSignature: function (url, method, nonce, epoch, params) {
var sigParams = {
'oauth_consumer_key': this._consumerKey,
'oauth_nonce': nonce,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': epoch,
'oauth_token': this._accessKey,
'oauth_version': '1.0'
};
if (!this._accessKey) {
delete sigParams.oauth_token;
}
var sig = [];
for (var p in params) {
sigParams[p] = params[p];
}
var first = true;
var keys = Object.keys(sigParams).sort();
for (var k in keys) {
var key = keys[k];
if (!first) {
sig.push("&");
}
first = false;
if (typeof (sigParams[key]) === "object") {
//TODO: Encode Photo
}
else {
sig.push(encodeURIComponent(key));
sig.push("=");
sig.push(encodeURIComponent(sigParams[key]));
}
}
var sigString = method.toUpperCase() + "&" + encodeURIComponent(url) + "&" + encodeURIComponent(sig.join(''));
var keyMaterial = Windows.Security.Cryptography.CryptographicBuffer.convertStringToBinary(this._consumerSecret + "&" + (this._accessSecret || ''), Windows.Security.Cryptography.BinaryStringEncoding.utf8);
var provider = new Windows.Security.Cryptography.Core.MacAlgorithmProvider.openAlgorithm("HMAC_SHA1");
var key = provider.createKey(keyMaterial);
var tbs = Windows.Security.Cryptography.CryptographicBuffer.convertStringToBinary(sigString, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
var signatureBuffer = Windows.Security.Cryptography.Core.CryptographicEngine.sign(key, tbs);
var signature = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(signatureBuffer);
return signature;
},
getApiKeyRequest: function (url, method, params, oauth) {
params = params || {};
params["api_key"] = this._consumerKey;
if (oauth && this._accessKey) {
return this.getAuthRequest(url, method, params);
}
return this.makeRequest(url, method, null, params);
},
getAuthRequest: function (url, method, params, type, addToHeader) {
if (!params) {
params = {};
}
var header = this.generateHeader(url, method, params, addToHeader);
return this.makeRequest(url, method, header, params, type);
},
makeRequest: function (url, method, sig, data, type) {
var headers = null;
if (sig) {
headers = { Authorization: sig }
}
if ((method || "get").toLowerCase() === "get") {
var parts = [];
parts.push(url);
var start = true;
for (var k in data) {
parts.push(start ? "?" : "&");
start = false;
parts.push(encodeURIComponent(k));
parts.push("=");
parts.push(encodeURIComponent(data[k]));
}
url = parts.join('');
}
return WinJS.xhr({ type: (method || "get").toUpperCase(), responseType: type || "json", url: url, headers: headers, data: data }).then(function (r) {
if (!type || type == "json") {
return JSON.parse(r.response);
}
return r.response;
}, function (r) {
return JSON.parse((r && r.response && r.response != "") ? r.response : "{}");
});
},
setAccessDetails: function (key, secret) {
this._accessKey = key;
this._accessSecret = secret;
}
})
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment