├── oauthTest.html
├── README.txt
├── example
├── index.html
├── authorize.html
├── requestToken.html
├── accessToken.html
├── echo.html
├── AJAX.html
├── consumer.js
├── signature.html
└── gadget
│ └── oauth-example.xml
├── sha1.js
├── oauthTest.js
└── oauth.js
/oauthTest.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | encode
9 | getParameters
10 | getBaseString
11 | getSignature
12 |
13 |
14 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | This is JavaScript software for implementing an OAuth consumer.
2 |
3 | Authors:
4 | John Kristian
5 |
6 | IMPORTANT NOTE
7 | ==============
8 | This library isn't as useful as you think it's going to be.
9 |
10 | OAuth is based around allowing tools and websites to talk to each other.
11 | However, JavaScript running in web browsers is nearly always hampered by
12 | security restrictions which prevent code running on one website from
13 | accessing data stored or served on another.
14 |
15 | Before you start hacking, make sure you understand the limitations posed
16 | by cross-domain XMLHttpRequest.
17 |
18 | WITH THAT SAID...
19 | =================
20 | There are an increasing number of platforms which use JavaScript as
21 | their language, but enable the programmer to access remote sites.
22 | Examples include Google Gadgets, and Microsoft Vista Sidebar. For those
23 | platforms, this library should come in handy.
24 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Here's a small demonstration of the
4 | OAuth library for JavaScript .
5 | You can fill out a form to
6 | get a request token .
7 | Then copy and paste the token into the form to
8 | authorize your consumer .
9 | Then copy and paste the token and secret into the form to
10 | get an access token .
11 | Then copy and paste the access token and secret into the form to
12 | echo a message .
13 |
14 | When using Microsoft Internet Explorer, you can prevent annoying warnings
15 | about protecting your security by going to
16 | 'Tools > Internet Options ... > Advanced > Security'
17 | and checking the box
18 | 'Allow active content to run in files on my computer'.
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/example/authorize.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/requestToken.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/example/accessToken.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
17 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/example/echo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
20 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/AJAX.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Here's a very simple example of using
4 | OAuth via
5 | XMLHttpRequest .
6 | Each of these buttons will request OAuth tokens,
7 | and display the resulting HTTP responses in popup windows.
8 |
9 |
10 |
11 |
12 |
13 | This won't work if you load this page from an HTTP server, because
14 | it attempts to send requests via XMLHttpRequest to term.ie or madgex.com.
15 | Most browsers forbid this for
16 | security reasons .
17 | You can make it work with Microsoft Internet Explorer, if you
18 | copy this page to a file and direct your browser to load from the file.
19 |
20 |
21 |
22 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/example/consumer.js:
--------------------------------------------------------------------------------
1 | var consumer = {};
2 |
3 | consumer.example =
4 | { consumerKey : "myKey"
5 | , consumerSecret: "mySecret"
6 | , serviceProvider:
7 | { signatureMethod : "HMAC-SHA1"
8 | , requestTokenURL : "http://localhost/oauth-provider/request_token"
9 | , userAuthorizationURL: "http://localhost/oauth-provider/authorize"
10 | , accessTokenURL : "http://localhost/oauth-provider/access_token"
11 | , echoURL : "http://localhost/oauth-provider/echo"
12 | }
13 | };
14 |
15 | consumer.madgex =
16 | { consumerKey : "key"
17 | , consumerSecret: "secret"
18 | , accessToken: "requestkey"
19 | , accessTokenSecret: "requestsecret"
20 | , echo: "accesskey"
21 | , echoSecret: "accesssecret"
22 | , serviceProvider:
23 | { signatureMethod : "HMAC-SHA1"
24 | , requestTokenURL : "http://echo.lab.madgex.com/request-token.ashx"
25 | , accessTokenURL : "http://echo.lab.madgex.com/access-token.ashx"
26 | , echoURL : "http://echo.lab.madgex.com/echo.ashx"
27 | }
28 | };
29 |
30 | consumer.mediamatic =
31 | { consumerKey : "e388e4f4d6f4cc10ff6dc0fd1637da370478e49e2"
32 | , consumerSecret: "0b062293b6e29ec91a23b2002abf88e9"
33 | , serviceProvider:
34 | { signatureMethod : "HMAC-SHA1"
35 | , requestTokenURL : "http://oauth-sandbox.mediamatic.nl/module/OAuth/request_token"
36 | , userAuthorizationURL: "http://oauth-sandbox.mediamatic.nl/module/OAuth/authorize"
37 | , accessTokenURL : "http://oauth-sandbox.mediamatic.nl/module/OAuth/access_token"
38 | , echoURL : "http://oauth-sandbox.mediamatic.nl/services/rest/?method=anymeta.test.echo"
39 | }
40 | };
41 |
42 | consumer.termie =
43 | { consumerKey : "key"
44 | , consumerSecret: "secret"
45 | , accessToken: "requestkey"
46 | , accessTokenSecret: "requestsecret"
47 | , echo: "accesskey"
48 | , echoSecret: "accesssecret"
49 | , serviceProvider:
50 | { signatureMethod : "HMAC-SHA1"
51 | , requestTokenURL : "http://term.ie/oauth/example/request_token.php"
52 | , userAuthorizationURL: "accessToken.html" // a stub
53 | , accessTokenURL : "http://term.ie/oauth/example/access_token.php"
54 | , echoURL : "http://term.ie/oauth/example/echo_api.php"
55 | }
56 | };
57 |
58 | consumer.initializeForm =
59 | function initializeForm(form, etc, usage) {
60 | var selector = etc.elements[0];
61 | var selection = selector.options[selector.selectedIndex].value;
62 | var selected = consumer[selection];
63 | if (selected != null) {
64 | consumer.setInputs(etc, { URL : selected.serviceProvider[usage + "URL"]
65 | , consumerSecret: selected.consumerSecret
66 | , tokenSecret : selected[usage + "Secret"]
67 | });
68 | consumer.setInputs(form, { oauth_signature_method: selected.serviceProvider.signatureMethod
69 | , oauth_consumer_key : selected.consumerKey
70 | , oauth_token : selected[usage]
71 | });
72 | }
73 | return true;
74 | };
75 |
76 | consumer.setInputs =
77 | function setInputs(form, props) {
78 | for (p in props) {
79 | if (form[p] != null && props[p] != null) {
80 | form[p].value = props[p];
81 | }
82 | }
83 | }
84 |
85 | consumer.signForm =
86 | function signForm(form, etc) {
87 | form.action = etc.URL.value;
88 | var accessor = { consumerSecret: etc.consumerSecret.value
89 | , tokenSecret : etc.tokenSecret.value};
90 | var message = { action: form.action
91 | , method: form.method
92 | , parameters: []
93 | };
94 | for (var e = 0; e < form.elements.length; ++e) {
95 | var input = form.elements[e];
96 | if (input.name != null && input.name != "" && input.value != null
97 | && (!(input.type == "checkbox" || input.type == "radio") || input.checked))
98 | {
99 | message.parameters.push([input.name, input.value]);
100 | }
101 | }
102 | OAuth.setTimestampAndNonce(message);
103 | OAuth.SignatureMethod.sign(message, accessor);
104 | //alert(outline("message", message));
105 | var parameterMap = OAuth.getParameterMap(message.parameters);
106 | for (var p in parameterMap) {
107 | if (p.substring(0, 6) == "oauth_"
108 | && form[p] != null && form[p].name != null && form[p].name != "")
109 | {
110 | form[p].value = parameterMap[p];
111 | }
112 | }
113 | return true;
114 | };
115 |
--------------------------------------------------------------------------------
/example/signature.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
45 |
46 |
47 | To compute an
48 | OAuth
49 | request signature ,
50 | fill in this form and click the 'Sign' button.
51 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/example/gadget/oauth-example.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
19 |
20 |
21 |
22 | Self Test
23 | Get Request Token
24 | Get Access Token
25 | Echo
26 | Wrong Secret
27 |
119 | ]]>
120 |
121 |
122 |
--------------------------------------------------------------------------------
/sha1.js:
--------------------------------------------------------------------------------
1 | /*
2 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
3 | * in FIPS PUB 180-1
4 | * Version 2.1a Copyright Paul Johnston 2000 - 2002.
5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6 | * Distributed under the BSD License
7 | * See http://pajhome.org.uk/crypt/md5 for details.
8 | */
9 |
10 | /*
11 | * Configurable variables. You may need to tweak these to be compatible with
12 | * the server-side, but the defaults work in most cases.
13 | */
14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
16 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
17 |
18 | /*
19 | * These are the functions you'll usually want to call
20 | * They take string arguments and return either hex or base-64 encoded strings
21 | */
22 | function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
23 | function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
24 | function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
25 | function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
26 | function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
27 | function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
28 |
29 | /*
30 | * Perform a simple self-test to see if the VM is working
31 | */
32 | function sha1_vm_test()
33 | {
34 | return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
35 | }
36 |
37 | /*
38 | * Calculate the SHA-1 of an array of big-endian words, and a bit length
39 | */
40 | function core_sha1(x, len)
41 | {
42 | /* append padding */
43 | x[len >> 5] |= 0x80 << (24 - len % 32);
44 | x[((len + 64 >> 9) << 4) + 15] = len;
45 |
46 | var w = Array(80);
47 | var a = 1732584193;
48 | var b = -271733879;
49 | var c = -1732584194;
50 | var d = 271733878;
51 | var e = -1009589776;
52 |
53 | for(var i = 0; i < x.length; i += 16)
54 | {
55 | var olda = a;
56 | var oldb = b;
57 | var oldc = c;
58 | var oldd = d;
59 | var olde = e;
60 |
61 | for(var j = 0; j < 80; j++)
62 | {
63 | if(j < 16) w[j] = x[i + j];
64 | else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
65 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
66 | safe_add(safe_add(e, w[j]), sha1_kt(j)));
67 | e = d;
68 | d = c;
69 | c = rol(b, 30);
70 | b = a;
71 | a = t;
72 | }
73 |
74 | a = safe_add(a, olda);
75 | b = safe_add(b, oldb);
76 | c = safe_add(c, oldc);
77 | d = safe_add(d, oldd);
78 | e = safe_add(e, olde);
79 | }
80 | return Array(a, b, c, d, e);
81 |
82 | }
83 |
84 | /*
85 | * Perform the appropriate triplet combination function for the current
86 | * iteration
87 | */
88 | function sha1_ft(t, b, c, d)
89 | {
90 | if(t < 20) return (b & c) | ((~b) & d);
91 | if(t < 40) return b ^ c ^ d;
92 | if(t < 60) return (b & c) | (b & d) | (c & d);
93 | return b ^ c ^ d;
94 | }
95 |
96 | /*
97 | * Determine the appropriate additive constant for the current iteration
98 | */
99 | function sha1_kt(t)
100 | {
101 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
102 | (t < 60) ? -1894007588 : -899497514;
103 | }
104 |
105 | /*
106 | * Calculate the HMAC-SHA1 of a key and some data
107 | */
108 | function core_hmac_sha1(key, data)
109 | {
110 | var bkey = str2binb(key);
111 | if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
112 |
113 | var ipad = Array(16), opad = Array(16);
114 | for(var i = 0; i < 16; i++)
115 | {
116 | ipad[i] = bkey[i] ^ 0x36363636;
117 | opad[i] = bkey[i] ^ 0x5C5C5C5C;
118 | }
119 |
120 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
121 | return core_sha1(opad.concat(hash), 512 + 160);
122 | }
123 |
124 | /*
125 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally
126 | * to work around bugs in some JS interpreters.
127 | */
128 | function safe_add(x, y)
129 | {
130 | var lsw = (x & 0xFFFF) + (y & 0xFFFF);
131 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
132 | return (msw << 16) | (lsw & 0xFFFF);
133 | }
134 |
135 | /*
136 | * Bitwise rotate a 32-bit number to the left.
137 | */
138 | function rol(num, cnt)
139 | {
140 | return (num << cnt) | (num >>> (32 - cnt));
141 | }
142 |
143 | /*
144 | * Convert an 8-bit or 16-bit string to an array of big-endian words
145 | * In 8-bit function, characters >255 have their hi-byte silently ignored.
146 | */
147 | function str2binb(str)
148 | {
149 | var bin = Array();
150 | var mask = (1 << chrsz) - 1;
151 | for(var i = 0; i < str.length * chrsz; i += chrsz)
152 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
153 | return bin;
154 | }
155 |
156 | /*
157 | * Convert an array of big-endian words to a string
158 | */
159 | function binb2str(bin)
160 | {
161 | var str = "";
162 | var mask = (1 << chrsz) - 1;
163 | for(var i = 0; i < bin.length * 32; i += chrsz)
164 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
165 | return str;
166 | }
167 |
168 | /*
169 | * Convert an array of big-endian words to a hex string.
170 | */
171 | function binb2hex(binarray)
172 | {
173 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
174 | var str = "";
175 | for(var i = 0; i < binarray.length * 4; i++)
176 | {
177 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
178 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
179 | }
180 | return str;
181 | }
182 |
183 | /*
184 | * Convert an array of big-endian words to a base-64 string
185 | */
186 | function binb2b64(binarray)
187 | {
188 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
189 | var str = "";
190 | for(var i = 0; i < binarray.length * 4; i += 3)
191 | {
192 | var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
193 | | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
194 | | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
195 | for(var j = 0; j < 4; j++)
196 | {
197 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
198 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
199 | }
200 | }
201 | return str;
202 | }
203 |
--------------------------------------------------------------------------------
/oauthTest.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2008 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // Here are some unit tests for the software in oauth.js.
18 | // The test data were copied from http://oauth.pbwiki.com/TestCases
19 |
20 | function testOAuth() {
21 | testEncode();
22 | testGetParameters();
23 | testGetBaseString();
24 | testGetSignature();
25 | }
26 |
27 | var ENCODING // From http://wiki.oauth.net/TestCases
28 | = [ ["abcABC123", "abcABC123"]
29 | , ["-._~" , "-._~"]
30 | , ["%" , "%25"]
31 | , ["+" , "%2B"]
32 | , ["&=*" , "%26%3D%2A"]
33 | , ["!'()" , "%21%27%28%29"]
34 | , ["\n" , "%0A"]
35 | , [" " , "%20"]
36 | ];
37 |
38 | function testEncode() {
39 | for (var i = 0; i < ENCODING.length; ++i) {
40 | var input = ENCODING[i][0];
41 | var expected = ENCODING[i][1];
42 | var actual = OAuth.percentEncode(input);
43 | if (expected != actual) {
44 | alert("OAuth.percentEncode(" + input + ") = " + actual);
45 | }
46 | }
47 | }
48 |
49 | function testGetParameters() {
50 | var list = OAuth.getParameterList(null);
51 | if (list == null || !(list instanceof Array) || list.length != 0) {
52 | alert("getParameterList(null) = " + list);
53 | }
54 | list = OAuth.getParameterList('');
55 | if (list == null || !(list instanceof Array) || list.length != 0) {
56 | alert("getParameterList('') = " + list);
57 | }
58 | var map = OAuth.getParameterMap(null);
59 | if (map == null || (map instanceof Array) || typeof map != "object") {
60 | alert("getParameterMap(null) = " + map);
61 | }
62 | var actual = OAuth.getParameter({x: 'a', y: 'b'}, 'x');
63 | if (actual != 'a') {
64 | alert("getParameter({}, 'x') = " + actual);
65 | }
66 | actual = OAuth.getParameter([['x', 'a'], ['y', 'b'], ['x', 'c']], 'x');
67 | if (actual != 'a') {
68 | alert("getParameter([], 'x') = " + actual);
69 | }
70 | var expected = 'OAuth realm="R",oauth_token="T",oauth_w%40%21rd="%23%40%2A%21"';
71 | actual = OAuth.getAuthorizationHeader('R', [['a', 'b'], ['oauth_token', 'T'], ['oauth_w@!rd', '#@*!']]);
72 | if (actual == null || actual != expected) {
73 | alert("getAuthorizationHeader\n" + expected + " != \n" + actual);
74 | }
75 | actual = OAuth.getAuthorizationHeader('R', {a: 'b', oauth_token: 'T', 'oauth_w@!rd': '#@*!'});
76 | if (actual == null || actual != expected) {
77 | alert("getAuthorizationHeader\n" + expected + " != \n" + actual);
78 | }
79 | var message = {action: 'http://localhost', parameters: {}};
80 | OAuth.completeRequest(message, {consumerKey: 'CK', token: 'T'});
81 | assertMemberEquals(message, 'method', "GET");
82 | map = message.parameters;
83 | assertMemberEquals(map, 'oauth_consumer_key', 'CK');
84 | assertMemberEquals(map, 'oauth_token', 'T');
85 | assertMemberEquals(map, 'oauth_version', '1.0');
86 | assertMemberNotNull(map, 'oauth_timestamp');
87 | assertMemberNotNull(map, 'oauth_nonce');
88 | }
89 |
90 | function assertMemberEquals(map, name, expected) {
91 | var actual = map[name];
92 | if (actual != expected) {
93 | alert(name + '=' + actual + ' (not ' + expected + ')');
94 | }
95 | }
96 |
97 | function assertMemberNotNull(map, name) {
98 | var actual = map[name];
99 | if (!actual) {
100 | alert(name + '=' + actual);
101 | }
102 | }
103 |
104 | var OAUTH_A_BASE_STRING = "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&"
105 | + "file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal";
106 |
107 | var BASES = //
108 | // label, HTTP method, action, parameters, expected
109 | { "simple" : ["GET", "http://example.com/", {n: "v"}, "GET&http%3A%2F%2Fexample.com%2F&n%3Dv" ]
110 | , "no path" : ["GET", "http://example.com" , {n: "v"}, "GET&http%3A%2F%2Fexample.com%2F&n%3Dv" ]
111 | , "sorting" : ["GET", "http://example.com/", [["n", "AB"], ["n", "{}"]], "GET&http%3A%2F%2Fexample.com%2F&n%3D%257B%257D%26n%3DAB" ]
112 | // , "username in URL": ["GET", "http://U:PW@Example.COM" , null, "GET&http%3A%2F%2FU%3APW%40example.com%2F&" ]
113 | , "capitalized URL": ["GET", "HtTp://Example.CoM/A/b/C" , null, "GET&http%3A%2F%2Fexample.com%2FA%2Fb%2FC&" ]
114 | , "@ in URL" : ["GET", "http://example.com/A@B/C" , null, "GET&http%3A%2F%2Fexample.com%2FA%40B%2FC&" ]
115 | , "punctuated URL" : ["GET", "http://example.com/a;b,c#d", null, "GET&http%3A%2F%2Fexample.com%2Fa%3Bb%2Cc&" ]
116 | , "OAuth A request": ["POST", "https://photos.example.net/request_token",
117 | { oauth_version: "1.0", oauth_consumer_key: "dpf43f3p2l4k3l03"
118 | , oauth_timestamp: "1191242090", oauth_nonce: "hsu94j3884jdopsl"
119 | , oauth_signature_method: "PLAINTEXT", oauth_signature: "ignored"
120 | }
121 | , "POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&"
122 | + "oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method%3DPLAINTEXT%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0" ]
123 | , "OAuth A access" : ["GET", "http://photos.example.net/photos",
124 | { file: "vacation.jpg", size: "original"
125 | , oauth_version: "1.0", oauth_consumer_key: "dpf43f3p2l4k3l03", oauth_token: "nnch734d00sl2jdk"
126 | , oauth_timestamp: "1191242096", oauth_nonce: "kllo9940pd9333jh"
127 | , oauth_signature: "ignored", oauth_signature_method: "HMAC-SHA1"
128 | }
129 | , OAUTH_A_BASE_STRING ]
130 | };
131 |
132 | function testGetBaseString() {
133 | for (var label in BASES) {
134 | try {
135 | var base = BASES[label];
136 | var b = 0;
137 | var method = base[b++];
138 | var action = base[b++];
139 | var parameters = base[b++];
140 | var expected = base[b++];
141 | var actual = OAuth.SignatureMethod.getBaseString({method: method, action: action, parameters: parameters});
142 | if (expected != actual) {
143 | alert(label + "\n" + actual + " (actual)\n" + expected + " (expected)");
144 | }
145 | } catch(e) {
146 | alert(e);
147 | }
148 | }
149 | // alert("tested OAuth.SignatureMethod.getBaseString");
150 | }
151 |
152 | var SIGNATURES =
153 | // label, method, consumer secret, token secret, base string, expected
154 | { "HMAC-SHA1.a" : [ "HMAC-SHA1", "cs", null, "bs", "egQqG5AJep5sJ7anhXju1unge2I=" ]
155 | , "HMAC-SHA1.b" : [ "HMAC-SHA1", "cs", "ts", "bs", "VZVjXceV7JgPq/dOTnNmEfO0Fv8=" ]
156 | , "OAuth A access" : [ "HMAC-SHA1", "kd94hf93k423kf44",
157 | "pfkkdhi9sl3r4s00", OAUTH_A_BASE_STRING,
158 | "tR3+Ty81lMeYAr/Fid0kMTYa/WM=" ]
159 | , "PLAINTEXT" : [ "PLAINTEXT", "cs", "ts", "bs", "cs&ts" ]
160 | , "OAuth A request": [ "PLAINTEXT", "kd94hf93k423kf44", null, null, "kd94hf93k423kf44&" ]
161 | };
162 |
163 | function testGetSignature() {
164 | for (label in SIGNATURES) {
165 | try {
166 | var signature = SIGNATURES[label];
167 | var s = 0;
168 | var methodName = signature[s++];
169 | var consumerSecret = signature[s++];
170 | var tokenSecret = signature[s++];
171 | var baseString = signature[s++];
172 | var expected = signature[s++];
173 | var signer = OAuth.SignatureMethod.newMethod(methodName,
174 | {consumerSecret: consumerSecret, tokenSecret: tokenSecret});
175 | var actual = signer.getSignature(baseString);
176 | if (expected != actual) {
177 | alert(label + "\n" + actual + " (actual)\n" + expected + " (expected)");
178 | }
179 | } catch(e) {
180 | alert(label + ": " + e);
181 | }
182 | }
183 | // alert("tested OAuth.SignatureMethod.getSignature");
184 | }
185 |
--------------------------------------------------------------------------------
/oauth.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2008 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /* Here's some JavaScript software for implementing OAuth.
18 |
19 | This isn't as useful as you might hope. OAuth is based around
20 | allowing tools and websites to talk to each other. However,
21 | JavaScript running in web browsers is hampered by security
22 | restrictions that prevent code running on one website from
23 | accessing data stored or served on another.
24 |
25 | Before you start hacking, make sure you understand the limitations
26 | posed by cross-domain XMLHttpRequest.
27 |
28 | On the bright side, some platforms use JavaScript as their
29 | language, but enable the programmer to access other web sites.
30 | Examples include Google Gadgets, and Microsoft Vista Sidebar.
31 | For those platforms, this library should come in handy.
32 | */
33 |
34 | // The HMAC-SHA1 signature method calls b64_hmac_sha1, defined by
35 | // http://pajhome.org.uk/crypt/md5/sha1.js
36 |
37 | /* An OAuth message is represented as an object like this:
38 | {method: "GET", action: "http://server.com/path", parameters: ...}
39 |
40 | The parameters may be either a map {name: value, name2: value2}
41 | or an Array of name-value pairs [[name, value], [name2, value2]].
42 | The latter representation is more powerful: it supports parameters
43 | in a specific sequence, or several parameters with the same name;
44 | for example [["a", 1], ["b", 2], ["a", 3]].
45 |
46 | Parameter names and values are NOT percent-encoded in an object.
47 | They must be encoded before transmission and decoded after reception.
48 | For example, this message object:
49 | {method: "GET", action: "http://server/path", parameters: {p: "x y"}}
50 | ... can be transmitted as an HTTP request that begins:
51 | GET /path?p=x%20y HTTP/1.0
52 | (This isn't a valid OAuth request, since it lacks a signature etc.)
53 | Note that the object "x y" is transmitted as x%20y. To encode
54 | parameters, you can call OAuth.addToURL, OAuth.formEncode or
55 | OAuth.getAuthorization.
56 |
57 | This message object model harmonizes with the browser object model for
58 | input elements of an form, whose value property isn't percent encoded.
59 | The browser encodes each value before transmitting it. For example,
60 | see consumer.setInputs in example/consumer.js.
61 | */
62 |
63 | /* This script needs to know what time it is. By default, it uses the local
64 | clock (new Date), which is apt to be inaccurate in browsers. To do
65 | better, you can load this script from a URL whose query string contains
66 | an oauth_timestamp parameter, whose value is a current Unix timestamp.
67 | For example, when generating the enclosing document using PHP:
68 |
69 |