basic node.js authentication tested
This commit is contained in:
parent
afb021af9b
commit
cc4af8f95a
|
@ -3,14 +3,17 @@
|
|||
// process.stdout.isTTY
|
||||
var form = require('terminal-forms.js').create(process.stdin, process.stdout);
|
||||
var OAUTH3 = require('../oauth3.node.js');
|
||||
// TODO change to ._hooks
|
||||
OAUTH3.hooks.directives._get = require('../oauth3.node.storage.js').directives._get;
|
||||
OAUTH3.hooks.directives._set = require('../oauth3.node.storage.js').directives._set;
|
||||
OAUTH3.hooks.session._get = require('../oauth3.node.storage.js').session._get;
|
||||
OAUTH3.hooks.session._set = require('../oauth3.node.storage.js').session._set;
|
||||
var url = require('url');
|
||||
console.log('stdin tty', process.stdin.isTTY);
|
||||
console.log('stdout tty', process.stdout.isTTY);
|
||||
//console.log('stdin tty', process.stdin.isTTY);
|
||||
//console.log('stdout tty', process.stdout.isTTY);
|
||||
|
||||
form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(function (urlResult) {
|
||||
var urlObj = url.parse(urlResult.input);
|
||||
var urlObj = url.parse(urlResult.result || urlResult.input);
|
||||
// TODO get unique client id for bootstrapping app
|
||||
var oauth3 = OAUTH3.create(urlObj);
|
||||
var providerPromise = oauth3.setProvider(urlObj.host + urlObj.pathname);
|
||||
|
@ -20,23 +23,79 @@ form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(funct
|
|||
// TODO lookup uuid locally before performing loginMeta
|
||||
// TODO lookup token locally before performing loginMeta / otp
|
||||
return providerPromise.then(function () {
|
||||
return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (result) {
|
||||
return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (/*result*/) {
|
||||
return emailResult.input;
|
||||
}, function (/*err*/) {
|
||||
// TODO require hashcash to create user account
|
||||
console.log(result);
|
||||
return form.PromiseA.reject(new Error("not implemented"));
|
||||
function confirmCreateAccount() {
|
||||
// TODO directives should specify private (invite-only) vs internal (request) vs public (allow) accounts
|
||||
return form.ask({
|
||||
label: "We don't recognize that address. Do you want to create a new account? [Y/n] "
|
||||
, type: 'text' // TODO boolean with default Y or N
|
||||
}).then(function (result) {
|
||||
if (!result.input) {
|
||||
result.input = 'Y';
|
||||
}
|
||||
|
||||
result.input = result.input.toLowerCase();
|
||||
|
||||
if ('y' !== result.input) {
|
||||
return getCurrentUserEmail();
|
||||
}
|
||||
|
||||
return emailResult.input;
|
||||
});
|
||||
}
|
||||
|
||||
return confirmCreateAccount();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getCurrentUserEmail().then(function (email) {
|
||||
return getCurrentUserEmail().then(function (email) {
|
||||
// TODO skip if token exists locally
|
||||
form.println("Sending login code to '" + email + "'...");
|
||||
return OAUTH3.authn.otp(oauth3._providerDirectives, { email: email }).then(function (otpResult) {
|
||||
return form.ask({
|
||||
label: "What's your login code?"
|
||||
, help: "(it was sent to '" + urlResult.input + "' and looks like 1234-5678-9012)"
|
||||
}).then(function () {
|
||||
console.log(otpResult);
|
||||
label: "What's your login code? "
|
||||
, help: "(it was sent to '" + email + "' and looks like 1234-5678-9012)"
|
||||
// onkeyup
|
||||
// ondebounce
|
||||
// onchange
|
||||
// regexp // html5 name?
|
||||
, onReturnAsync: function (rs, ws, input/*, ch*/) {
|
||||
var formatted = input.toLowerCase().replace(/[^\d]+/g, '');
|
||||
|
||||
if (12 !== formatted.length) {
|
||||
return form.PromiseA.reject(new Error("invalid code please try again in the format xxxx-yyyy-zzzz"));
|
||||
}
|
||||
|
||||
formatted = formatted.match(/.{4,4}/g).join('-');
|
||||
|
||||
if (14 !== formatted.split('').length) {
|
||||
return form.PromiseA.reject(new Error("invalid code '" + formatted + "', please try again xxxx-yyyy-zzzz"));
|
||||
}
|
||||
|
||||
var data = {
|
||||
username: email
|
||||
, username_type: 'email'
|
||||
, client_id: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer)
|
||||
, client_uri: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer)
|
||||
, otp_code: formatted
|
||||
, otp_uuid: otpResult.data.uuid
|
||||
};
|
||||
|
||||
// returns session instead of input
|
||||
var colors = require('colors');
|
||||
form.setStatus(colors.dim("authenticating with server..."));
|
||||
return OAUTH3.authn.resourceOwnerPassword(oauth3._providerDirectives, data);
|
||||
}
|
||||
}).then(function (results) {
|
||||
var session = results.result;
|
||||
|
||||
form.println('session:');
|
||||
form.println(session);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -817,7 +817,8 @@
|
|||
}
|
||||
|
||||
resolve({
|
||||
request: xhr
|
||||
_request: xhr
|
||||
, headers: null // TODO
|
||||
, data: data
|
||||
, status: xhr.status
|
||||
});
|
||||
|
@ -1023,10 +1024,8 @@
|
|||
this._clientUri = OAUTH3.clientUri(location);
|
||||
}
|
||||
if (this._providerUri) {
|
||||
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri }).then(function (/*directives*/) {
|
||||
console.error("BUG: there's some jquery in oauth3.core.js that needs to be removed and tested");
|
||||
$('.js-signin').removeAttr('disabled');
|
||||
});
|
||||
// returns directives
|
||||
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri });
|
||||
}
|
||||
|
||||
return OAUTH3.discover(this._clientUri, { client_id: this._clientUri }).then(function (clientDirectives) {
|
||||
|
|
|
@ -130,6 +130,7 @@ OAUTH3.urls.resourceOwnerPassword = function (directive, opts) {
|
|||
var clientUri = opts.client_uri;
|
||||
var args = directive[type];
|
||||
var otpCode = opts.otp || opts.otpCode || opts.otp_code || opts.otpToken || opts.otp_token || undefined;
|
||||
// TODO require user agent
|
||||
var params = {
|
||||
client_id: opts.client_id || opts.client_uri
|
||||
, client_uri: opts.client_uri
|
||||
|
@ -239,20 +240,23 @@ OAUTH3.authn.loginMeta = function (directive, opts) {
|
|||
return OAUTH3.request({
|
||||
method: directive.credential_meta.method || 'GET'
|
||||
// TODO lint urls
|
||||
// TODO client_uri
|
||||
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_meta.url)
|
||||
.replace(':type', 'email')
|
||||
.replace(':id', opts.email)
|
||||
});
|
||||
};
|
||||
OAUTH3.authn.otp = function (directive, opts) {
|
||||
// TODO client_uri
|
||||
var preq = {
|
||||
method: directive.credential_otp.method || 'POST'
|
||||
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_otp.url)
|
||||
, data: {
|
||||
// TODO replace with signed hosted file
|
||||
client_agree_tos: 'oauth3.org/tos/draft'
|
||||
, client_id: directive.issuer // In this case, the issuer is its own client
|
||||
, client_uri: directive.issuer
|
||||
// TODO unbreak the client_uri option (if broken)
|
||||
, client_id: /*opts.client_id ||*/ OAUTH3.uri.normalize(directive.issuer) // In this case, the issuer is its own client
|
||||
, client_uri: /*opts.client_uri ||*/ OAUTH3.uri.normalize(directive.issuer)
|
||||
, request_otp: true
|
||||
, username: opts.email
|
||||
}
|
||||
|
@ -268,6 +272,7 @@ OAUTH3.authn.resourceOwnerPassword = function (directive, opts) {
|
|||
return OAUTH3.discover(providerUri, opts).then(function (directive) {
|
||||
var prequest = OAUTH3.urls.resourceOwnerPassword(directive, opts);
|
||||
|
||||
// TODO return not the raw request?
|
||||
return OAUTH3.request(prequest).then(function (req) {
|
||||
var data = req.data;
|
||||
data.provider_uri = providerUri;
|
||||
|
|
|
@ -22,6 +22,13 @@ OAUTH3._requestHelper = function (preq, opts) {
|
|||
*/
|
||||
return OAUTH3._node.request(preq, opts);
|
||||
};
|
||||
OAUTH3._base64.atob = function (base64) {
|
||||
return new Buffer(base64, 'base64').toString('utf8');
|
||||
};
|
||||
OAUTH3._base64.btoa = function (text) {
|
||||
return new Buffer(text, 'utf8').toString('base64');
|
||||
};
|
||||
|
||||
OAUTH3._node = {};
|
||||
OAUTH3._node.discover = function(providerUri/*, opts*/) {
|
||||
return OAUTH3.request({
|
||||
|
@ -76,10 +83,13 @@ OAUTH3._node._parseJson = function (resp) {
|
|||
return PromiseA.reject(err);
|
||||
}
|
||||
|
||||
resp.data = json;
|
||||
return resp;
|
||||
return {
|
||||
headers: resp.headers
|
||||
, status: resp.statusCode
|
||||
, data: json
|
||||
};
|
||||
};
|
||||
OAUTH3._logoutHelper = function(directives, opts) {
|
||||
OAUTH3._logoutHelper = function(/*directives, opts*/) {
|
||||
// TODO allow prompting of which account
|
||||
return OAUTH3.PromiseA.reject(new Error("logout not yet implemented for node.js"));
|
||||
};
|
||||
|
|
|
@ -18,4 +18,19 @@ module.exports = {
|
|||
return directives;
|
||||
}
|
||||
}
|
||||
|
||||
, session: {
|
||||
_get: function (providerUri) {
|
||||
// TODO make safe
|
||||
try {
|
||||
return require(path.join(process.cwd(), providerUri + '.session.json'));
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
, _set: function (providerUri, session) {
|
||||
fs.writeFileSync(path.join(process.cwd(), providerUri + '.session.json'), JSON.stringify(session, null, 2));
|
||||
return session;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue