more login logic
This commit is contained in:
		
							parent
							
								
									dd0b257038
								
							
						
					
					
						commit
						79ee4ba7da
					
				
							
								
								
									
										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;
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// opts = { email, providerUri }
 | 
			
		||||
module.exports.login = function (options) {
 | 
			
		||||
  options = options || {};
 | 
			
		||||
  var url = require('url');
 | 
			
		||||
  //console.log('stdin tty', process.stdin.isTTY);
 | 
			
		||||
  //console.log('stdout tty', process.stdout.isTTY);
 | 
			
		||||
  var oauth3;
 | 
			
		||||
  var opts = {
 | 
			
		||||
  providerUri: undefined
 | 
			
		||||
    email: options.email
 | 
			
		||||
  , providerUri: options.providerUri
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
function getCurrentUserEmail() {
 | 
			
		||||
  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();
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
  if (opts.form) {
 | 
			
		||||
    form = opts.form;
 | 
			
		||||
  }
 | 
			
		||||
  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 token locally before performing loginMeta / otp
 | 
			
		||||
      form.println("got to loginMeta");
 | 
			
		||||
      return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (/*result*/) {
 | 
			
		||||
        return { node: emailResult.result || emailResult.input, type: 'email' };
 | 
			
		||||
    return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: email }).then(function (/*result*/) {
 | 
			
		||||
      return { node: email, type: 'email' };
 | 
			
		||||
    }, function (/*err*/) {
 | 
			
		||||
      // TODO require hashcash to create user account
 | 
			
		||||
      function confirmCreateAccount() {
 | 
			
		||||
@ -81,15 +62,14 @@ function getCurrentUserEmail() {
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (!sameProvider) {
 | 
			
		||||
              return { node: emailResult.result || emailResult.input, type: 'email' };
 | 
			
		||||
            return { node: email, type: 'email' };
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          return form.ask({
 | 
			
		||||
            label: "What's your recovery email (or cloud mail) address? ", type: 'email'
 | 
			
		||||
          }).then(function (recoveryResult) {
 | 
			
		||||
              username = emailParts[0];
 | 
			
		||||
            return {
 | 
			
		||||
                node: emailResult.result || emailResult.input
 | 
			
		||||
              node: email
 | 
			
		||||
            , type: 'name'
 | 
			
		||||
            , recovery: recoveryResult.result || recoveryResult.input
 | 
			
		||||
            };
 | 
			
		||||
@ -98,12 +78,7 @@ function getCurrentUserEmail() {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return confirmCreateAccount();
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
return getCurrentUserEmail().then(function (user) {
 | 
			
		||||
    }).then(function (user) {
 | 
			
		||||
      // TODO skip if token exists locally
 | 
			
		||||
      var email = (user.recovery || user.node);
 | 
			
		||||
      form.println("Sending login code to '" + email + "'...");
 | 
			
		||||
@ -140,13 +115,95 @@ return getCurrentUserEmail().then(function (user) {
 | 
			
		||||
            // returns session instead of input
 | 
			
		||||
            var colors = require('colors');
 | 
			
		||||
            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);
 | 
			
		||||
    oauth3.__session = session;
 | 
			
		||||
    return oauth3;
 | 
			
		||||
  });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								node_modules/terminal-forms.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								node_modules/terminal-forms.js
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -1 +1 @@
 | 
			
		||||
Subproject commit f078d479b085e8658fb2039eb3e4de49afd9db0e
 | 
			
		||||
Subproject commit 91efb1bbf2ab8f4db86f3e93a5c82bf541f1cc67
 | 
			
		||||
@ -1118,6 +1118,7 @@
 | 
			
		||||
 | 
			
		||||
        return OAUTH3.implicitGrant(me._providerDirectives, opts).then(function (session) {
 | 
			
		||||
          me._session = true;
 | 
			
		||||
          me.__session = session;
 | 
			
		||||
          return session;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
@ -1130,7 +1131,7 @@
 | 
			
		||||
        preq.client_id = this._clientUri;
 | 
			
		||||
        preq.method = preq.method || 'GET';
 | 
			
		||||
        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?
 | 
			
		||||
        preq.url = OAUTH3.url.resolve(this._providerUri, preq.url);
 | 
			
		||||
@ -1138,6 +1139,8 @@
 | 
			
		||||
        return OAUTH3.request(preq, opts);
 | 
			
		||||
      }
 | 
			
		||||
    , logout: function (opts) {
 | 
			
		||||
        this.__session = false;
 | 
			
		||||
        this._session = false;
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        opts.client_uri = this._clientUri;
 | 
			
		||||
        opts.client_id = this._clientUri;
 | 
			
		||||
@ -1148,7 +1151,8 @@
 | 
			
		||||
    , api: function (api, opts) {
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        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);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -1,46 +1,134 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var fs = require('fs');
 | 
			
		||||
var PromiseA = require('bluebird');
 | 
			
		||||
var fs = PromiseA.promisifyAll(require('fs'));
 | 
			
		||||
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 = {
 | 
			
		||||
  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
 | 
			
		||||
      try {
 | 
			
		||||
        return require(path.join(process.cwd(), providerUri + '.directives.json'));
 | 
			
		||||
        return require(path.join(directivesdir, providerUri + '.json'));
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  , 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;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , 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: {
 | 
			
		||||
    get: function (providerUri, id) {
 | 
			
		||||
      // TODO make safe
 | 
			
		||||
      try {
 | 
			
		||||
        if (id) {
 | 
			
		||||
          return require(path.join(process.cwd(), providerUri + '.' + id + '.session.json'));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          return require(path.join(process.cwd(), providerUri + '.session.json'));
 | 
			
		||||
        }
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
    all: function (providerUri) {
 | 
			
		||||
      var dirname = path.join(oauth3dir, 'sessions');
 | 
			
		||||
      return fs.readdirAsync(dirname).then(function (nodes) {
 | 
			
		||||
        return nodes.map(function (node) {
 | 
			
		||||
          var result = require(path.join(dirname, node));
 | 
			
		||||
          if (result.link) {
 | 
			
		||||
            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) {
 | 
			
		||||
        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 {
 | 
			
		||||
        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;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , 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;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user