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; | 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; | ||||||
|   }); |   }); | ||||||
|   }); | }; | ||||||
| }); |  | ||||||
|  | |||||||
							
								
								
									
										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) { |         return OAUTH3.implicitGrant(me._providerDirectives, opts).then(function (session) { | ||||||
|           me._session = true; |           me._session = true; | ||||||
|  |           me.__session = session; | ||||||
|           return session; |           return session; | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
| @ -1130,7 +1131,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); | ||||||
| @ -1138,6 +1139,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; | ||||||
| @ -1148,7 +1151,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); | ||||||
|       } |       } | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -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; | ||||||
|  |       }); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user