-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
104 lines (85 loc) · 3.17 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const querystring = require('querystring');
const url = require('url');
const oauth = require('oauth');
const redirect = require('micro-redirect');
const provider = 'twitter';
const getRedirectUrl = token => {
return `https://twitter.com/oauth/authorize?oauth_token=${token}`;
};
const microAuthTwitter = ({ consumerKey, consumerSecret, callbackUrl, path = '/auth/twitter' }) => {
const getConsumer = (consumerKey, consumerSecret) => {
return new oauth.OAuth(
'https://twitter.com/oauth/request_token.json', 'https://twitter.com/oauth/access_token.json',
consumerKey, consumerSecret, '1.0A', callbackUrl, 'HMAC-SHA1');
};
const getRequestToken = () => {
return new Promise((resolve, reject) => {
getConsumer(consumerKey, consumerSecret).getOAuthRequestToken((err, requestToken, requestTokenSecret) => {
if (err) {
return reject(err);
}
return resolve({ requestToken, requestTokenSecret });
});
});
};
const getAccessToken = (token, secret, verifier) => {
return new Promise((resolve, reject) => {
getConsumer(consumerKey, consumerSecret)
.getOAuthAccessToken(token, secret, verifier, (err, accessToken, accessTokenSecret) => {
if (err) {
return reject(err);
}
return resolve({ accessToken, accessTokenSecret });
});
});
};
const verifyCredentials = (accessToken, accessTokenSecret) => {
return new Promise((resolve, reject) => {
getConsumer(consumerKey, consumerSecret)
.get('https://api.twitter.com/1.1/account/verify_credentials.json', accessToken, accessTokenSecret, (err, result) => {
if (err) {
return reject(err);
}
return resolve(result);
});
});
};
const states = new Map();
return fn => async (req, res, ...args) => {
const { pathname, query } = url.parse(req.url);
if (pathname === path) {
try {
const results = await getRequestToken();
states.set(results.requestToken, results);
const redirectLocation = getRedirectUrl(results.requestToken);
return redirect(res, 302, redirectLocation);
} catch (err) {
args.push({ err, provider });
return fn(req, res, ...args);
}
}
const callbackPath = url.parse(callbackUrl).pathname;
if (pathname === callbackPath) {
try {
const queryObject = querystring.parse(query);
const state = states.get(queryObject.oauth_token);
states.delete(queryObject.oauth_token);
const results = await getAccessToken(state.requestToken, state.requestTokenSecret, queryObject.oauth_verifier);
const data = await verifyCredentials(results.accessToken, results.accessTokenSecret);
const result = {
provider,
info: JSON.parse(data),
accessToken: results.accessToken,
accessTokenSecret: results.accessTokenSecret
};
args.push({ result });
return fn(req, res, ...args);
} catch (err) {
args.push({ err, provider });
return fn(req, res, ...args);
}
};
return fn(req, res, ...args);
};
};
module.exports = microAuthTwitter;