handle accounts
This commit is contained in:
		
							parent
							
								
									c045e4c712
								
							
						
					
					
						commit
						4e459ea617
					
				
							
								
								
									
										90
									
								
								lib/extensions/admin/account.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								lib/extensions/admin/account.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | |||||||
|  | <html> | ||||||
|  |   <head> | ||||||
|  |     <title>Telebit Account</title> | ||||||
|  |   </head> | ||||||
|  |   <body> | ||||||
|  |     <form class="js-auth-form"> | ||||||
|  |       <input class="js-auth-subject" type="email"/> | ||||||
|  |       <button class="js-auth-submit" type="submit">Login</button> | ||||||
|  |     </form> | ||||||
|  | 
 | ||||||
|  |     <script src="assets/oauth3.org/oauth3.core.js"></script> | ||||||
|  |     <script> | ||||||
|  |       (function () { | ||||||
|  |         'use strict'; | ||||||
|  |         var OAUTH3 = window.OAUTH3; | ||||||
|  |         var oauth3 = OAUTH3.create({ | ||||||
|  |           host: window.location.host | ||||||
|  |         , pathname: window.location.pathname.replace(/\/[^\/]*$/, '/') | ||||||
|  |         }); | ||||||
|  |         var $ = function () { return document.querySelector.apply(document, arguments); } | ||||||
|  | 
 | ||||||
|  | 				function onChangeProvider(providerUri) { | ||||||
|  | 					// example https://oauth3.org | ||||||
|  | 					return oauth3.setIdentityProvider(providerUri); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// This opens up the login window for the specified provider | ||||||
|  | 				// | ||||||
|  | 				function onClickLogin(ev) { | ||||||
|  |           ev.preventDefault(); | ||||||
|  |           ev.stopPropagation(); | ||||||
|  | 
 | ||||||
|  |           // TODO check subject for provider viability | ||||||
|  |           return oauth3.authenticate({ | ||||||
|  |             subject: $('.js-auth-subject').value | ||||||
|  |           }).then(function (session) { | ||||||
|  | 
 | ||||||
|  | 						console.info('Authentication was Successful:'); | ||||||
|  | 						console.log(session); | ||||||
|  | 
 | ||||||
|  | 						// You can use the PPID (or preferably a hash of it) as the login for your app | ||||||
|  | 						// (it securely functions as both username and password which is known only by your app) | ||||||
|  | 						// If you use a hash of it as an ID, you can also use the PPID itself as a decryption key | ||||||
|  | 						// | ||||||
|  | 						console.info('Secure PPID (aka subject):', session.token.sub); | ||||||
|  | 
 | ||||||
|  | 						return oauth3.request({ | ||||||
|  | 							url: 'https://api.oauth3.org/api/issuer@oauth3.org/jwks/:sub/:kid.json' | ||||||
|  |                 .replace(/:sub/g, session.token.sub) | ||||||
|  |                 .replace(/:kid/g, session.token.iss) | ||||||
|  | 						, session: session | ||||||
|  | 						}).then(function (resp) { | ||||||
|  |               console.info("Public Key:"); | ||||||
|  |               console.log(resp.data); | ||||||
|  | 
 | ||||||
|  |               return oauth3.request({ | ||||||
|  |                 url: 'https://api.oauth3.org/api/issuer@oauth3.org/acl/profile' | ||||||
|  |               , session: session | ||||||
|  |               }).then(function (resp) { | ||||||
|  | 
 | ||||||
|  |                 console.info("Inspect Token:"); | ||||||
|  |                 console.log(resp.data); | ||||||
|  | 
 | ||||||
|  |                 return oauth3.request({ | ||||||
|  |                   url: 'https://api.telebit.cloud/api/telebit.cloud/account' | ||||||
|  |                 , session: session | ||||||
|  |                 }).then(function (resp) { | ||||||
|  | 
 | ||||||
|  |                   console.info("Telebit Account:"); | ||||||
|  |                   console.log(resp.data); | ||||||
|  | 
 | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |               }); | ||||||
|  | 
 | ||||||
|  | 						}); | ||||||
|  | 
 | ||||||
|  | 					}, function (err) { | ||||||
|  | 						console.error('Authentication Failed:'); | ||||||
|  | 						console.log(err); | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  |         $('body form.js-auth-form').addEventListener('submit', onClickLogin); | ||||||
|  |         onChangeProvider('oauth3.org'); | ||||||
|  |       }()); | ||||||
|  |     </script> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
| @ -29,6 +29,9 @@ | |||||||
|       <p>Friends enable friends to share anything, access anywhere, connect anytime.</p> |       <p>Friends enable friends to share anything, access anywhere, connect anytime.</p> | ||||||
|     </center> |     </center> | ||||||
| 
 | 
 | ||||||
|  |     <a href="account.html#/login">Login</a> | ||||||
|  |     <a href="account.html#/create_account">Create Account</a> | ||||||
|  | 
 | ||||||
|     <div style="width: 800px; margin: auto;"> |     <div style="width: 800px; margin: auto;"> | ||||||
|       <div> |       <div> | ||||||
|         <h2>Share and Test over HTTPS</h2> |         <h2>Share and Test over HTTPS</h2> | ||||||
| @ -139,74 +142,6 @@ TCP | |||||||
| 
 | 
 | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <form class="js-auth-form"> |  | ||||||
|       <input class="js-auth-subject" type="email"/> |  | ||||||
|       <button class="js-auth-submit" type="submit">Login</button> |  | ||||||
|     </form> |  | ||||||
|     <script src="assets/oauth3.org/oauth3.core.js"></script> |  | ||||||
|     <script> |  | ||||||
|       (function () { |  | ||||||
|         'use strict'; |  | ||||||
|         var OAUTH3 = window.OAUTH3; |  | ||||||
|         var oauth3 = OAUTH3.create(window.location); |  | ||||||
|         var $ = function () { return document.querySelector.apply(document, arguments); } |  | ||||||
| 
 |  | ||||||
| 				function onChangeProvider(providerUri) { |  | ||||||
| 					// example https://oauth3.org |  | ||||||
| 					return oauth3.setIdentityProvider(providerUri); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				// This opens up the login window for the specified provider |  | ||||||
| 				// |  | ||||||
| 				function onClickLogin(ev) { |  | ||||||
|           ev.preventDefault(); |  | ||||||
|           ev.stopPropagation(); |  | ||||||
| 
 |  | ||||||
|           // TODO check subject for provider viability |  | ||||||
|           return oauth3.authenticate({ |  | ||||||
|             subject: $('.js-auth-subject').value |  | ||||||
|           }).then(function (session) { |  | ||||||
| 
 |  | ||||||
| 						console.info('Authentication was Successful:'); |  | ||||||
| 						console.log(session); |  | ||||||
| 
 |  | ||||||
| 						// You can use the PPID (or preferably a hash of it) as the login for your app |  | ||||||
| 						// (it securely functions as both username and password which is known only by your app) |  | ||||||
| 						// If you use a hash of it as an ID, you can also use the PPID itself as a decryption key |  | ||||||
| 						// |  | ||||||
| 						console.info('Secure PPID (aka subject):', session.token.sub); |  | ||||||
| 
 |  | ||||||
| 						return oauth3.request({ |  | ||||||
| 							url: 'https://api.oauth3.org/api/issuer@oauth3.org/jwks/:sub/:kid.json' |  | ||||||
|                 .replace(/:sub/g, session.token.sub) |  | ||||||
|                 .replace(/:kid/g, session.token.iss) |  | ||||||
| 						, session: session |  | ||||||
| 						}).then(function (resp) { |  | ||||||
|               console.info("Public Key:"); |  | ||||||
|               console.log(resp.data); |  | ||||||
| 
 |  | ||||||
|               return oauth3.request({ |  | ||||||
|                 url: 'https://api.oauth3.org/api/issuer@oauth3.org/acl/profile' |  | ||||||
|               , session: session |  | ||||||
|               }).then(function (resp) { |  | ||||||
| 
 |  | ||||||
|                 console.info("Inspect Token:"); |  | ||||||
|                 console.log(resp.data); |  | ||||||
| 
 |  | ||||||
|               }); |  | ||||||
| 
 |  | ||||||
| 						}); |  | ||||||
| 
 |  | ||||||
| 					}, function (err) { |  | ||||||
| 						console.error('Authentication Failed:'); |  | ||||||
| 						console.log(err); |  | ||||||
| 					}); |  | ||||||
| 
 |  | ||||||
| 				} |  | ||||||
|         $('body form.js-auth-form').addEventListener('submit', onClickLogin); |  | ||||||
|         onChangeProvider('oauth3.org'); |  | ||||||
|       }()); |  | ||||||
|     </script> |  | ||||||
|     <script src="js/app.js"></script> |     <script src="js/app.js"></script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  | |||||||
| @ -6,7 +6,9 @@ var util = require('util'); | |||||||
| var crypto = require('crypto'); | var crypto = require('crypto'); | ||||||
| var escapeHtml = require('escape-html'); | var escapeHtml = require('escape-html'); | ||||||
| var jwt = require('jsonwebtoken'); | var jwt = require('jsonwebtoken'); | ||||||
| var requestAsync = util.promisify(require('request')); | var requestAsync = util.promisify(require('@coolaj86/urequest')); | ||||||
|  | var readFileAsync = util.promisify(fs.readFile); | ||||||
|  | var mkdirpAsync = util.promisify(require('mkdirp')); | ||||||
| 
 | 
 | ||||||
| var _auths = module.exports._auths = {}; | var _auths = module.exports._auths = {}; | ||||||
| var Auths = {}; | var Auths = {}; | ||||||
| @ -77,6 +79,72 @@ Auths._clean = function () { | |||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | var sfs = require('safe-replace'); | ||||||
|  | var Accounts = {}; | ||||||
|  | Accounts._getTokenId = function (auth) { | ||||||
|  |   return auth.data.sub + '@' + (auth.data.iss||'').replace(/\/|\\/g, '-'); | ||||||
|  | }; | ||||||
|  | Accounts._accPath = function (req, accId) { | ||||||
|  |   return path.join(req._state.config.accountsDir, 'self', accId); | ||||||
|  | }; | ||||||
|  | Accounts._subPath = function (req, id) { | ||||||
|  |   return path.join(req._state.config.accountsDir, 'oauth3', id); | ||||||
|  | }; | ||||||
|  | Accounts._setSub = function (req, id, subData) { | ||||||
|  |   var subpath = Accounts._subPath(req, id); | ||||||
|  |   return mkdirpAsync(subpath).then(function () { | ||||||
|  |     return sfs.writeFileAsync(path.join(subpath, 'index.json'), JSON.stringify(subData)); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | Accounts._setAcc = function (req, accId, acc) { | ||||||
|  |   var accpath = Accounts._accPath(req, accId); | ||||||
|  |   return mkdirpAsync(accpath).then(function () { | ||||||
|  |     return sfs.writeFileAsync(path.join(accpath, 'index.json'), JSON.stringify(acc)); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | Accounts.create = function (req) { | ||||||
|  |   var id = Accounts._getTokenId(req.auth); | ||||||
|  |   var acc = { | ||||||
|  |     sub: crypto.randomBytes(16).toString('hex') | ||||||
|  |          // TODO use something from the request to know which of the domains to use
 | ||||||
|  |   , iss: req._state.config.webminDomain | ||||||
|  |   , contacts: [] | ||||||
|  |   }; | ||||||
|  |   var accId = Accounts._getTokenId(acc); | ||||||
|  |   acc.id = accId; | ||||||
|  | 
 | ||||||
|  |   // TODO notify any non-authorized accounts that they've been added?
 | ||||||
|  |   return Accounts.getBySub(req).then(function (subData) { | ||||||
|  |     subData.accounts.push({ type: 'self', id: accId }); | ||||||
|  |     acc.contacts.push({ type: 'oauth3', id: subData.id, sub: subData.sub, iss: subData.iss }); | ||||||
|  |     return Accounts._setSub(req, id, subData).then(function () { | ||||||
|  |       return Accounts._setAcc(req, accId, acc).then(function () { | ||||||
|  |         return acc; | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | /* | ||||||
|  | // TODO an owner of an asset can give permission to another entity
 | ||||||
|  | // but that does not mean that that owner has access to that entity's things
 | ||||||
|  | // Example:
 | ||||||
|  | //   A 3rd party login's email verification cannot be trusted for auth
 | ||||||
|  | //   Only 1st party verifications can be trusted for authorization
 | ||||||
|  | Accounts.link = function (req) { | ||||||
|  | }; | ||||||
|  | */ | ||||||
|  | Accounts.getBySub = function (req) { | ||||||
|  |   var id = Accounts._getTokenId(req.auth); | ||||||
|  |   var subpath = Accounts._subPath(req, id); | ||||||
|  |   return readFileAsync(path.join(subpath, 'index.json'), 'utf8').then(function (text) { | ||||||
|  |     return JSON.parse(text); | ||||||
|  |   }, function (/*err*/) { | ||||||
|  |     return null; | ||||||
|  |   }).then(function (links) { | ||||||
|  |     return links || { id: id, sub: req.auth.sub, iss: req.auth.iss, accounts: [] }; | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| function sendMail(state, auth) { | function sendMail(state, auth) { | ||||||
|   console.log('[DEBUG] ext auth', auth); |   console.log('[DEBUG] ext auth', auth); | ||||||
|   /* |   /* | ||||||
| @ -137,6 +205,179 @@ function sendMail(state, auth) { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // TODO replace with OAuth3 function
 | ||||||
|  | function oauth3Auth(req, res, next) { | ||||||
|  |   var jwt = require('jsonwebtoken'); | ||||||
|  |   var verifyJwt = util.promisify(jwt.verify); | ||||||
|  |   var token = (req.headers.authorization||'').replace(/^bearer /i, ''); | ||||||
|  |   var auth; | ||||||
|  |   var authData; | ||||||
|  | 
 | ||||||
|  |   if (!token) { | ||||||
|  |     res.send({ | ||||||
|  |       error: { | ||||||
|  |         code: "E_NOAUTH" | ||||||
|  |       , message: "no authorization header" | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     authData = jwt.decode(token, { complete: true }); | ||||||
|  |   } catch(e) { | ||||||
|  |     authData = null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!authData) { | ||||||
|  |     res.send({ | ||||||
|  |       error: { | ||||||
|  |         code: "E_PARSEAUTH" | ||||||
|  |       , message: "could not parse authorization header as JWT" | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   auth = authData.payload; | ||||||
|  |   if (!auth.sub && ('*' === auth.aud || '*' === auth.azp)) { | ||||||
|  |     res.send({ | ||||||
|  |       error: { | ||||||
|  |         code: "E_NOIMPL" | ||||||
|  |       , message: "missing 'sub' and a wildcard 'azp' or 'aud' indicates that this is an exchange token," | ||||||
|  |          + " however, this app has not yet implemented opaque token exchange" | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if ([ 'sub', 'iss' ].some(function (key) { | ||||||
|  |     if ('string' !== typeof auth[key]) { | ||||||
|  |       res.send({ | ||||||
|  |         error: { | ||||||
|  |           code: "E_PARSEAUTH" | ||||||
|  |         , message: "could not read property '" + key + "' of authorization token" | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   })) { return; } | ||||||
|  |   if ([ 'kid' ].some(function (key) { | ||||||
|  |     if (/\/|\\/.test(authData.header[key])) { | ||||||
|  |       res.send({ | ||||||
|  |         error: { | ||||||
|  |           code: "E_PARSESUBJECT" | ||||||
|  |         , message: "'" + key + "' `" + JSON.stringify(authData.header[key]) + "' contains invalid characters" | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   })) { return; } | ||||||
|  |   if ([ 'sub', 'kid' ].some(function (key) { | ||||||
|  |     if (/\/|\\/.test(auth[key])) { | ||||||
|  |       res.send({ | ||||||
|  |         error: { | ||||||
|  |           code: "E_PARSESUBJECT" | ||||||
|  |         , message: "'" + key + "' `" + JSON.stringify(auth[key]) + "' contains invalid characters" | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   })) { return; } | ||||||
|  | 
 | ||||||
|  |   // TODO needs to work with app:// and custom://
 | ||||||
|  |   function prefixHttps(str) { | ||||||
|  |     return (str||'').replace(/^(https?:\/\/)?/i, 'https://'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var url = require('url'); | ||||||
|  |   var discoveryUrl = url.resolve(prefixHttps(auth.iss), '_apis/oauth3.org/index.json'); | ||||||
|  |   console.log('discoveryUrl: ', discoveryUrl, auth.iss); | ||||||
|  |   return requestAsync({ | ||||||
|  |     url: discoveryUrl | ||||||
|  |   , json: true | ||||||
|  |   }).then(function (resp) { | ||||||
|  | 
 | ||||||
|  |     // TODO
 | ||||||
|  |     // it may be necessary to exchange the token,
 | ||||||
|  | 
 | ||||||
|  |     if (200 !== resp.statusCode || 'object' !== typeof resp.body || !resp.body.retrieve_jwk | ||||||
|  |         || 'string' !== typeof resp.body.retrieve_jwk.url || 'string' !== typeof resp.body.api) { | ||||||
|  |       res.send({ | ||||||
|  |         error: { | ||||||
|  |           code: "E_NOTFOUND" | ||||||
|  |         , message: resp.statusCode + ": issuer `" + JSON.stringify(auth.iss) | ||||||
|  |             + "' does not declare 'api' & 'retrieve_key' and hence the token you provided cannot be verified." | ||||||
|  |         , _status: resp.statusCode | ||||||
|  |         , _url: discoveryUrl | ||||||
|  |         , _body: resp.body | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     var keyUrl = url.resolve( | ||||||
|  |         prefixHttps(resp.body.api).replace(/:hostname/g, auth.iss) | ||||||
|  |       , resp.body.retrieve_jwk.url | ||||||
|  |           .replace(/:hostname/g, auth.iss) | ||||||
|  |           .replace(/:sub/g, auth.sub) | ||||||
|  |           // TODO
 | ||||||
|  |           .replace(/:kid/g, authData.header.kid || auth.iss) | ||||||
|  |     ); | ||||||
|  |     console.log('keyUrl: ', keyUrl); | ||||||
|  |     return requestAsync({ | ||||||
|  |       url: keyUrl | ||||||
|  |     , json: true | ||||||
|  |     }).then(function (resp) { | ||||||
|  |       var jwk = resp.body; | ||||||
|  |       if (200 !== resp.statusCode || 'object' !== typeof resp.body) { | ||||||
|  |         //headers.authorization
 | ||||||
|  |         res.send({ | ||||||
|  |           error: { | ||||||
|  |             code: "E_NOTFOUND" | ||||||
|  |           , message: resp.statusCode + ": did not retrieve public key from `" + JSON.stringify(auth.iss) | ||||||
|  |               + "' for token validation and hence the token you provided cannot be verified." | ||||||
|  |           , _status: resp.statusCode | ||||||
|  |           , _url: keyUrl | ||||||
|  |           , _body: resp.body | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var pubpem; | ||||||
|  |       try { | ||||||
|  |         pubpem = require('jwk-to-pem')(jwk, { private: false }); | ||||||
|  |       } catch(e) { | ||||||
|  |         pubpem = null; | ||||||
|  |       } | ||||||
|  | 			return verifyJwt(token, pubpem, { | ||||||
|  | 				algorithms: [ 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512' ] | ||||||
|  | 			}).then(function (decoded) { | ||||||
|  |         if (!decoded) { | ||||||
|  |           res.send({ | ||||||
|  |             error: { | ||||||
|  |               code: "E_UNVERIFIED" | ||||||
|  |             , message: "retrieved jwk does not verify provided token." | ||||||
|  |             , _jwk: jwk | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |         req.auth = {}; | ||||||
|  |         req.auth.jwt = token; | ||||||
|  |         req.auth.data = auth; | ||||||
|  |         next(); | ||||||
|  | 			}); | ||||||
|  |     }); | ||||||
|  |   }, function (err) { | ||||||
|  |     res.send({ | ||||||
|  |       error: { | ||||||
|  |         code: err.code || "E_GENERIC" | ||||||
|  |       , message: err.toString() | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| module.exports.pairRequest = function (opts) { | module.exports.pairRequest = function (opts) { | ||||||
|   console.log("It's auth'n time!"); |   console.log("It's auth'n time!"); | ||||||
|   var state = opts.state; |   var state = opts.state; | ||||||
| @ -357,9 +598,36 @@ var urls = { | |||||||
|   pairState: '/api/telebit.cloud/pair_state/:id' |   pairState: '/api/telebit.cloud/pair_state/:id' | ||||||
| }; | }; | ||||||
| staticApp.use('/', express.static(path.join(__dirname, 'admin'))); | staticApp.use('/', express.static(path.join(__dirname, 'admin'))); | ||||||
| app.use('/api', CORS({})); | app.use('/api', CORS({ | ||||||
|  |   credentials: true | ||||||
|  | , headers: [ 'Authorization', 'X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept' ] | ||||||
|  | })); | ||||||
| app.use('/api', bodyParser.json()); | app.use('/api', bodyParser.json()); | ||||||
| 
 | 
 | ||||||
|  | app.use('/api/telebit.cloud/account', oauth3Auth); | ||||||
|  | app.get('/api/telebit.cloud/account', function (req, res) { | ||||||
|  |   Accounts.getBySub(req).then(function (subData) { | ||||||
|  |     res.send(subData); | ||||||
|  |   }, function (err) { | ||||||
|  |     res.send({ | ||||||
|  |       error: { | ||||||
|  |         code: err.code || "E_GENERIC" | ||||||
|  |       , message: err.toString() | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | app.post('/api/telebit.cloud/account', function (req, res) { | ||||||
|  |   return Accounts.create(req).then(function (acc) { | ||||||
|  |     res.send({ | ||||||
|  |       success: true | ||||||
|  |     , id: acc.id | ||||||
|  |     , sub: acc.sub | ||||||
|  |     , iss: acc.iss | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| // From Device (which knows id, but not secret)
 | // From Device (which knows id, but not secret)
 | ||||||
| app.post('/api/telebit.cloud/pair_request', function (req, res) { | app.post('/api/telebit.cloud/pair_request', function (req, res) { | ||||||
|   var auth = req.body; |   var auth = req.body; | ||||||
| @ -383,7 +651,7 @@ app.post('/api/telebit.cloud/pair_request', function (req, res) { | |||||||
| app.get('/api/telebit.cloud/pair_request/:secret', function (req, res) { | app.get('/api/telebit.cloud/pair_request/:secret', function (req, res) { | ||||||
|   var secret = req.params.secret; |   var secret = req.params.secret; | ||||||
|   var auth = Auths.getBySecret(secret); |   var auth = Auths.getBySecret(secret); | ||||||
|   var crypto = require('crypto'); |   //var crypto = require('crypto');
 | ||||||
|   var response = {}; |   var response = {}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								package.json
									
									
									
									
									
								
							| @ -37,8 +37,7 @@ | |||||||
|   }, |   }, | ||||||
|   "homepage": "https://git.coolaj86.com/coolaj86/telebit-relay.js", |   "homepage": "https://git.coolaj86.com/coolaj86/telebit-relay.js", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@coolaj86/urequest": "^1.1.1", |     "@coolaj86/urequest": "^1.2.1", | ||||||
|     "bluebird": "^3.5.1", |  | ||||||
|     "body-parser": "^1.18.3", |     "body-parser": "^1.18.3", | ||||||
|     "cluster-store": "^2.0.8", |     "cluster-store": "^2.0.8", | ||||||
|     "connect-cors": "^0.5.6", |     "connect-cors": "^0.5.6", | ||||||
| @ -48,16 +47,22 @@ | |||||||
|     "greenlock": "^2.2.4", |     "greenlock": "^2.2.4", | ||||||
|     "human-readable-ids": "^1.0.4", |     "human-readable-ids": "^1.0.4", | ||||||
|     "js-yaml": "^3.11.0", |     "js-yaml": "^3.11.0", | ||||||
|     "jsonwebtoken": "^8.2.1", |     "jsonwebtoken": "^8.3.0", | ||||||
|  |     "jwk-to-pem": "^2.0.0", | ||||||
|  |     "mkdirp": "^0.5.1", | ||||||
|     "nowww": "^1.2.1", |     "nowww": "^1.2.1", | ||||||
|     "proxy-packer": "^1.4.3", |     "proxy-packer": "^1.4.3", | ||||||
|     "recase": "^1.0.4", |     "recase": "^1.0.4", | ||||||
|     "redirect-https": "^1.1.5", |     "redirect-https": "^1.1.5", | ||||||
|     "request": "^2.87.0", |     "request": "^2.87.0", | ||||||
|  |     "safe-replace": "^1.0.3", | ||||||
|     "serve-static": "^1.13.2", |     "serve-static": "^1.13.2", | ||||||
|     "sni": "^1.0.0", |     "sni": "^1.0.0", | ||||||
|     "ws": "^5.1.1" |     "ws": "^5.1.1" | ||||||
|   }, |   }, | ||||||
|  |   "trulyOptionalDependencies": { | ||||||
|  |     "bluebird": "^3.5.1" | ||||||
|  |   }, | ||||||
|   "engineStrict": true, |   "engineStrict": true, | ||||||
|   "engines": { |   "engines": { | ||||||
|     "node": "10.2.1" |     "node": "10.2.1" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user