Merge branch 'master' into signing
This commit is contained in:
commit
9cfd517880
|
@ -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
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 66d46eab32d8014f43307f9fbe97027b8c913f7a
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
var OAUTH3 = exports.OAUTH3 = {
|
var OAUTH3 = exports.OAUTH3 = {
|
||||||
clientUri: function (location) {
|
clientUri: function (location) {
|
||||||
return OAUTH3.uri.normalize(location.host + location.pathname);
|
return OAUTH3.uri.normalize(location.host + (location.pathname || ''));
|
||||||
}
|
}
|
||||||
, error: {
|
, error: {
|
||||||
parse: function (providerUri, params) {
|
parse: function (providerUri, params) {
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
// TODO put in different file for browser vs node
|
// TODO put in different file for browser vs node
|
||||||
try {
|
try {
|
||||||
return Array.prototype.slice.call(
|
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('');
|
).map(function (ch) { return (ch).toString(16); }).join('');
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return OAUTH3.utils._insecureRandomState();
|
return OAUTH3.utils._insecureRandomState();
|
||||||
|
@ -616,6 +616,11 @@
|
||||||
return OAUTH3.hooks.session.check(preq, opts).then(fetch);
|
return OAUTH3.hooks.session.check(preq, opts).then(fetch);
|
||||||
}
|
}
|
||||||
, _requestHelper: function (preq, opts) {
|
, _requestHelper: function (preq, opts) {
|
||||||
|
/*
|
||||||
|
if (opts && opts.directives) {
|
||||||
|
preq.url = OAUTH3.url.resolve(opts.directives.issuer, preq.url);
|
||||||
|
}
|
||||||
|
*/
|
||||||
return OAUTH3._browser.request(preq, opts);
|
return OAUTH3._browser.request(preq, opts);
|
||||||
}
|
}
|
||||||
, implicitGrant: function(directives, opts) {
|
, implicitGrant: function(directives, opts) {
|
||||||
|
@ -695,7 +700,8 @@
|
||||||
return OAUTH3.discover(providerUri, opts).then(function (directive) {
|
return OAUTH3.discover(providerUri, opts).then(function (directive) {
|
||||||
var prequest = OAUTH3.urls.refreshToken(directive, opts);
|
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;
|
var data = req.data;
|
||||||
data.provider_uri = providerUri;
|
data.provider_uri = providerUri;
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
|
@ -747,7 +753,7 @@
|
||||||
// Let the Code Waste begin!!
|
// Let the Code Waste begin!!
|
||||||
//
|
//
|
||||||
, _browser: {
|
, _browser: {
|
||||||
window: window
|
window: 'undefined' !== typeof window ? window : null
|
||||||
// TODO we don't need to include this if we're using jQuery or angular
|
// TODO we don't need to include this if we're using jQuery or angular
|
||||||
, discover: function(providerUri, opts) {
|
, discover: function(providerUri, opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
@ -841,7 +847,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
request: xhr
|
_request: xhr
|
||||||
|
, headers: null // TODO
|
||||||
, data: data
|
, data: data
|
||||||
, status: xhr.status
|
, status: xhr.status
|
||||||
});
|
});
|
||||||
|
@ -1047,9 +1054,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
|
||||||
$('.js-signin').removeAttr('disabled');
|
p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OAUTH3.discover(this._clientUri, { client_id: this._clientUri }).then(function (clientDirectives) {
|
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?
|
// 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);
|
||||||
|
|
||||||
return OAUTH3.request(preq, opts);
|
return OAUTH3.request(preq, opts);
|
||||||
}
|
}
|
||||||
, logout: function (opts) {
|
, logout: function (opts) {
|
||||||
|
|
|
@ -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));
|
|
@ -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;
|
||||||
|
|
|
@ -15,9 +15,9 @@ angular
|
||||||
function PromiseAngularQ(fn) {
|
function PromiseAngularQ(fn) {
|
||||||
var d = $q.defer();
|
var d = $q.defer();
|
||||||
|
|
||||||
$timeout(function () {
|
//$timeout(function () {
|
||||||
fn(d.resolve, d.reject);
|
fn(d.resolve, d.reject);
|
||||||
}, 0);
|
//}, 0);
|
||||||
|
|
||||||
//this.then = d.promise.then;
|
//this.then = d.promise.then;
|
||||||
//this.catch = d.promise.catch;
|
//this.catch = d.promise.catch;
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -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));
|
40
package.json
40
package.json
|
@ -1,12 +1,36 @@
|
||||||
{
|
{
|
||||||
"name": "oauth3",
|
"name": "oauth3.js",
|
||||||
"respository": {
|
"version": "1.0.0",
|
||||||
"type": "git",
|
"description": "The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation.",
|
||||||
"url": "git+ssh://git@git.daplie.com:OAuth3/oauth3.js.git"
|
"main": "oauth3.node.js",
|
||||||
},
|
|
||||||
"scripts": {
|
"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": {
|
"devDependencies": {
|
||||||
"browserify-aes": "^1.0.6",
|
"browserify-aes": "^1.0.6",
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
|
@ -20,5 +44,7 @@
|
||||||
"gulp-streamify": "^1.0.2",
|
"gulp-streamify": "^1.0.2",
|
||||||
"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/)",
|
||||||
|
"license": "(MIT OR Apache-2.0)"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue