basic node.js authentication tested
This commit is contained in:
parent
afb021af9b
commit
cc4af8f95a
@ -3,14 +3,17 @@
|
|||||||
// process.stdout.isTTY
|
// process.stdout.isTTY
|
||||||
var form = require('terminal-forms.js').create(process.stdin, process.stdout);
|
var form = require('terminal-forms.js').create(process.stdin, process.stdout);
|
||||||
var OAUTH3 = require('../oauth3.node.js');
|
var OAUTH3 = require('../oauth3.node.js');
|
||||||
|
// TODO change to ._hooks
|
||||||
OAUTH3.hooks.directives._get = require('../oauth3.node.storage.js').directives._get;
|
OAUTH3.hooks.directives._get = require('../oauth3.node.storage.js').directives._get;
|
||||||
OAUTH3.hooks.directives._set = require('../oauth3.node.storage.js').directives._set;
|
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');
|
var url = require('url');
|
||||||
console.log('stdin tty', process.stdin.isTTY);
|
//console.log('stdin tty', process.stdin.isTTY);
|
||||||
console.log('stdout tty', process.stdout.isTTY);
|
//console.log('stdout tty', process.stdout.isTTY);
|
||||||
|
|
||||||
form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(function (urlResult) {
|
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
|
// TODO get unique client id for bootstrapping app
|
||||||
var oauth3 = OAUTH3.create(urlObj);
|
var oauth3 = OAUTH3.create(urlObj);
|
||||||
var providerPromise = oauth3.setProvider(urlObj.host + urlObj.pathname);
|
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 uuid locally before performing loginMeta
|
||||||
// TODO lookup token locally before performing loginMeta / otp
|
// TODO lookup token locally before performing loginMeta / otp
|
||||||
return providerPromise.then(function () {
|
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
|
// TODO require hashcash to create user account
|
||||||
console.log(result);
|
function confirmCreateAccount() {
|
||||||
return form.PromiseA.reject(new Error("not implemented"));
|
// 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
|
// 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 OAUTH3.authn.otp(oauth3._providerDirectives, { email: email }).then(function (otpResult) {
|
||||||
return form.ask({
|
return form.ask({
|
||||||
label: "What's your login code?"
|
label: "What's your login code? "
|
||||||
, help: "(it was sent to '" + urlResult.input + "' and looks like 1234-5678-9012)"
|
, help: "(it was sent to '" + email + "' and looks like 1234-5678-9012)"
|
||||||
}).then(function () {
|
// onkeyup
|
||||||
console.log(otpResult);
|
// 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({
|
resolve({
|
||||||
request: xhr
|
_request: xhr
|
||||||
|
, headers: null // TODO
|
||||||
, data: data
|
, data: data
|
||||||
, status: xhr.status
|
, status: xhr.status
|
||||||
});
|
});
|
||||||
@ -1023,10 +1024,8 @@
|
|||||||
this._clientUri = OAUTH3.clientUri(location);
|
this._clientUri = OAUTH3.clientUri(location);
|
||||||
}
|
}
|
||||||
if (this._providerUri) {
|
if (this._providerUri) {
|
||||||
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri }).then(function (/*directives*/) {
|
// returns directives
|
||||||
console.error("BUG: there's some jquery in oauth3.core.js that needs to be removed and tested");
|
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri });
|
||||||
$('.js-signin').removeAttr('disabled');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OAUTH3.discover(this._clientUri, { client_id: this._clientUri }).then(function (clientDirectives) {
|
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 clientUri = opts.client_uri;
|
||||||
var args = directive[type];
|
var args = directive[type];
|
||||||
var otpCode = opts.otp || opts.otpCode || opts.otp_code || opts.otpToken || opts.otp_token || undefined;
|
var otpCode = opts.otp || opts.otpCode || opts.otp_code || opts.otpToken || opts.otp_token || undefined;
|
||||||
|
// TODO require user agent
|
||||||
var params = {
|
var params = {
|
||||||
client_id: opts.client_id || opts.client_uri
|
client_id: opts.client_id || opts.client_uri
|
||||||
, client_uri: opts.client_uri
|
, client_uri: opts.client_uri
|
||||||
@ -239,20 +240,23 @@ OAUTH3.authn.loginMeta = function (directive, opts) {
|
|||||||
return OAUTH3.request({
|
return OAUTH3.request({
|
||||||
method: directive.credential_meta.method || 'GET'
|
method: directive.credential_meta.method || 'GET'
|
||||||
// TODO lint urls
|
// TODO lint urls
|
||||||
|
// TODO client_uri
|
||||||
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_meta.url)
|
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_meta.url)
|
||||||
.replace(':type', 'email')
|
.replace(':type', 'email')
|
||||||
.replace(':id', opts.email)
|
.replace(':id', opts.email)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
OAUTH3.authn.otp = function (directive, opts) {
|
OAUTH3.authn.otp = function (directive, opts) {
|
||||||
|
// TODO client_uri
|
||||||
var preq = {
|
var preq = {
|
||||||
method: directive.credential_otp.method || 'POST'
|
method: directive.credential_otp.method || 'POST'
|
||||||
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_otp.url)
|
, url: OAUTH3.url.resolve(directive.issuer, directive.credential_otp.url)
|
||||||
, data: {
|
, data: {
|
||||||
// TODO replace with signed hosted file
|
// TODO replace with signed hosted file
|
||||||
client_agree_tos: 'oauth3.org/tos/draft'
|
client_agree_tos: 'oauth3.org/tos/draft'
|
||||||
, client_id: directive.issuer // In this case, the issuer is its own client
|
// TODO unbreak the client_uri option (if broken)
|
||||||
, client_uri: directive.issuer
|
, 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
|
, request_otp: true
|
||||||
, username: opts.email
|
, username: opts.email
|
||||||
}
|
}
|
||||||
@ -268,6 +272,7 @@ OAUTH3.authn.resourceOwnerPassword = function (directive, opts) {
|
|||||||
return OAUTH3.discover(providerUri, opts).then(function (directive) {
|
return OAUTH3.discover(providerUri, opts).then(function (directive) {
|
||||||
var prequest = OAUTH3.urls.resourceOwnerPassword(directive, opts);
|
var prequest = OAUTH3.urls.resourceOwnerPassword(directive, opts);
|
||||||
|
|
||||||
|
// TODO return not the raw request?
|
||||||
return OAUTH3.request(prequest).then(function (req) {
|
return OAUTH3.request(prequest).then(function (req) {
|
||||||
var data = req.data;
|
var data = req.data;
|
||||||
data.provider_uri = providerUri;
|
data.provider_uri = providerUri;
|
||||||
|
@ -22,6 +22,13 @@ OAUTH3._requestHelper = function (preq, opts) {
|
|||||||
*/
|
*/
|
||||||
return OAUTH3._node.request(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 = {};
|
||||||
OAUTH3._node.discover = function(providerUri/*, opts*/) {
|
OAUTH3._node.discover = function(providerUri/*, opts*/) {
|
||||||
return OAUTH3.request({
|
return OAUTH3.request({
|
||||||
@ -76,10 +83,13 @@ OAUTH3._node._parseJson = function (resp) {
|
|||||||
return PromiseA.reject(err);
|
return PromiseA.reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.data = json;
|
return {
|
||||||
return resp;
|
headers: resp.headers
|
||||||
|
, status: resp.statusCode
|
||||||
|
, data: json
|
||||||
|
};
|
||||||
};
|
};
|
||||||
OAUTH3._logoutHelper = function(directives, opts) {
|
OAUTH3._logoutHelper = function(/*directives, opts*/) {
|
||||||
// TODO allow prompting of which account
|
// TODO allow prompting of which account
|
||||||
return OAUTH3.PromiseA.reject(new Error("logout not yet implemented for node.js"));
|
return OAUTH3.PromiseA.reject(new Error("logout not yet implemented for node.js"));
|
||||||
};
|
};
|
||||||
|
@ -18,4 +18,19 @@ module.exports = {
|
|||||||
return directives;
|
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…
x
Reference in New Issue
Block a user