Merge branch 'master' into v1.0

This commit is contained in:
AJ ONeal 2017-03-29 17:23:02 -06:00
commit 0bfdd009b7
11 changed files with 16883 additions and 140 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "node_modules/terminal-forms.js"]
path = node_modules/terminal-forms.js
url = git@git.daplie.com:/OAuth3/terminal-forms.js

5
.npmignore Normal file
View File

@ -0,0 +1,5 @@
.git*
browserify/
prefactor/
gulpfile.js
bump-version.sh

View File

@ -211,6 +211,7 @@ You can create a very simple demo application like this:
```javascript ```javascript
var providerUri; var providerUri;
var opts = { client_uri: OAUTH3.utils.clientUri(window.location) };
// this is any OAuth3-compatible provider, such as oauth3.org // this is any OAuth3-compatible provider, such as oauth3.org
@ -218,7 +219,7 @@ var providerUri;
// //
function onChangeProvider(_providerUri) { function onChangeProvider(_providerUri) {
providerUri = _providerUri; providerUri = _providerUri;
return OAUTH3.discover(providerUri); // just to cache return OAUTH3.discover(providerUri, opts); // just to cache
} }
@ -226,7 +227,6 @@ function onChangeProvider(_providerUri) {
// //
function onClickLogin() { function onClickLogin() {
var opts = { client_uri: OAuth3.clientUri(window.location) };
return OAUTH3.implicitGrant(providerUri, opts).then(function (session) { return OAUTH3.implicitGrant(providerUri, opts).then(function (session) {
console.info('Authentication was Successful:'); console.info('Authentication was Successful:');

View File

@ -15,52 +15,33 @@ OAUTH3._hooks.session.get = require('../oauth3.node.storage.js').sessions.get;
OAUTH3._hooks.session.set = require('../oauth3.node.storage.js').sessions.set; OAUTH3._hooks.session.set = require('../oauth3.node.storage.js').sessions.set;
*/ */
// opts = { email, providerUri }
module.exports.login = function (options) {
options = options || {};
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);
var oauth3; var oauth3;
var opts = { var opts = {
providerUri: undefined email: options.email
, providerUri: options.providerUri
}; };
if (opts.form) {
function getCurrentUserEmail() { form = opts.form;
return form.ask({ label: "What's your email (or cloud mail) address? ", type: 'email' }).then(function (emailResult) {
var emailParts = (emailResult.result || emailResult.input).split('@');
var domain = emailParts[1];
var username;
var sameProvider;
var urlObj = url.parse(opts.providerUri || domain);
// TODO get unique client id for bootstrapping app
oauth3 = OAUTH3.create(urlObj);
form.println("got to setProvider");
return oauth3.setProvider(domain).then(function () {
form.println("got to setProvider SUCCESS");
sameProvider = true;
// ignore
}, function () {
form.println("got to setProvider ERROR");
function askOauth3Url() {
return form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(function (urlResult) {
var urlObj = url.parse(urlResult.result || urlResult.input);
// TODO get unique client id for bootstrapping app
oauth3 = OAUTH3.create(urlObj);
return oauth3.setProvider(urlResult.result || urlResult.input).then(function () {
// ignore
}, function (err) {
form.println(err.stack || err.message || err.toString());
return askOauth3Url();
});
});
} }
var email;
var providerUrl;
var providerUri;
var sameProvider;
var username;
function getSession() {
var username;
return askOauth3Url();
}).then(function () {
// 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
form.println("got to loginMeta"); return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: email }).then(function (/*result*/) {
return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (/*result*/) { return { node: email, type: 'email' };
return { node: emailResult.result || emailResult.input, type: 'email' };
}, function (/*err*/) { }, function (/*err*/) {
// TODO require hashcash to create user account // TODO require hashcash to create user account
function confirmCreateAccount() { function confirmCreateAccount() {
@ -81,15 +62,14 @@ function getCurrentUserEmail() {
} }
if (!sameProvider) { if (!sameProvider) {
return { node: emailResult.result || emailResult.input, type: 'email' }; return { node: email, type: 'email' };
} }
return form.ask({ return form.ask({
label: "What's your recovery email (or cloud mail) address? ", type: 'email' label: "What's your recovery email (or cloud mail) address? ", type: 'email'
}).then(function (recoveryResult) { }).then(function (recoveryResult) {
username = emailParts[0];
return { return {
node: emailResult.result || emailResult.input node: email
, type: 'name' , type: 'name'
, recovery: recoveryResult.result || recoveryResult.input , recovery: recoveryResult.result || recoveryResult.input
}; };
@ -98,12 +78,7 @@ function getCurrentUserEmail() {
} }
return confirmCreateAccount(); return confirmCreateAccount();
}); }).then(function (user) {
});
});
}
return getCurrentUserEmail().then(function (user) {
// TODO skip if token exists locally // TODO skip if token exists locally
var email = (user.recovery || user.node); var email = (user.recovery || user.node);
form.println("Sending login code to '" + email + "'..."); form.println("Sending login code to '" + email + "'...");
@ -140,13 +115,95 @@ return getCurrentUserEmail().then(function (user) {
// returns session instead of input // returns session instead of input
var colors = require('colors'); var colors = require('colors');
form.setStatus(colors.dim("authenticating with server...")); form.setStatus(colors.dim("authenticating with server..."));
return OAUTH3.authn.resourceOwnerPassword(oauth3._providerDirectives, data); return OAUTH3.authn.resourceOwnerPassword(oauth3._providerDirectives, data).then(function (result) {
return result;
}, function (/*err*/) {
// TODO test error
return form.PromiseA.reject(new Error("The code '" + formatted + "' is mistyped or incorrect. Double check and try again."));
});
}
});
});
});
} }
}).then(function (results) {
var session = results.result;
function getCurrentUserEmail() {
return form.ask({
label: "What's your email (or cloud mail) address? ", type: 'email', value: opts.email
}).then(function (emailResult) {
opts.email = undefined;
email = (emailResult.result || emailResult.input);
var emailParts = email.split('@');
var domain = emailParts[1];
username = emailParts[0];
providerUrl = 'https://' + domain;
providerUri = domain;
var urlObj = url.parse(providerUrl);
// TODO get unique client id for bootstrapping app
oauth3 = OAUTH3.create(urlObj);
return oauth3.setProvider(domain).then(function () {
sameProvider = true;
// ignore
}, function () {
function askOauth3Url() {
return form.ask({
label: "What's your OAuth3 Provider URL? ", type: 'url', value: opts.providerUri
}).then(function (urlResult) {
opts.providerUri = undefined;
providerUrl = urlResult.result || urlResult.input;
providerUri = OAUTH3.uri.normalize(providerUrl);
var urlObj = url.parse(providerUrl);
// TODO get unique client id for bootstrapping app
oauth3 = OAUTH3.create(urlObj);
return oauth3.setProvider(providerUri).then(function () {
// ignore
}, function (err) {
form.println(err.stack || err.message || err.toString());
return askOauth3Url();
});
});
}
return askOauth3Url();
});
});
}
return getCurrentUserEmail().then(function () {
return OAUTH3._hooks.meta.get(email).then(function (id) {
if (!id) {
return null;
}
return OAUTH3._hooks.sessions.get(providerUri, id).then(function (session) {
if (session) {
return session;
}
return null;
});
});
}).then(function (session) {
if (session) {
return session;
}
return getSession().then(function (sessionResult) {
console.log('sessionResult');
console.log(sessionResult);
var session = sessionResult.result;
var id = require('crypto').createHash('sha256').update(session.token.sub || '').digest('hex');
return OAUTH3._hooks.sessions.set(providerUri, session, id).then(function (session) {
return OAUTH3._hooks.meta.set(email, id).then(function () {
return session;
});
});
});
}).then(function (session) {
form.println('session:'); form.println('session:');
form.println(session); form.println(session);
oauth3.__session = session;
return oauth3;
}); });
}); };
});

View File

@ -29,6 +29,11 @@
"homepage": "https://git.daplie.com/OAuth3/oauth3.js", "homepage": "https://git.daplie.com/OAuth3/oauth3.js",
"ignore": [ "ignore": [
"**/.*", "**/.*",
"browserify",
"prefactor",
"gulpfile.js",
"bump-version.sh",
"oauth3.node.*",
"node_modules", "node_modules",
"bower_components", "bower_components",
"test", "test",

2
node_modules/terminal-forms.js generated vendored

@ -1 +1 @@
Subproject commit f078d479b085e8658fb2039eb3e4de49afd9db0e Subproject commit 91efb1bbf2ab8f4db86f3e93a5c82bf541f1cc67

View File

@ -1134,6 +1134,7 @@
return OAUTH3.implicitGrant(me._providerDirectives, opts).then(function (session) { return OAUTH3.implicitGrant(me._providerDirectives, opts).then(function (session) {
me._session = true; me._session = true;
me.__session = session;
return session; return session;
}); });
} }
@ -1149,7 +1150,7 @@
preq.client_id = this._clientUri; preq.client_id = this._clientUri;
preq.method = preq.method || 'GET'; preq.method = preq.method || 'GET';
if (this._session) { if (this._session) {
preq.session = preq.session || OAUTH3.hooks.session._getCached(this._providerUri); preq.session = preq.session || this.session(); // OAUTH3.hooks.session._getCached(this._providerUri);
} }
// TODO maybe use a baseUrl from the directives file? // TODO maybe use a baseUrl from the directives file?
preq.url = OAUTH3.url.resolve(this._providerUri, preq.url); preq.url = OAUTH3.url.resolve(this._providerUri, preq.url);
@ -1157,6 +1158,8 @@
return OAUTH3.request(preq, opts); return OAUTH3.request(preq, opts);
} }
, logout: function (opts) { , logout: function (opts) {
this.__session = false;
this._session = false;
opts = opts || {}; opts = opts || {};
opts.client_uri = this._clientUri; opts.client_uri = this._clientUri;
opts.client_id = this._clientUri; opts.client_id = this._clientUri;
@ -1167,7 +1170,8 @@
, api: function (api, opts) { , api: function (api, opts) {
opts = opts || {}; opts = opts || {};
opts.api = api; opts.api = api;
opts.session = OAUTH3.hooks.session._getCached(this._providerUri); opts.session = this.__session || OAUTH3.hooks.session._getCached(this._providerUri);
return OAUTH3.api(this._providerUri, opts); return OAUTH3.api(this._providerUri, opts);
} }
}; };

16578
oauth3.crypto.fallback.js Normal file

File diff suppressed because it is too large Load Diff

8
oauth3.crypto.fallback.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,46 +1,134 @@
'use strict'; 'use strict';
var fs = require('fs'); var PromiseA = require('bluebird');
var fs = PromiseA.promisifyAll(require('fs'));
var path = require('path'); var path = require('path');
//var oauth3dir = process.cwd();
var oauth3dir = path.join(require('os').homedir(), '.oauth3', 'v1');
var sessionsdir = path.join(oauth3dir, 'sessions');
var directivesdir = path.join(oauth3dir, 'directives');
var metadir = path.join(oauth3dir, 'meta');
if (!fs.existsSync(oauth3dir)) {
fs.mkdirSync(oauth3dir);
}
if (!fs.existsSync(directivesdir)) {
fs.mkdirSync(directivesdir);
}
if (!fs.existsSync(sessionsdir)) {
fs.mkdirSync(sessionsdir);
}
if (!fs.existsSync(metadir)) {
fs.mkdirSync(metadir);
}
module.exports = { module.exports = {
directives: { directives: {
get: function (providerUri) { all: function () {
return fs.readdirAsync(directivesdir).then(function (nodes) {
return nodes.map(function (node) {
try {
return require(path.join(directivesdir, node));
} catch(e) {
return null;
}
}).filter(Boolean);
});
}
, get: function (providerUri) {
// TODO make safe // TODO make safe
try { try {
return require(path.join(process.cwd(), providerUri + '.directives.json')); return require(path.join(directivesdir, providerUri + '.json'));
} catch(e) { } catch(e) {
return null; return null;
} }
} }
, set: function (providerUri, directives) { , set: function (providerUri, directives) {
fs.writeFileSync(path.join(process.cwd(), providerUri + '.directives.json'), JSON.stringify(directives, null, 2)); return fs.writeFileAsync(
path.join(directivesdir, providerUri + '.json')
, JSON.stringify(directives, null, 2)
).then(function () {
return directives; return directives;
});
}
, clear: function () {
return fs.readdirAsync(directivesdir).then(function (nodes) {
return PromiseA.all(nodes.map(function (node) {
return fs.unlinkAsync(path.join(directivesdir, node)).then(function () { }, function () { });
}));
});
} }
} }
, sessions: { , sessions: {
get: function (providerUri, id) { all: function (providerUri) {
// TODO make safe var dirname = path.join(oauth3dir, 'sessions');
try { return fs.readdirAsync(dirname).then(function (nodes) {
if (id) { return nodes.map(function (node) {
return require(path.join(process.cwd(), providerUri + '.' + id + '.session.json')); var result = require(path.join(dirname, node));
} if (result.link) {
else {
return require(path.join(process.cwd(), providerUri + '.session.json'));
}
} catch(e) {
return null; return null;
} }
}).filter(Boolean).filter(function (result) {
if (!providerUri || providerUri === result.issuer) {
return result;
} }
, set: function (providerUri, session, id) { });
});
}
, get: function (providerUri, id) {
var result;
try {
if (id) { if (id) {
fs.writeFileSync(path.join(process.cwd(), providerUri + '.' + id + '.session.json'), JSON.stringify(session, null, 2)); return PromiseA.resolve(require(path.join(sessionsdir, providerUri + '.' + id + '.json')));
} }
else { else {
fs.writeFileSync(path.join(process.cwd(), providerUri + '.session.json'), JSON.stringify(session, null, 2)); result = require(path.join(sessionsdir, providerUri + '.json'));
// TODO make safer
if (result.link && '/' !== result.link[0] && !/\.\./.test(result.link)) {
result = require(path.join(oauth3dir, 'sessions', result.link));
} }
}
} catch(e) {
return PromiseA.resolve(null);
}
return PromiseA.resolve(result);
}
, set: function (providerUri, session, id) {
var p;
if (id) {
p = fs.writeFileAsync(path.join(sessionsdir, providerUri + '.' + id + '.json'), JSON.stringify(session, null, 2));
}
else {
p = fs.writeFileAsync(path.join(sessionsdir, providerUri + '.json'), JSON.stringify(session, null, 2));
}
return p.then(function () {
return session; return session;
});
}
, clear: function () {
var dirname = path.join(oauth3dir, 'sessions');
return fs.readdirAsync(dirname).then(function (nodes) {
return PromiseA.all(nodes.map(function (node) {
return fs.unlinkAsync(path.join(dirname, node));
}));
});
}
}
, meta: {
get: function (key) {
// TODO make safe
try {
return PromiseA.resolve(require(path.join(metadir, key + '.json')));
} catch(e) {
return PromiseA.resolve(null);
}
}
, set: function (key, value) {
return fs.writeFileAsync(path.join(metadir, key + '.json'), JSON.stringify(value, null, 2)).then(function () {
return value;
});
} }
} }
}; };

View File

@ -4,7 +4,7 @@
"description": "The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation.", "description": "The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation.",
"main": "oauth3.node.js", "main": "oauth3.node.js",
"scripts": { "scripts": {
"install": "./node_modules/.bin/gulp", "prepare": "gulp",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
@ -32,7 +32,8 @@
"sign" "sign"
], ],
"dependencies": { "dependencies": {
"elliptic": "^6.4.0" "elliptic": "^6.4.0",
"terminal-forms.js": "git+https://git.daplie.com/OAuth3/terminal-forms.js.git#v1"
}, },
"devDependencies": { "devDependencies": {
"browserify-aes": "^1.0.6", "browserify-aes": "^1.0.6",
@ -46,6 +47,6 @@
"gulp-uglify": "^2.1.0", "gulp-uglify": "^2.1.0",
"vinyl-source-stream": "^1.1.0" "vinyl-source-stream": "^1.1.0"
}, },
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", "author": "AJ ONeal <aj@daplie.com> (https://daplie.com/)",
"license": "(MIT OR Apache-2.0)" "license": "(MIT OR Apache-2.0)"
} }