|
| 1 | +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.oauth1 || (g.oauth1 = {})).a = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({"oauth-1.0a":[function(require,module,exports){ |
| 2 | +if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') { |
| 3 | + module.exports = OAuth; |
| 4 | +} |
| 5 | + |
| 6 | +/** |
| 7 | + * Constructor |
| 8 | + * @param {Object} opts consumer key and secret |
| 9 | + */ |
| 10 | +function OAuth(opts) { |
| 11 | + if(!(this instanceof OAuth)) { |
| 12 | + return new OAuth(opts); |
| 13 | + } |
| 14 | + |
| 15 | + if(!opts) { |
| 16 | + opts = {}; |
| 17 | + } |
| 18 | + |
| 19 | + if(!opts.consumer) { |
| 20 | + throw new Error('consumer option is required'); |
| 21 | + } |
| 22 | + |
| 23 | + this.consumer = opts.consumer; |
| 24 | + this.nonce_length = opts.nonce_length || 32; |
| 25 | + this.version = opts.version || '1.0'; |
| 26 | + this.parameter_seperator = opts.parameter_seperator || ', '; |
| 27 | + this.realm = opts.realm; |
| 28 | + |
| 29 | + if(typeof opts.last_ampersand === 'undefined') { |
| 30 | + this.last_ampersand = true; |
| 31 | + } else { |
| 32 | + this.last_ampersand = opts.last_ampersand; |
| 33 | + } |
| 34 | + |
| 35 | + // default signature_method is 'PLAINTEXT' |
| 36 | + this.signature_method = opts.signature_method || 'PLAINTEXT'; |
| 37 | + |
| 38 | + if(this.signature_method == 'PLAINTEXT' && !opts.hash_function) { |
| 39 | + opts.hash_function = function(base_string, key) { |
| 40 | + return key; |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + if(!opts.hash_function) { |
| 45 | + throw new Error('hash_function option is required'); |
| 46 | + } |
| 47 | + |
| 48 | + this.hash_function = opts.hash_function; |
| 49 | + this.body_hash_function = opts.body_hash_function || this.hash_function; |
| 50 | +} |
| 51 | + |
| 52 | +/** |
| 53 | + * OAuth request authorize |
| 54 | + * @param {Object} request data |
| 55 | + * { |
| 56 | + * method, |
| 57 | + * url, |
| 58 | + * data |
| 59 | + * } |
| 60 | + * @param {Object} key and secret token |
| 61 | + * @return {Object} OAuth Authorized data |
| 62 | + */ |
| 63 | +OAuth.prototype.authorize = function(request, token) { |
| 64 | + var oauth_data = { |
| 65 | + oauth_consumer_key: this.consumer.key, |
| 66 | + oauth_nonce: this.getNonce(), |
| 67 | + oauth_signature_method: this.signature_method, |
| 68 | + oauth_timestamp: this.getTimeStamp(), |
| 69 | + oauth_version: this.version |
| 70 | + }; |
| 71 | + |
| 72 | + if(!token) { |
| 73 | + token = {}; |
| 74 | + } |
| 75 | + |
| 76 | + if(token.key !== undefined) { |
| 77 | + oauth_data.oauth_token = token.key; |
| 78 | + } |
| 79 | + |
| 80 | + if(!request.data) { |
| 81 | + request.data = {}; |
| 82 | + } |
| 83 | + |
| 84 | + if(request.includeBodyHash) { |
| 85 | + oauth_data.oauth_body_hash = this.getBodyHash(request, token.secret) |
| 86 | + } |
| 87 | + |
| 88 | + oauth_data.oauth_signature = this.getSignature(request, token.secret, oauth_data); |
| 89 | + |
| 90 | + return oauth_data; |
| 91 | +}; |
| 92 | + |
| 93 | +/** |
| 94 | + * Create a OAuth Signature |
| 95 | + * @param {Object} request data |
| 96 | + * @param {Object} token_secret key and secret token |
| 97 | + * @param {Object} oauth_data OAuth data |
| 98 | + * @return {String} Signature |
| 99 | + */ |
| 100 | +OAuth.prototype.getSignature = function(request, token_secret, oauth_data) { |
| 101 | + return this.hash_function(this.getBaseString(request, oauth_data), this.getSigningKey(token_secret)); |
| 102 | +}; |
| 103 | + |
| 104 | +/** |
| 105 | + * Create a OAuth Body Hash |
| 106 | + * @param {Object} request data |
| 107 | + */ |
| 108 | +OAuth.prototype.getBodyHash = function(request, token_secret) { |
| 109 | + var body = typeof request.data === 'string' ? request.data : JSON.stringify(request.data) |
| 110 | + |
| 111 | + if (!this.body_hash_function) { |
| 112 | + throw new Error('body_hash_function option is required'); |
| 113 | + } |
| 114 | + |
| 115 | + return this.body_hash_function(body, this.getSigningKey(token_secret)) |
| 116 | +}; |
| 117 | + |
| 118 | +/** |
| 119 | + * Base String = Method + Base Url + ParameterString |
| 120 | + * @param {Object} request data |
| 121 | + * @param {Object} OAuth data |
| 122 | + * @return {String} Base String |
| 123 | + */ |
| 124 | +OAuth.prototype.getBaseString = function(request, oauth_data) { |
| 125 | + return request.method.toUpperCase() + '&' + this.percentEncode(this.getBaseUrl(request.url)) + '&' + this.percentEncode(this.getParameterString(request, oauth_data)); |
| 126 | +}; |
| 127 | + |
| 128 | +/** |
| 129 | + * Get data from url |
| 130 | + * -> merge with oauth data |
| 131 | + * -> percent encode key & value |
| 132 | + * -> sort |
| 133 | + * |
| 134 | + * @param {Object} request data |
| 135 | + * @param {Object} OAuth data |
| 136 | + * @return {Object} Parameter string data |
| 137 | + */ |
| 138 | +OAuth.prototype.getParameterString = function(request, oauth_data) { |
| 139 | + var base_string_data; |
| 140 | + if (oauth_data.oauth_body_hash) { |
| 141 | + base_string_data = this.sortObject(this.percentEncodeData(this.mergeObject(oauth_data, this.deParamUrl(request.url)))); |
| 142 | + } else { |
| 143 | + base_string_data = this.sortObject(this.percentEncodeData(this.mergeObject(oauth_data, this.mergeObject(request.data, this.deParamUrl(request.url))))); |
| 144 | + } |
| 145 | + |
| 146 | + var data_str = ''; |
| 147 | + |
| 148 | + //base_string_data to string |
| 149 | + for(var i = 0; i < base_string_data.length; i++) { |
| 150 | + var key = base_string_data[i].key; |
| 151 | + var value = base_string_data[i].value; |
| 152 | + // check if the value is an array |
| 153 | + // this means that this key has multiple values |
| 154 | + if (value && Array.isArray(value)){ |
| 155 | + // sort the array first |
| 156 | + value.sort(); |
| 157 | + |
| 158 | + var valString = ""; |
| 159 | + // serialize all values for this key: e.g. formkey=formvalue1&formkey=formvalue2 |
| 160 | + value.forEach((function(item, i){ |
| 161 | + valString += key + '=' + item; |
| 162 | + if (i < value.length){ |
| 163 | + valString += "&"; |
| 164 | + } |
| 165 | + }).bind(this)); |
| 166 | + data_str += valString; |
| 167 | + } else { |
| 168 | + data_str += key + '=' + value + '&'; |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + //remove the last character |
| 173 | + data_str = data_str.substr(0, data_str.length - 1); |
| 174 | + return data_str; |
| 175 | +}; |
| 176 | + |
| 177 | +/** |
| 178 | + * Create a Signing Key |
| 179 | + * @param {String} token_secret Secret Token |
| 180 | + * @return {String} Signing Key |
| 181 | + */ |
| 182 | +OAuth.prototype.getSigningKey = function(token_secret) { |
| 183 | + token_secret = token_secret || ''; |
| 184 | + |
| 185 | + if(!this.last_ampersand && !token_secret) { |
| 186 | + return this.percentEncode(this.consumer.secret); |
| 187 | + } |
| 188 | + |
| 189 | + return this.percentEncode(this.consumer.secret) + '&' + this.percentEncode(token_secret); |
| 190 | +}; |
| 191 | + |
| 192 | +/** |
| 193 | + * Get base url |
| 194 | + * @param {String} url |
| 195 | + * @return {String} |
| 196 | + */ |
| 197 | +OAuth.prototype.getBaseUrl = function(url) { |
| 198 | + return url.split('?')[0]; |
| 199 | +}; |
| 200 | + |
| 201 | +/** |
| 202 | + * Get data from String |
| 203 | + * @param {String} string |
| 204 | + * @return {Object} |
| 205 | + */ |
| 206 | +OAuth.prototype.deParam = function(string) { |
| 207 | + var arr = string.split('&'); |
| 208 | + var data = {}; |
| 209 | + |
| 210 | + for(var i = 0; i < arr.length; i++) { |
| 211 | + var item = arr[i].split('='); |
| 212 | + |
| 213 | + // '' value |
| 214 | + item[1] = item[1] || ''; |
| 215 | + |
| 216 | + // check if the key already exists |
| 217 | + // this can occur if the QS part of the url contains duplicate keys like this: ?formkey=formvalue1&formkey=formvalue2 |
| 218 | + if (data[item[0]]){ |
| 219 | + // the key exists already |
| 220 | + if (!Array.isArray(data[item[0]])) { |
| 221 | + // replace the value with an array containing the already present value |
| 222 | + data[item[0]] = [data[item[0]]]; |
| 223 | + } |
| 224 | + // and add the new found value to it |
| 225 | + data[item[0]].push(decodeURIComponent(item[1])); |
| 226 | + } else { |
| 227 | + // it doesn't exist, just put the found value in the data object |
| 228 | + data[item[0]] = decodeURIComponent(item[1]); |
| 229 | + } |
| 230 | + } |
| 231 | + |
| 232 | + return data; |
| 233 | +}; |
| 234 | + |
| 235 | +/** |
| 236 | + * Get data from url |
| 237 | + * @param {String} url |
| 238 | + * @return {Object} |
| 239 | + */ |
| 240 | +OAuth.prototype.deParamUrl = function(url) { |
| 241 | + var tmp = url.split('?'); |
| 242 | + |
| 243 | + if (tmp.length === 1) |
| 244 | + return {}; |
| 245 | + |
| 246 | + return this.deParam(tmp[1]); |
| 247 | +}; |
| 248 | + |
| 249 | +/** |
| 250 | + * Percent Encode |
| 251 | + * @param {String} str |
| 252 | + * @return {String} percent encoded string |
| 253 | + */ |
| 254 | +OAuth.prototype.percentEncode = function(str) { |
| 255 | + return encodeURIComponent(str) |
| 256 | + .replace(/\!/g, "%21") |
| 257 | + .replace(/\*/g, "%2A") |
| 258 | + .replace(/\'/g, "%27") |
| 259 | + .replace(/\(/g, "%28") |
| 260 | + .replace(/\)/g, "%29"); |
| 261 | +}; |
| 262 | + |
| 263 | +/** |
| 264 | + * Percent Encode Object |
| 265 | + * @param {Object} data |
| 266 | + * @return {Object} percent encoded data |
| 267 | + */ |
| 268 | +OAuth.prototype.percentEncodeData = function(data) { |
| 269 | + var result = {}; |
| 270 | + |
| 271 | + for(var key in data) { |
| 272 | + var value = data[key]; |
| 273 | + // check if the value is an array |
| 274 | + if (value && Array.isArray(value)){ |
| 275 | + var newValue = []; |
| 276 | + // percentEncode every value |
| 277 | + value.forEach((function(val){ |
| 278 | + newValue.push(this.percentEncode(val)); |
| 279 | + }).bind(this)); |
| 280 | + value = newValue; |
| 281 | + } else { |
| 282 | + value = this.percentEncode(value); |
| 283 | + } |
| 284 | + result[this.percentEncode(key)] = value; |
| 285 | + } |
| 286 | + |
| 287 | + return result; |
| 288 | +}; |
| 289 | + |
| 290 | +/** |
| 291 | + * Get OAuth data as Header |
| 292 | + * @param {Object} oauth_data |
| 293 | + * @return {String} Header data key - value |
| 294 | + */ |
| 295 | +OAuth.prototype.toHeader = function(oauth_data) { |
| 296 | + var sorted = this.sortObject(oauth_data); |
| 297 | + |
| 298 | + var header_value = 'OAuth '; |
| 299 | + |
| 300 | + if (this.realm) { |
| 301 | + header_value += 'realm="' + this.realm + '"' + this.parameter_seperator; |
| 302 | + } |
| 303 | + |
| 304 | + for(var i = 0; i < sorted.length; i++) { |
| 305 | + if (sorted[i].key.indexOf('oauth_') !== 0) |
| 306 | + continue; |
| 307 | + |
| 308 | + header_value += this.percentEncode(sorted[i].key) + '="' + this.percentEncode(sorted[i].value) + '"' + this.parameter_seperator; |
| 309 | + } |
| 310 | + |
| 311 | + return { |
| 312 | + Authorization: header_value.substr(0, header_value.length - this.parameter_seperator.length) //cut the last chars |
| 313 | + }; |
| 314 | +}; |
| 315 | + |
| 316 | +/** |
| 317 | + * Create a random word characters string with input length |
| 318 | + * @return {String} a random word characters string |
| 319 | + */ |
| 320 | +OAuth.prototype.getNonce = function() { |
| 321 | + var word_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; |
| 322 | + var result = ''; |
| 323 | + |
| 324 | + for(var i = 0; i < this.nonce_length; i++) { |
| 325 | + result += word_characters[parseInt(Math.random() * word_characters.length, 10)]; |
| 326 | + } |
| 327 | + |
| 328 | + return result; |
| 329 | +}; |
| 330 | + |
| 331 | +/** |
| 332 | + * Get Current Unix TimeStamp |
| 333 | + * @return {Int} current unix timestamp |
| 334 | + */ |
| 335 | +OAuth.prototype.getTimeStamp = function() { |
| 336 | + return parseInt(new Date().getTime()/1000, 10); |
| 337 | +}; |
| 338 | + |
| 339 | +////////////////////// HELPER FUNCTIONS ////////////////////// |
| 340 | + |
| 341 | +/** |
| 342 | + * Merge object |
| 343 | + * @param {Object} obj1 |
| 344 | + * @param {Object} obj2 |
| 345 | + * @return {Object} |
| 346 | + */ |
| 347 | +OAuth.prototype.mergeObject = function(obj1, obj2) { |
| 348 | + obj1 = obj1 || {}; |
| 349 | + obj2 = obj2 || {}; |
| 350 | + |
| 351 | + var merged_obj = obj1; |
| 352 | + for(var key in obj2) { |
| 353 | + merged_obj[key] = obj2[key]; |
| 354 | + } |
| 355 | + return merged_obj; |
| 356 | +}; |
| 357 | + |
| 358 | +/** |
| 359 | + * Sort object by key |
| 360 | + * @param {Object} data |
| 361 | + * @return {Array} sorted array |
| 362 | + */ |
| 363 | +OAuth.prototype.sortObject = function(data) { |
| 364 | + var keys = Object.keys(data); |
| 365 | + var result = []; |
| 366 | + |
| 367 | + keys.sort(); |
| 368 | + |
| 369 | + for(var i = 0; i < keys.length; i++) { |
| 370 | + var key = keys[i]; |
| 371 | + result.push({ |
| 372 | + key: key, |
| 373 | + value: data[key], |
| 374 | + }); |
| 375 | + } |
| 376 | + |
| 377 | + return result; |
| 378 | +}; |
| 379 | + |
| 380 | +},{}]},{},[])("oauth-1.0a") |
| 381 | +}); |
0 commit comments