Merge branch 'master' into signing

Šī revīzija ir iekļauta:
tigerbot 2017-03-21 14:09:45 -06:00
revīzija 9cfd517880
14 mainīti faili ar 501 papildinājumiem un 19 dzēšanām

3
.gitmodules ārējs Parasts fails
Parādīt failu

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

102
bin/oauth3.js Parasts fails
Parādīt failu

@ -0,0 +1,102 @@
'use strict';
// 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);
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
var oauth3 = OAUTH3.create(urlObj);
var providerPromise = oauth3.setProvider(urlObj.host + urlObj.pathname);
function getCurrentUserEmail() {
return form.ask({ label: "What's your email (or cloud mail) address? ", type: 'email' }).then(function (emailResult) {
// 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 emailResult.input;
}, function (/*err*/) {
// TODO require hashcash to create user account
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();
});
});
});
}
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 '" + 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);
});
});
});
});

37
bower.json Parasts fails
Parādīt failu

@ -0,0 +1,37 @@
{
"name": "oauth3.js",
"authors": [
"AJ ONeal <aj@daplie.com>"
],
"description": "The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation.",
"main": "oauth3.core.js",
"keywords": [
"oauth",
"oauth2",
"oauth3",
"oidc",
"openid",
"connect",
"openidconnect",
"authn",
"authz",
"authentication",
"authorization",
"user",
"password",
"passphrase",
"login",
"signin",
"log",
"sign"
],
"license": "MIT",
"homepage": "https://git.daplie.com/OAuth3/oauth3.js",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

14
bump-versions.sh Parasts fails
Parādīt failu

@ -0,0 +1,14 @@
git push --tags
git checkout v1.0
git push
git checkout v1
git merge v1.0
git push
git checkout master
git merge v1
git push
git checkout v1.0

48
dns.examples.js Parasts fails
Parādīt failu

@ -0,0 +1,48 @@
oauth3.api('devices.list').then(function (result) {
console.log(result);
});
oauth3.api(
'devices.set'
, { data: {
name: 'tester.local'
, uid: 'test-01-uid'
, addresses: [
{
type: 'A'
, address: '192.168.1.104'
}
]
} }
).then(function (result) {
console.log('devices.set');
console.log(result);
});
// TODO don't allow attaching if the device is not set
// TODO update API as well
oauth3.api(
'devices.attach'
, { data: {
sub: 'test-01'
, sld: 'aj'
, tld: 'daplie.me'
, uid: 'test-01-uid'
} }
).then(function (result) {
console.log('devices.attach');
console.log(result);
});
oauth3.api(
'devices.detach'
, { data: {
sub: 'test-01'
, sld: 'aj'
, tld: 'daplie.me'
, uid: 'test-01-uid'
} }
).then(function (result) {
console.log('devices.detach');
console.log(result);
});

1
node_modules/terminal-forms.js ģenerēts ārējs Apakšmodulis

@ -0,0 +1 @@
Subproject commit 66d46eab32d8014f43307f9fbe97027b8c913f7a

Parādīt failu

@ -4,7 +4,7 @@
var OAUTH3 = exports.OAUTH3 = {
clientUri: function (location) {
return OAUTH3.uri.normalize(location.host + location.pathname);
return OAUTH3.uri.normalize(location.host + (location.pathname || ''));
}
, error: {
parse: function (providerUri, params) {
@ -175,7 +175,7 @@
// TODO put in different file for browser vs node
try {
return Array.prototype.slice.call(
window.crypto.getRandomValues(new Uint8Array(16))
OAUTH3._browser.window.crypto.getRandomValues(new Uint8Array(16))
).map(function (ch) { return (ch).toString(16); }).join('');
} catch(e) {
return OAUTH3.utils._insecureRandomState();
@ -616,6 +616,11 @@
return OAUTH3.hooks.session.check(preq, opts).then(fetch);
}
, _requestHelper: function (preq, opts) {
/*
if (opts && opts.directives) {
preq.url = OAUTH3.url.resolve(opts.directives.issuer, preq.url);
}
*/
return OAUTH3._browser.request(preq, opts);
}
, implicitGrant: function(directives, opts) {
@ -695,7 +700,8 @@
return OAUTH3.discover(providerUri, opts).then(function (directive) {
var prequest = OAUTH3.urls.refreshToken(directive, opts);
return OAUTH3.request(prequest).then(function (req) {
prequest.url = OAUTH3.url.resolve(providerUri/*directives.issuer*/, prequest.url);
return OAUTH3.request(prequest/*, { directives: directive }*/).then(function (req) {
var data = req.data;
data.provider_uri = providerUri;
if (data.error) {
@ -747,7 +753,7 @@
// Let the Code Waste begin!!
//
, _browser: {
window: window
window: 'undefined' !== typeof window ? window : null
// TODO we don't need to include this if we're using jQuery or angular
, discover: function(providerUri, opts) {
opts = opts || {};
@ -841,7 +847,8 @@
}
resolve({
request: xhr
_request: xhr
, headers: null // TODO
, data: data
, status: xhr.status
});
@ -1047,9 +1054,8 @@
this._clientUri = OAUTH3.clientUri(location);
}
if (this._providerUri) {
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri }).then(function (/*directives*/) {
$('.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) {
@ -1101,6 +1107,7 @@
}
// TODO maybe use a baseUrl from the directives file?
preq.url = OAUTH3.url.resolve(this._providerUri, preq.url);
return OAUTH3.request(preq, opts);
}
, logout: function (opts) {

79
oauth3.dns.js Parasts fails
Parādīt failu

@ -0,0 +1,79 @@
;(function (exports) {
'use strict';
var OAUTH3 = exports.OAUTH3 = exports.OAUTH3 || require('./oauth3.core.js').OAUTH3;
OAUTH3.api['dns.list'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
method: 'GET'
, url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub + '/dns'
, session: session
}).then(function (res) {
return res.data.records || res.data;
});
};
OAUTH3.api['devices.list'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub + '/devices'
, method: 'GET'
, session: session
}, {}).then(function (res) {
return res.data.devices || res.data;
});
};
OAUTH3.api['devices.attach'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub
//+ '/devices/' + device + '/'
+ '/devices/' + (opts.data.uid || '_') + '/' + opts.data.device
+ '/' + opts.data.tld + '/' + opts.data.sld + '/' + (opts.data.sub || '')
, method: 'POST'
, session: session
}, {}).then(function (res) {
return res.data.devices || res.data;
});
};
OAUTH3.api['devices.detach'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub
//+ '/devices/' + device + '/'
+ '/devices/' + (opts.data.uid || '_') + '/' + opts.data.device
+ '/' + opts.data.tld + '/' + opts.data.sld + '/' + (opts.data.sub || '')
, method: 'DELETE'
, session: session
}, {}).then(function (res) {
return res.data.devices || res.data;
});
};
OAUTH3.api['devices.detach'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub
+ '/devices/' + opts.data.device
+ '/' + opts.data.tld + '/' + opts.data.sld + '/' + (opts.data.sub || '')
, method: 'DELETE'
, session: session
}, {}).then(function (res) {
return res.data.device || res.data;
});
};
}('undefined' !== typeof exports ? exports : window));

Parādīt failu

@ -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;

Parādīt failu

@ -15,9 +15,9 @@ angular
function PromiseAngularQ(fn) {
var d = $q.defer();
$timeout(function () {
//$timeout(function () {
fn(d.resolve, d.reject);
}, 0);
//}, 0);
//this.then = d.promise.then;
//this.catch = d.promise.catch;

101
oauth3.node.js Parasts fails
Parādīt failu

@ -0,0 +1,101 @@
'use strict';
//var OAUTH3 = require('./oauth3.core.js').OAUTH3;
var OAUTH3 = require('./oauth3.issuer.js').OAUTH3;
// used for OAUTH3.urls.resourcePasswordOwner
// used for OAUTH3.authn.loginMeta
// used for OAUTH3.authn.otp
// used for OAUTH3.authn.resourcePasswordOwner
var PromiseA = require('bluebird');
var requestAsync = PromiseA.promisify(require('request'));
var crypto = require('crypto');
OAUTH3.PromiseA = PromiseA;
OAUTH3._discoverHelper = function(providerUri, opts) {
return OAUTH3._node.discover(providerUri, opts);
};
OAUTH3._requestHelper = function (preq, opts) {
/*
if (opts && opts.directives) {
preq.url = OAUTH3.url.resolve(opts.directives.issuer, preq.url);
}
*/
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({
method: 'GET'
, url: OAUTH3.url.normalize(providerUri) + '/.well-known/oauth3/directives.json'
}).then(function (resp) {
return resp.data;
});
};
OAUTH3._node.request = function(preq/*, _sys*/) {
var data = {
method: preq.method
, url: preq.url || preq.uri
, headers: preq.headers
, json: preq.data || preq.body || preq.json || undefined // TODO which to use?
, formData: preq.formData || undefined
};
//console.log('DEBUG request');
//console.log(preq.url || preq.uri);
//console.log(data.json);
return requestAsync(data).then(OAUTH3._node._parseJson);
};
OAUTH3._node._parseJson = function (resp) {
var err;
var json = resp.body;
// TODO toCamelCase
if (!(resp.statusCode >= 200 && resp.statusCode < 400)) {
// console.log('[A3] DEBUG', resp.body);
err = new Error("bad response code: " + resp.statusCode);
err.result = resp.body;
return PromiseA.reject(err);
}
//console.log('resp.body', typeof resp.body);
if ('string' === typeof json) {
try {
json = JSON.parse(json);
} catch(e) {
err = new Error('response not parsable:' + resp.body);
err.result = resp.body;
return PromiseA.reject(err);
}
}
// handle both Oauth2- and node-style errors
if (json.error) {
err = new Error(json.error && json.error.message || json.error_description || json.error);
err.result = json;
return PromiseA.reject(err);
}
return {
headers: resp.headers
, status: resp.statusCode
, data: json
};
};
OAUTH3._logoutHelper = function(/*directives, opts*/) {
// TODO allow prompting of which account
return OAUTH3.PromiseA.reject(new Error("logout not yet implemented for node.js"));
};
OAUTH3._node.randomState = function () {
return crypto.randomBytes(16).toString('hex');
};
OAUTH3.randomState = OAUTH3._node.randomState;
module.exports = OAUTH3;

36
oauth3.node.storage.js Parasts fails
Parādīt failu

@ -0,0 +1,36 @@
'use strict';
var fs = require('fs');
var path = require('path');
module.exports = {
directives: {
_get: function (providerUri) {
// TODO make safe
try {
return require(path.join(process.cwd(), providerUri + '.directives.json'));
} catch(e) {
return null;
}
}
, _set: function (providerUri, directives) {
fs.writeFileSync(path.join(process.cwd(), providerUri + '.directives.json'), JSON.stringify(directives, null, 2));
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;
}
}
};

23
oauth3.tunnel.js Parasts fails
Parādīt failu

@ -0,0 +1,23 @@
;(function (exports) {
'use strict';
var OAUTH3 = exports.OAUTH3 = exports.OAUTH3 || require('./oauth3.core.js').OAUTH3;
OAUTH3.api['tunnel.token'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
method: 'POST'
, url: OAUTH3.url.normalize(providerUri)
+ '/api/org.oauth3.tunnel/accounts/' + session.token.sub + '/token'
, session: session
, data: {
domains: opts.data.domains
, device: opts.data.device
}
}).then(function (res) {
return res.data.records || res.data;
});
};
}('undefined' !== typeof exports ? exports : window));

Parādīt failu

@ -1,12 +1,36 @@
{
"name": "oauth3",
"respository": {
"type": "git",
"url": "git+ssh://git@git.daplie.com:OAuth3/oauth3.js.git"
},
"name": "oauth3.js",
"version": "1.0.0",
"description": "The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation.",
"main": "oauth3.node.js",
"scripts": {
"install": "./node_modules/.bin/gulp"
"install": "./node_modules/.bin/gulp",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git@git.daplie.com:OAuth3/oauth3.js.git"
},
"keywords": [
"oauth",
"oauth2",
"oauth3",
"oidc",
"openid",
"connect",
"openidconnect",
"authn",
"authz",
"authentication",
"authorization",
"user",
"password",
"passphrase",
"login",
"signin",
"log",
"sign"
],
"devDependencies": {
"browserify-aes": "^1.0.6",
"create-hash": "^1.1.2",
@ -20,5 +44,7 @@
"gulp-streamify": "^1.0.2",
"gulp-uglify": "^2.1.0",
"vinyl-source-stream": "^1.1.0"
}
},
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "(MIT OR Apache-2.0)"
}