getting closer to accounts via api

This commit is contained in:
AJ ONeal 2018-06-20 09:07:35 +00:00
parent 58ed4baff1
commit e4640a8a00
4 changed files with 138 additions and 36 deletions

View File

@ -7,6 +7,8 @@ var pkg = require('../package.json');
var url = require('url');
var path = require('path');
var os = require('os');
var fs = require('fs');
var urequest = require('@coolaj86/urequest');
var common = require('../lib/cli-common.js');
var http = require('http');
var YAML = require('js-yaml');
@ -397,7 +399,6 @@ function serveControlsHelper() {
res.end('{"error":{"message":"unrecognized rpc"}}');
});
var fs = require('fs');
if (fs.existsSync(state._ipc.path)) {
fs.unlinkSync(state._ipc.path);
}
@ -494,15 +495,7 @@ function connectTunnel() {
controlServer.close();
}
// reverse 2FA otp
function leftpad(i, n, c) {
while (i.toString().length < (n || 4)) {
i = (c || '0') + i;
}
return i;
}
function getOtp() {
return leftpad(Math.round(Math.random() * 9999), 4, '0');
}
process.on('SIGINT', sigHandler);
state.net = state.net || {
createConnection: function (info, cb) {
@ -515,7 +508,6 @@ function connectTunnel() {
}
};
state.otp = getOtp();
state.greenlockConf = state.config.greenlock || {};
state.sortingHat = state.config.sortingHat || path.resolve(__dirname, '..', 'lib/sorting-hat.js');
@ -653,39 +645,79 @@ function rawTunnel(cb) {
state.relayUrl = common.parseUrl(state.relay);
state.relayHostname = common.parseHostname(state.relay);
if (!state.config.token && state.config.secret) {
var jwt = require('jsonwebtoken');
var tokenData = {
domains: Object.keys(state.config.servernames || {}).filter(function (name) {
return /\./.test(name);
})
, ports: Object.keys(state.config.ports || {}).filter(function (port) {
port = parseInt(port, 10);
return port > 0 && port <= 65535;
})
, aud: aud
, iss: Math.round(Date.now() / 1000)
urequest({ url: state.relayUrl + common.apiDirectory, json: true }, function (err, resp, body) {
state._apiDirectory = body;
state.wss = body.tunnel.method + '://' + body.api_host.replace(/:hostname/g, state.relayHostname) + body.tunnel.pathname;
console.log('api dir:');
console.log(body);
console.log('state.wss:');
console.log(state.wss);
if (!state.config.token && state.config.secret) {
var jwt = require('jsonwebtoken');
var tokenData = {
domains: Object.keys(state.config.servernames || {}).filter(function (name) {
return /\./.test(name);
})
, ports: Object.keys(state.config.ports || {}).filter(function (port) {
port = parseInt(port, 10);
return port > 0 && port <= 65535;
})
, aud: state.relayUrl
, iss: Math.round(Date.now() / 1000)
};
state.token = jwt.sign(tokenData, state.config.secret);
}
state.token = state.token || state.config.token;
if (state.token) { cb(null, connectTunnel()); return; }
if (!state.config.email) {
cb(new Error("No email... how did that happen?"));
return;
}
// TODO sign token with own private key, including public key and thumbprint
// (much like ACME JOSE account)
state.otp = common.otp();
state._auth = {
subject: state.config.email
, subject_scheme: 'mailto'
// TODO create domains list earlier
, scope: Object.keys(state.config.servernames || {}).join(',')
, otp: state.otp
, hostname: os.hostname()
// Used for User-Agent
, os_type: os.type()
, os_platform: os.platform()
, os_release: os.release()
, os_arch: os.arch()
};
state.token = jwt.sign(tokenData, state.config.secret);
}
state.token = state.token || state.config.token;
common.urequest({ url: state.relayUrl + common.apiDirectory, json: true }, function (err, resp, body) {
state._apiDirectory = body;
state.wss = body.tunnel.method + '://' + body.api_host.replace(/:hostname/g, state.relayHostname) + body.tunnel.pathname
if (token) {
if (err || !body || !body.pair_request) {
cb(null, connectTunnel());
return;
}
// TODO sign token with own private key, including public key and thumbprint
// (much like ACME JOSE account)
// TODO do auth stuff
var pairRequest = url.resolve('https://' + body.api_host.replace(/:hostname/g, state.relayHostname), body.pair_request.pathname);
var req = {
url: pairRequest
, method: body.pair_request.method
, json: state._auth
};
console.log('[telebitd.js] req');
console.log(req);
urequest(req, function (err, resp, body) {
if (err) { console.error('[telebitd.js] pair request', err); }
cb(null, connectTunnel());
console.log(body);
// TODO poll for token
//cb(null, connectTunnel());
}
);
});
}

View File

@ -37,8 +37,30 @@ common.parseUrl = function (hostname) {
hostname = location.protocol.replace(/https?/, 'https') + '//' + hostname + location.pathname;
return hostname;
};
common.parseHostname = function (hostname) {
var url = require('url');
var location = url.parse(hostname);
if (!location.protocol || /\./.test(location.protocol)) {
hostname = 'https://' + hostname;
location = url.parse(hostname);
}
//hostname = location.hostname + (location.port ? ':' + location.port : '');
//hostname = location.protocol.replace(/https?/, 'https') + '//' + hostname + location.pathname;
return location.hostname;
};
common.apiDirectory = '_apis/telebit.cloud/index.json';
function leftpad(i, n, c) {
while (i.toString().length < (n || 4)) {
i = (c || '0') + i;
}
return i;
}
common.otp = function getOtp() {
return leftpad(Math.round(Math.random() * 9999), 4, '0');
};
common.urequest = function (opts, cb) {
var https = require('https');
// request.js behavior:

30
tests/pair-request.js Normal file
View File

@ -0,0 +1,30 @@
'use strict';
var email = 'jon@example.com';
var urequest = require('@coolaj86/urequest');
var req = {
url: 'https://api.telebit.ppl.family/api/telebit.cloud/pair_request'
, method: 'POST'
, headers: { 'cOntEnt-tYpE': 'application/json;charset=utf-8' }
, json: {
subject: email
, subject_scheme: 'mailto'
, scope: ''
, otp: '321654'
, hostname: "Jon's Macbook Pro"
, os_type: 'Linux'
, os_platform: 'linux'
, os_release: '4.4.0-116-generic'
, os_arch: 'x64'
}
};
urequest(req, function (err, resp, body) {
if (err) {
console.error(err);
return;
}
console.log('Location:', resp.headers.location);
console.log('Body:');
console.log(body);
});

18
tests/pair-state.js Normal file
View File

@ -0,0 +1,18 @@
'use strict';
var stateUrl = 'https://api.telebit.ppl.family/api/telebit.cloud/pair_state/bca27428719e9c67805359f1';
var urequest = require('@coolaj86/urequest');
var req = {
url: stateUrl
, method: 'GET'
, json: true
};
urequest(req, function (err, resp, body) {
if (err) {
console.error(err);
return;
}
console.log('Done:');
console.log(body);
});