Merge branch 'master' into v1.0
This commit is contained in:
commit
0bfdd009b7
|
@ -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
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
.git*
|
||||||
|
browserify/
|
||||||
|
prefactor/
|
||||||
|
gulpfile.js
|
||||||
|
bump-version.sh
|
|
@ -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:');
|
||||||
|
|
157
bin/oauth3.js
157
bin/oauth3.js
|
@ -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;
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f078d479b085e8658fb2039eb3e4de49afd9db0e
|
Subproject commit 91efb1bbf2ab8f4db86f3e93a5c82bf541f1cc67
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -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;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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)"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue