· 9 years ago · Nov 05, 2016, 06:54 PM
1const R = require('ramda')
2const hmacsha1 = require('hmacsha1');
3
4// For RFC 3986 Compliant URI Encoding.
5let encode = R.pipe(
6 encodeURIComponent,
7 R.replace(/!/g, '%21'),
8 R.replace(/'/g, '%27'),
9 R.replace(/(/g, '%28'),
10 R.replace(/)/g, '%29'),
11 R.replace(/*/g, '%2A')
12);
13
14// Create a random alphanumeric string of a given length.
15let nonce = R.pipe(
16 R.times(
17 R.partial(
18 chars => chars[Math.floor(Math.random() * chars.length)],
19 [ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ]
20 )
21 ),
22 R.join('')
23);
24
25// Return the current timestamp in seconds
26let now = R.pipe(
27 Date.now,
28 R.flip(R.divide)(1000),
29 Math.floor
30);
31
32// Sort a list of pairs by the first item then the second.
33let sortPairs = R.compose(
34 R.sortBy(R.prop(0)),
35 R.sortBy(R.prop(1))
36);
37
38// Encode a list of pairs.
39let encodePairs = R.map(R.map(encode));
40
41// Convert a list of pairs into a query string.
42let toParams = R.compose(
43 R.join('&'),
44 R.map(R.join('='))
45);
46
47// Join key items with an ampersand and hash with given data.
48let hash = R.pipe(
49 R.unapply(R.identity),
50 R.compose(R.split(null), R.join('&')),
51 R.partial(hmacsha1)
52);
53
54// Prepend the method and url to the base string.
55let prependRequest = R.pipe(
56 R.unapply(R.identity),
57 R.adjust(R.toUpper, 0),
58 R.adjust(encode, 1),
59 R.compose(R.split(null), R.flip(R.concat)('&'), R.join('&')),
60 R.partial(R.concat)
61)
62
63// Sort and encode the oauth params.
64let encodeParams = R.pipe(
65 R.toPairs,
66 encodePairs,
67 sortPairs,
68 toParams,
69 encode
70);
71
72// Create an OAuth 1.0 signature.
73module.exports = function signature({
74 consumerKey,
75 consumerSecret,
76 oauthToken,
77 oauthSecret,
78 url,
79 params={},
80 data={},
81 method='POST',
82 version='1.0',
83 signatureMethod='HMAC-SHA1',
84 nonceSize=32
85}) {
86
87 return R.pipe(
88 encodeParams,
89 prependRequest(method, url),
90 hash(consumerSecret, oauthSecret)
91 )(Object.assign({
92 oauth_consumer_key: consumerKey,
93 oauth_nonce: nonce(nonceSize),
94 oauth_signature_method: signatureMethod,
95 oauth_timestamp: now(),
96 oauth_token: oauthToken,
97 oauth_version: version,
98 }, params, data));
99}