-
Notifications
You must be signed in to change notification settings - Fork 0
/
authentication.js
107 lines (86 loc) · 2.59 KB
/
authentication.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
105
106
107
const fetch = require('node-fetch');
const { cli } = require('cli-ux');
const fs = require('fs');
const jsonHeaders = {
'Content-Type': 'application/json',
Accept: 'application/json',
};
const OAUTH_CLIENT_ID = '98364a543e873178bcaa';
const TOKEN_FILE_PATH = `${__dirname}/.token`;
const encoding = 'utf8';
const authenticate = async () => {
const codeResponse = await fetch('https://github.com/login/device/code', {
method: 'POST',
body: JSON.stringify({
client_id: OAUTH_CLIENT_ID,
scope: null,
}),
headers: jsonHeaders,
});
const { device_code, user_code, verification_uri, interval } = await codeResponse.json();
cli.action.start(`Please paste this device code into the site opening in your default browser: "${user_code}"`);
// skip this in tests, couldn't figure out how to mock the open function
if (verification_uri) {
cli.open(verification_uri);
}
const hasVerified = async () => {
const verifiedResponse = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
body: JSON.stringify({
client_id: OAUTH_CLIENT_ID,
device_code,
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
}),
headers: jsonHeaders,
});
try {
const response = await verifiedResponse.json();
if (response.access_token) {
cli.action.stop();
return response.access_token;
}
return false;
} catch (error) {
return false;
}
};
return new Promise((resolve) => {
const intervalHandle = setInterval(async () => {
const token = await hasVerified();
if (token) {
resolve(token);
clearInterval(intervalHandle);
}
// if you check right at the allowed interval, it breaks the request
}, (interval + 1) * 1000);
});
};
const doesCachedTokenFileExist = (path) => {
try {
fs.accessSync(path, fs.constants.R_OK | fs.constants.W_OK);
return true;
} catch {
return false;
}
};
const writeToken = (token, path) => {
fs.writeFileSync(path, token, encoding);
};
const getCachedToken = (path) => {
const token = fs.readFileSync(path, { encoding: encoding });
return token.trim();
};
const getToken = async (resetToken, tokenFilePath = TOKEN_FILE_PATH) => {
if (doesCachedTokenFileExist(tokenFilePath)) {
if (resetToken) {
writeToken('', tokenFilePath);
console.log('GitHub token has been cleared.');
} else {
return getCachedToken(tokenFilePath);
}
}
const token = await authenticate();
writeToken(token, tokenFilePath);
return token;
};
module.exports = getToken;