/* SimpleOAuth - Simply builds OAuth 1.0 headers * * Copyright (c) 2013, Ben Olson (github.com/bseth99/simple-oauth-js) * * Adapted from Ruby Gem simple_oauth: * https://github.com/laserlemon/simple_oauth * * and OAuthSimple: * http://unitedHeroes.net/OAuthSimple * * Usage is essentially the same and should match the Ruby versions output * for server-side processing. * * * This basic usage will yield a string suitable for setting on the * Authorization header in an AJAX request. It is not library specific * nor does it assume which header you will use it with: * * var options = { * consumer_key: 'R1Y3QW1L15uw8X0t5ddJbQ', * consumer_secret: '7xKJvmTCKm97WBQQllji9Oz8DRQHJoN1svhiY8vo' * }; * * var header = new SimpleOAuth.Header('get', 'http://example.org/resource', null, options); * var authorization = header.build(); * * See github.com/bseth99/simple-oauth for more usage examples and notes * Also check the test cases and samples for jQuery/Backbone integration cases * * Only support HMAC-SHA1 signing * * Other sources noted throughout. * * Dependancies: * underscore.js >= 1.4.3 (http://underscorejs.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the unitedHeroes.net nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. define(['underscore'], factory); } else { // Browser globals root.SimpleOAuth = factory( root._ ); } }(this, function ( _ ) { var ATTRIBUTE_KEYS = ['callback', 'consumer_key', 'nonce', 'signature_method', 'timestamp', 'token', 'verifier', 'version']; var NONCE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; /* getNonce adapted from OAuthSimple * A simpler version of OAuth * * author: jr conlin * mail: src@anticipatr.com * copyright: unitedHeroes.net * version: 1.2 * url: http://unitedHeroes.net/OAuthSimple * * Copyright (c) 2011, unitedHeroes.net * */ function getNonce(length) { var length = length || 16, result = '', i=0, rnum, len = NONCE_CHARS.length; for ( ;i * MIT License */ parseUri: function (str) { var uri = Parser.parse(str); uri['queryKey'] = {}; uri['query'].replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) { if ($1) uri['queryKey'][$1] = $2; }); return new _uri(uri); }, } /*! * https://github.com/medialize/URI.js * MIT License */ var Parser = {}; Parser.protocol_expression = /^[a-z][a-z0-9.+-]*$/i; Parser.parse = function( string ) { var pos, parts = {}; // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] // extract fragment parts.source = string; parts.fragment = ''; pos = string.indexOf('#'); if (pos > -1) { // escaping? parts.fragment = string.substring(pos + 1) || ''; string = string.substring(0, pos); } // extract query pos = string.indexOf('?'); parts.query = ''; if (pos > -1) { // escaping? parts.query = string.substring(pos + 1) || ''; string = string.substring(0, pos); } // extract protocol if (string.substring(0, 2) === '//') { // relative-scheme parts.scheme = null; string = string.substring(2); // extract "user:pass@host:port" string = Parser.parseAuthority(string, parts); } else { pos = string.indexOf(':'); if (pos > -1) { parts.scheme = string.substring(0, pos) || ''; if (parts.scheme && !parts.scheme.match(Parser.protocol_expression)) { // : may be within the path parts.scheme = undefined; } else if (parts.scheme === 'file') { // the file scheme: does not contain an authority string = string.substring(pos + 3); } else if (string.substring(pos + 1, pos + 3) === '//') { string = string.substring(pos + 3); // extract "user:pass@host:port" string = Parser.parseAuthority(string, parts); } else { string = string.substring(pos + 1); parts.urn = true; } } } // what's left must be the path parts.path = string; if ( parts.path.length > 0 ) { parts.directory = ''; parts.file = ''; } parts.relative = parts.path + ( parts.query.length > 0 ? '?' + parts.query : '' ); // and we're done return parts; }; Parser.parseHost = function(string, parts) { // extract host:port var pos = string.indexOf('/'); var bracketPos; var t; if (pos === -1) { pos = string.length; } if (string.charAt(0) === '[') { // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts // IPv6+port in the format [2001:db8::1]:80 (for the time being) bracketPos = string.indexOf(']'); parts.host = string.substring(1, bracketPos) || ''; parts.port = string.substring(bracketPos + 2, pos) || ''; if (parts.port === '/') { parts.port = ''; } } else if (string.indexOf(':') !== string.lastIndexOf(':')) { // IPv6 host contains multiple colons - but no port // this notation is actually not allowed by RFC 3986, but we're a liberal parser parts.host = string.substring(0, pos) || ''; parts.port = ''; } else { t = string.substring(0, pos).split(':'); parts.host = t[0] || ''; parts.port = t[1] || ''; } if (parts.host && string.substring(pos).charAt(0) !== '/') { pos++; string = '/' + string; } parts.authority = ( parts.host || '' ) + ( parts.port ? ':' + parts.port : '' ) return string.substring(pos) || '/'; }; Parser.parseAuthority = function(string, parts) { string = Parser.parseUserinfo(string, parts); return Parser.parseHost(string, parts); }; Parser.parseUserinfo = function(string, parts) { // extract username:password var firstSlash = string.indexOf('/'); /*jshint laxbreak: true */ var pos = firstSlash > -1 ? string.lastIndexOf('@', firstSlash) : string.indexOf('@'); /*jshint laxbreak: false */ var t; // authority@ must come before /path if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { t = string.substring(0, pos).split(':'); parts.user = t[0] ? decodeURIComponent(t[0]) : ''; t.shift(); parts.password = t[0] ? decodeURIComponent(t.join(':')) : ''; parts.userinfo = parts.user + '@' + parts.password; string = string.substring(pos + 1); } else { parts.userinfo = ''; parts.user = ''; parts.password = ''; } return string; }; function b64_hmac_sha1(k,d,_p,_z){ // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js // _p = b64pad, _z = character size; not used here but I left them available just in case if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d); } return SimpleOAuth; }));