| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 00:58:45 -07:00
										 |  |  | module.exports.dependencies = [ 'storage.owners' ]; | 
					
						
							|  |  |  | module.exports.create = function (deps) { | 
					
						
							|  |  |  |   var scmp = require('scmp'); | 
					
						
							|  |  |  |   var crypto = require('crypto'); | 
					
						
							|  |  |  |   var jwt = require('jsonwebtoken'); | 
					
						
							| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  |   var bodyParser = require('body-parser'); | 
					
						
							|  |  |  |   var jsonParser = bodyParser.json({ | 
					
						
							|  |  |  |     inflate: true, limit: '100kb', reviver: null, strict: true /* type, verify */ | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 00:58:45 -07:00
										 |  |  |   /* | 
					
						
							|  |  |  |   var owners; | 
					
						
							|  |  |  |   deps.storage.owners.on('set', function (_owners) { | 
					
						
							|  |  |  |     owners = _owners; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  |   deps.storage.owners.exists = function (id) { | 
					
						
							|  |  |  |     return deps.storage.owners.all().then(function (owners) { | 
					
						
							|  |  |  |       return owners.some(function (owner) { | 
					
						
							|  |  |  |         return scmp(id, owner.id); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 00:58:45 -07:00
										 |  |  |   function isAuthorized(req, res, fn) { | 
					
						
							|  |  |  |     var auth = jwt.decode((req.headers.authorization||'').replace(/^bearer\s+/i, '')); | 
					
						
							|  |  |  |     if (!auth) { | 
					
						
							| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  |       res.setHeader('Content-Type', 'application/json;'); | 
					
						
							| 
									
										
										
										
											2017-03-02 00:58:45 -07:00
										 |  |  |       res.end(JSON.stringify({ error: { message: "no token", code: 'E_NO_TOKEN', uri: undefined } })); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var id = crypto.createHash('sha256').update(auth.sub).digest('hex'); | 
					
						
							|  |  |  |     return deps.storage.owners.exists(id).then(function (exists) { | 
					
						
							|  |  |  |       if (!exists) { | 
					
						
							|  |  |  |         res.setHeader('Content-Type', 'application/json;'); | 
					
						
							|  |  |  |         res.end(JSON.stringify({ error: { message: "not authorized", code: 'E_NO_AUTHZ', uri: undefined } })); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fn(); | 
					
						
							| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-03-02 00:58:45 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     init: function (req, res) { | 
					
						
							|  |  |  |       jsonParser(req, res, function () { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('req.body', req.body); | 
					
						
							|  |  |  |       var auth = jwt.decode((req.headers.authorization||'').replace(/^bearer\s+/i, '')); | 
					
						
							|  |  |  |       var token = jwt.decode(req.body.access_token); | 
					
						
							|  |  |  |       var refresh = jwt.decode(req.body.refresh_token); | 
					
						
							|  |  |  |       auth.sub = auth.sub || auth.acx.id; | 
					
						
							|  |  |  |       token.sub = token.sub || token.acx.id; | 
					
						
							|  |  |  |       refresh.sub = refresh.sub || refresh.acx.id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // TODO validate token with issuer, but as-is the sub is already a secret
 | 
					
						
							|  |  |  |       var id = crypto.createHash('sha256').update(auth.sub).digest('hex'); | 
					
						
							|  |  |  |       var tid = crypto.createHash('sha256').update(token.sub).digest('hex'); | 
					
						
							|  |  |  |       var rid = crypto.createHash('sha256').update(refresh.sub).digest('hex'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('ids', id, tid, rid); | 
					
						
							|  |  |  |       return deps.storage.owners.all().then(function (results) { | 
					
						
							|  |  |  |         console.log('results', results); | 
					
						
							|  |  |  |         var err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // There is no owner yet. First come, first serve.
 | 
					
						
							|  |  |  |         if (!results || !results.length) { | 
					
						
							|  |  |  |           if (tid !== id || rid !== id) { | 
					
						
							|  |  |  |             err = new Error("When creating an owner the Authorization Bearer and Token and Refresh must all match"); | 
					
						
							|  |  |  |             return deps.PromiseA.reject(err); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           console.log('no owner, creating'); | 
					
						
							|  |  |  |           return deps.storage.owners.set(id, { token: token, refresh: refresh }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log('has results'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // There are onwers. Is this one of them?
 | 
					
						
							|  |  |  |         if (!results.some(function (token) { | 
					
						
							|  |  |  |           return scmp(id, token.id); | 
					
						
							|  |  |  |         })) { | 
					
						
							|  |  |  |           err = new Error("Authorization token does not belong to an existing owner."); | 
					
						
							|  |  |  |           return deps.PromiseA.reject(err); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log('has correct owner'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // We're adding an owner, unless it already exists
 | 
					
						
							|  |  |  |         if (!results.some(function (token) { | 
					
						
							|  |  |  |           return scmp(tid, token.id); | 
					
						
							|  |  |  |         })) { | 
					
						
							|  |  |  |           console.log('adds new owner with existing owner'); | 
					
						
							|  |  |  |           return deps.storage.owners.set(id, { token: token, refresh: refresh }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).then(function () { | 
					
						
							|  |  |  |         res.setHeader('Content-Type', 'application/json;'); | 
					
						
							|  |  |  |         res.end(JSON.stringify({ success: true })); | 
					
						
							|  |  |  |       }, function (err) { | 
					
						
							|  |  |  |         res.setHeader('Content-Type', 'application/json;'); | 
					
						
							|  |  |  |         res.end(JSON.stringify({ error: { message: err.message, code: err.code, uri: err.uri } })); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   , config: function (req, res) { | 
					
						
							|  |  |  |       isAuthorized(req, res, function () { | 
					
						
							|  |  |  |         if ('POST' !== req.method) { | 
					
						
							|  |  |  |           res.setHeader('Content-Type', 'application/json;'); | 
					
						
							|  |  |  |           res.end(JSON.stringify(deps.recase.snakeCopy(deps.options))); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         jsonParser(req, res, function () { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           console.log('req.body', req.body); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           deps.storage.config.merge(req.body); | 
					
						
							|  |  |  |           deps.storage.config.save(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-28 14:55:48 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  | }; |