Skip to content
This repository was archived by the owner on Feb 18, 2024. It is now read-only.

Commit e06b547

Browse files
authored
Merge pull request #91 from tamird/token-auth-0.17
Remove username/password support; always use tokens
2 parents ba22b3c + b306765 commit e06b547

File tree

2 files changed

+35
-43
lines changed

2 files changed

+35
-43
lines changed

github.js

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ catch(e) {}
3131
var execGit = require('./exec-git');
3232

3333
function createRemoteStrings(auth, hostname) {
34-
var authString = auth ? (encodeURIComponent(auth.username) + ':' + encodeURIComponent(auth.password) + '@') : '';
34+
var authString = auth.username ? (encodeURIComponent(auth.username) + ':' + encodeURIComponent(auth.password) + '@') : '';
3535
hostname = hostname || 'github.com';
3636

3737
this.remoteString = 'https://' + authString + hostname + '/';
38+
this.authSuffix = auth.token ? '?access_token=' + auth.token : '';
3839

3940
if (hostname == 'github.com')
4041
this.apiRemoteString = 'https://' + authString + 'api.github.com/';
@@ -44,10 +45,6 @@ function createRemoteStrings(auth, hostname) {
4445
this.apiRemoteString = 'https://' + authString + hostname + '/api/v3/';
4546
}
4647

47-
// avoid storing passwords as plain text in config
48-
function encodeCredentials(auth) {
49-
return new Buffer(auth.username + ':' + auth.password).toString('base64');
50-
}
5148
function decodeCredentials(str) {
5249
var auth = new Buffer(str, 'base64').toString('utf8').split(':');
5350

@@ -80,6 +77,10 @@ function readNetrc(hostname) {
8077
}
8178
}
8279

80+
function isGithubToken(token) {
81+
return token.match(/[0-9a-f]{40}/);
82+
}
83+
8384
var GithubLocation = function(options, ui) {
8485

8586
// ensure git is installed
@@ -97,19 +98,15 @@ var GithubLocation = function(options, ui) {
9798
this.versionString = options.versionString + '.1';
9899

99100
// Give the environment precedence over options object
100-
if(process.env.JSPM_GITHUB_AUTH_TOKEN) {
101-
options.auth = process.env.JSPM_GITHUB_AUTH_TOKEN;
102-
} else if (options.username && !options.auth) {
103-
options.auth = encodeCredentials(options);
104-
// NB deprecate old auth eventually
105-
// delete options.username;
106-
// delete options.password;
107-
}
101+
var auth = process.env.JSPM_GITHUB_AUTH_TOKEN || options.auth;
108102

109-
if (typeof options.auth == 'string') {
110-
this.auth = decodeCredentials(options.auth);
111-
}
112-
else {
103+
if (auth) {
104+
if (isGithubToken(auth)) {
105+
this.auth = { token: auth };
106+
} else {
107+
this.auth = decodeCredentials(auth);
108+
}
109+
} else {
113110
this.auth = readNetrc(options.hostname);
114111
}
115112

@@ -147,7 +144,7 @@ var GithubLocation = function(options, ui) {
147144

148145
this.remote = options.remote;
149146

150-
createRemoteStrings.call(this, this.auth, options.hostname);
147+
createRemoteStrings.call(this, this.auth || {}, options.hostname);
151148
};
152149

153150
function clearDir(dir) {
@@ -198,20 +195,14 @@ function configureCredentials(config, ui) {
198195

199196
return Promise.resolve()
200197
.then(function() {
201-
ui.log('info', 'If using two-factor authentication or to avoid using your password you can generate an access token at %https://' + (config.hostname || 'github.com') + '/settings/tokens%. Ensure it has `public_repo` scope access.');
202-
return ui.input('Enter your GitHub username');
203-
})
204-
.then(function(username) {
205-
auth.username = username;
206-
if (auth.username)
207-
return ui.input('Enter your GitHub password or access token', null, true);
198+
ui.log('info', 'You can generate an access token at %https://' + (config.hostname || 'github.com') + '/settings/tokens%.');
199+
return ui.input('Enter your GitHub access token');
208200
})
209-
.then(function(password) {
210-
auth.password = password;
211-
if (!auth.username)
212-
return false;
213-
214-
return ui.confirm('Would you like to test these credentials?', true);
201+
.then(function(token) {
202+
auth.token = token;
203+
if (auth.token) {
204+
return ui.confirm('Would you like to test these credentials?', true);
205+
}
215206
})
216207
.then(function(test) {
217208
if (!test)
@@ -223,7 +214,7 @@ function configureCredentials(config, ui) {
223214
createRemoteStrings.call(remotes, auth, config.hostname);
224215

225216
return asp(request)({
226-
uri: remotes.apiRemoteString + 'user',
217+
uri: remotes.apiRemoteString + 'user' + remotes.authSuffix,
227218
headers: {
228219
'User-Agent': 'jspm',
229220
'Accept': 'application/vnd.github.v3+json'
@@ -234,7 +225,7 @@ function configureCredentials(config, ui) {
234225
})
235226
.then(function(res) {
236227
if (res.statusCode == 401) {
237-
ui.log('warn', 'Provided GitHub credentials are not authorized, try re-entering your password or access token.');
228+
ui.log('warn', 'Provided GitHub credentials are not authorized, try re-entering your access token.');
238229
}
239230
else if (res.statusCode != 200) {
240231
ui.log('warn', 'Invalid response code, %' + res.statusCode + '%');
@@ -253,10 +244,10 @@ function configureCredentials(config, ui) {
253244
.then(function(redo) {
254245
if (redo)
255246
return configureCredentials(config, ui);
256-
return encodeCredentials(auth);
247+
return auth.token;
257248
});
258-
else if (auth.username)
259-
return encodeCredentials(auth);
249+
else if (auth.token)
250+
return auth.token;
260251
else
261252
return null;
262253
});
@@ -302,14 +293,15 @@ GithubLocation.prototype = {
302293
locate: function(repo) {
303294
var self = this;
304295
var remoteString = this.remoteString;
296+
var authSuffix = this.authSuffix;
305297

306298
if (repo.split('/').length !== 2)
307299
throw "GitHub packages must be of the form `owner/repo`.";
308300

309301
// request the repo to check that it isn't a redirect
310302
return new Promise(function(resolve, reject) {
311303
request(extend({
312-
uri: remoteString + repo,
304+
uri: remoteString + repo + authSuffix,
313305
headers: {
314306
'User-Agent': 'jspm'
315307
},
@@ -352,8 +344,7 @@ GithubLocation.prototype = {
352344
execGit('ls-remote ' + remoteString.replace(/(['"()])/g, '\\\$1') + repo + '.git refs/tags/* refs/heads/*', execOpt, function(err, stdout, stderr) {
353345
if (err) {
354346
if (err.toString().indexOf('not found') == -1) {
355-
// dont show plain text passwords in error
356-
var error = new Error(stderr.toString().replace(remoteString, ''));
347+
var error = new Error(stderr);
357348
error.hideStack = true;
358349
error.retriable = true;
359350
reject(error);
@@ -410,7 +401,7 @@ GithubLocation.prototype = {
410401
var ui = this.ui;
411402

412403
return asp(request)({
413-
uri: this.apiRemoteString + 'repos/' + repo + '/contents/package.json',
404+
uri: this.apiRemoteString + 'repos/' + repo + '/contents/package.json' + this.authSuffix,
414405
headers: {
415406
'User-Agent': 'jspm',
416407
'Accept': 'application/vnd.github.v3.raw'
@@ -546,13 +537,14 @@ GithubLocation.prototype = {
546537
var execOpt = this.execOpt;
547538
var max_repo_size = this.max_repo_size;
548539
var remoteString = this.remoteString;
540+
var authSuffix = this.authSuffix;
549541

550542
var self = this;
551543

552544
// Download from the git archive
553545
return new Promise(function(resolve, reject) {
554546
request({
555-
uri: remoteString + repo + '/archive/' + version + '.tar.gz',
547+
uri: remoteString + repo + '/archive/' + version + '.tar.gz' + authSuffix,
556548
headers: { 'accept': 'application/octet-stream' },
557549
strictSSL: self.defaultRequestOptions.strictSSL
558550
})

test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github = new github({
44
baseDir: '.',
55
log: true,
66
tmpDir: '.',
7-
username: '',
8-
password: ''
7+
auth: '',
8+
token: ''
99
});
1010

1111
github.lookup('angular/bower-angular')

0 commit comments

Comments
 (0)