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

Commit

Permalink
Remove username/password support; always use tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
tamird committed Jun 13, 2016
1 parent ba22b3c commit b306765
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 43 deletions.
74 changes: 33 additions & 41 deletions github.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ catch(e) {}
var execGit = require('./exec-git');

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

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

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

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

Expand Down Expand Up @@ -80,6 +77,10 @@ function readNetrc(hostname) {
}
}

function isGithubToken(token) {
return token.match(/[0-9a-f]{40}/);
}

var GithubLocation = function(options, ui) {

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

// Give the environment precedence over options object
if(process.env.JSPM_GITHUB_AUTH_TOKEN) {
options.auth = process.env.JSPM_GITHUB_AUTH_TOKEN;
} else if (options.username && !options.auth) {
options.auth = encodeCredentials(options);
// NB deprecate old auth eventually
// delete options.username;
// delete options.password;
}
var auth = process.env.JSPM_GITHUB_AUTH_TOKEN || options.auth;

if (typeof options.auth == 'string') {
this.auth = decodeCredentials(options.auth);
}
else {
if (auth) {
if (isGithubToken(auth)) {
this.auth = { token: auth };
} else {
this.auth = decodeCredentials(auth);
}
} else {
this.auth = readNetrc(options.hostname);
}

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

this.remote = options.remote;

createRemoteStrings.call(this, this.auth, options.hostname);
createRemoteStrings.call(this, this.auth || {}, options.hostname);
};

function clearDir(dir) {
Expand Down Expand Up @@ -198,20 +195,14 @@ function configureCredentials(config, ui) {

return Promise.resolve()
.then(function() {
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.');
return ui.input('Enter your GitHub username');
})
.then(function(username) {
auth.username = username;
if (auth.username)
return ui.input('Enter your GitHub password or access token', null, true);
ui.log('info', 'You can generate an access token at %https://' + (config.hostname || 'github.com') + '/settings/tokens%.');
return ui.input('Enter your GitHub access token');
})
.then(function(password) {
auth.password = password;
if (!auth.username)
return false;

return ui.confirm('Would you like to test these credentials?', true);
.then(function(token) {
auth.token = token;
if (auth.token) {
return ui.confirm('Would you like to test these credentials?', true);
}
})
.then(function(test) {
if (!test)
Expand All @@ -223,7 +214,7 @@ function configureCredentials(config, ui) {
createRemoteStrings.call(remotes, auth, config.hostname);

return asp(request)({
uri: remotes.apiRemoteString + 'user',
uri: remotes.apiRemoteString + 'user' + remotes.authSuffix,
headers: {
'User-Agent': 'jspm',
'Accept': 'application/vnd.github.v3+json'
Expand All @@ -234,7 +225,7 @@ function configureCredentials(config, ui) {
})
.then(function(res) {
if (res.statusCode == 401) {
ui.log('warn', 'Provided GitHub credentials are not authorized, try re-entering your password or access token.');
ui.log('warn', 'Provided GitHub credentials are not authorized, try re-entering your access token.');
}
else if (res.statusCode != 200) {
ui.log('warn', 'Invalid response code, %' + res.statusCode + '%');
Expand All @@ -253,10 +244,10 @@ function configureCredentials(config, ui) {
.then(function(redo) {
if (redo)
return configureCredentials(config, ui);
return encodeCredentials(auth);
return auth.token;
});
else if (auth.username)
return encodeCredentials(auth);
else if (auth.token)
return auth.token;
else
return null;
});
Expand Down Expand Up @@ -302,14 +293,15 @@ GithubLocation.prototype = {
locate: function(repo) {
var self = this;
var remoteString = this.remoteString;
var authSuffix = this.authSuffix;

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

// request the repo to check that it isn't a redirect
return new Promise(function(resolve, reject) {
request(extend({
uri: remoteString + repo,
uri: remoteString + repo + authSuffix,
headers: {
'User-Agent': 'jspm'
},
Expand Down Expand Up @@ -352,8 +344,7 @@ GithubLocation.prototype = {
execGit('ls-remote ' + remoteString.replace(/(['"()])/g, '\\\$1') + repo + '.git refs/tags/* refs/heads/*', execOpt, function(err, stdout, stderr) {
if (err) {
if (err.toString().indexOf('not found') == -1) {
// dont show plain text passwords in error
var error = new Error(stderr.toString().replace(remoteString, ''));
var error = new Error(stderr);
error.hideStack = true;
error.retriable = true;
reject(error);
Expand Down Expand Up @@ -410,7 +401,7 @@ GithubLocation.prototype = {
var ui = this.ui;

return asp(request)({
uri: this.apiRemoteString + 'repos/' + repo + '/contents/package.json',
uri: this.apiRemoteString + 'repos/' + repo + '/contents/package.json' + this.authSuffix,
headers: {
'User-Agent': 'jspm',
'Accept': 'application/vnd.github.v3.raw'
Expand Down Expand Up @@ -546,13 +537,14 @@ GithubLocation.prototype = {
var execOpt = this.execOpt;
var max_repo_size = this.max_repo_size;
var remoteString = this.remoteString;
var authSuffix = this.authSuffix;

var self = this;

// Download from the git archive
return new Promise(function(resolve, reject) {
request({
uri: remoteString + repo + '/archive/' + version + '.tar.gz',
uri: remoteString + repo + '/archive/' + version + '.tar.gz' + authSuffix,
headers: { 'accept': 'application/octet-stream' },
strictSSL: self.defaultRequestOptions.strictSSL
})
Expand Down
4 changes: 2 additions & 2 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ github = new github({
baseDir: '.',
log: true,
tmpDir: '.',
username: '',
password: ''
auth: '',
token: ''
});

github.lookup('angular/bower-angular')
Expand Down

0 comments on commit b306765

Please sign in to comment.