added interface to save user tokens
This commit is contained in:
		
							父節點
							
								
									9c7aaa4f98
								
							
						
					
					
						當前提交
						cfaa8d4959
					
				@ -50,6 +50,9 @@ module.exports.create = function (deps, conf) {
 | 
				
			|||||||
    prom.then(function (result) {
 | 
					    prom.then(function (result) {
 | 
				
			||||||
      res.send(deps.recase.snakeCopy(result));
 | 
					      res.send(deps.recase.snakeCopy(result));
 | 
				
			||||||
    }).catch(function (err) {
 | 
					    }).catch(function (err) {
 | 
				
			||||||
 | 
					      if (conf.debug) {
 | 
				
			||||||
 | 
					        console.log(err);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      res.statusCode = err.statusCode || 500;
 | 
					      res.statusCode = err.statusCode || 500;
 | 
				
			||||||
      err.message = err.message || err.toString();
 | 
					      err.message = err.message || err.toString();
 | 
				
			||||||
      res.end(JSON.stringify({error: {message: err.message, code: err.code}}));
 | 
					      res.end(JSON.stringify({error: {message: err.message, code: err.code}}));
 | 
				
			||||||
@ -524,6 +527,24 @@ module.exports.create = function (deps, conf) {
 | 
				
			|||||||
    handlePromise(req, res, promise);
 | 
					    handlePromise(req, res, promise);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var tokens = { restful: {} };
 | 
				
			||||||
 | 
					  tokens.restful.getAll = function (req, res) {
 | 
				
			||||||
 | 
					    handlePromise(req, res, deps.storage.tokens.all());
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tokens.restful.getOne = function (req, res) {
 | 
				
			||||||
 | 
					    handlePromise(req, res, deps.storage.tokens.get(req.params.id));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tokens.restful.save = function (req, res) {
 | 
				
			||||||
 | 
					    handlePromise(req, res, deps.storage.tokens.save(req.body));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tokens.restful.revoke = function (req, res) {
 | 
				
			||||||
 | 
					    var promise = deps.storage.tokens.remove(req.params.id).then(function (success) {
 | 
				
			||||||
 | 
					      return {success: success};
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    handlePromise(req, res, promise);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var app = require('express')();
 | 
					  var app = require('express')();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Handle all of the API endpoints using the old definition style, and then we can
 | 
					  // Handle all of the API endpoints using the old definition style, and then we can
 | 
				
			||||||
@ -555,5 +576,11 @@ module.exports.create = function (deps, conf) {
 | 
				
			|||||||
  app.put(   '/config/domains/:domId',                        config.restful.updateDomain);
 | 
					  app.put(   '/config/domains/:domId',                        config.restful.updateDomain);
 | 
				
			||||||
  app.delete('/config/domains/:domId',                        config.restful.removeDomain);
 | 
					  app.delete('/config/domains/:domId',                        config.restful.removeDomain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  app.use(   '/tokens', makeCorsHandler(['GET', 'POST', 'DELETE']));
 | 
				
			||||||
 | 
					  app.get(   '/tokens',         tokens.restful.getAll);
 | 
				
			||||||
 | 
					  app.get(   '/tokens/:id',     tokens.restful.getOne);
 | 
				
			||||||
 | 
					  app.post(  '/tokens',         tokens.restful.save);
 | 
				
			||||||
 | 
					  app.delete('/tokens/:id',     tokens.restful.revoke);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return app;
 | 
					  return app;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
var PromiseA = require('bluebird');
 | 
					var PromiseA = require('bluebird');
 | 
				
			||||||
var path = require('path');
 | 
					var path = require('path');
 | 
				
			||||||
var fs = PromiseA.promisifyAll(require('fs'));
 | 
					var fs = PromiseA.promisifyAll(require('fs'));
 | 
				
			||||||
 | 
					var jwt = require('jsonwebtoken');
 | 
				
			||||||
 | 
					var crypto = require('crypto');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.create = function (deps, conf) {
 | 
					module.exports.create = function (deps, conf) {
 | 
				
			||||||
  var hrIds = require('human-readable-ids').humanReadableIds;
 | 
					  var hrIds = require('human-readable-ids').humanReadableIds;
 | 
				
			||||||
@ -93,6 +95,82 @@ module.exports.create = function (deps, conf) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var userTokens = {
 | 
				
			||||||
 | 
					    _filename: 'user-tokens.json'
 | 
				
			||||||
 | 
					  , _convertToken(id, token) {
 | 
				
			||||||
 | 
					      // convert the token into something that looks more like what OAuth3 uses internally
 | 
				
			||||||
 | 
					      // as sessions so we can use it with OAuth3. We don't use OAuth3's internal session
 | 
				
			||||||
 | 
					      // storage because it effectively only supports storing tokens based on provider URI.
 | 
				
			||||||
 | 
					      // We also use the token as the `access_token` instead of `refresh_token` because the
 | 
				
			||||||
 | 
					      // refresh functionality is closely tied to the storage.
 | 
				
			||||||
 | 
					      var decoded = jwt.decode(token);
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        id:           id
 | 
				
			||||||
 | 
					      , access_token: token
 | 
				
			||||||
 | 
					      , token:        decoded
 | 
				
			||||||
 | 
					      , provider_uri: decoded.iss || decoded.issuer || decoded.provider_uri
 | 
				
			||||||
 | 
					      , client_uri:   decoded.azp
 | 
				
			||||||
 | 
					      , scope:        decoded.scp || decoded.scope || decoded.grants
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  , all: function allUserTokens() {
 | 
				
			||||||
 | 
					      var self = this;
 | 
				
			||||||
 | 
					      return read(self._filename).then(function (tokens) {
 | 
				
			||||||
 | 
					        return Object.keys(tokens).map(function (id) {
 | 
				
			||||||
 | 
					          return self._convertToken(id, tokens[id]);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  , get: function getUserToken(id) {
 | 
				
			||||||
 | 
					      var self = this;
 | 
				
			||||||
 | 
					      return read(self._filename).then(function (tokens) {
 | 
				
			||||||
 | 
					        return self._convertToken(id, tokens[id]);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  , save: function saveUserToken(newToken) {
 | 
				
			||||||
 | 
					      var self = this;
 | 
				
			||||||
 | 
					      return read(self._filename).then(function (tokens) {
 | 
				
			||||||
 | 
					        var rawToken;
 | 
				
			||||||
 | 
					        if (typeof newToken === 'string') {
 | 
				
			||||||
 | 
					          rawToken = newToken;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          rawToken = newToken.refresh_token || newToken.access_token;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (typeof rawToken !== 'string') {
 | 
				
			||||||
 | 
					          throw new Error('cannot save invalid session: missing refresh_token and access_token');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var decoded = jwt.decode(rawToken);
 | 
				
			||||||
 | 
					        var idHash = crypto.createHash('sha256');
 | 
				
			||||||
 | 
					        idHash.update(decoded.sub || decoded.ppid || decoded.appScopedId || '');
 | 
				
			||||||
 | 
					        idHash.update(decoded.iss || decoded.issuer || '');
 | 
				
			||||||
 | 
					        idHash.update(decoded.aud || decoded.audience || '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var scope = decoded.scope || decoded.scp || decoded.grants || '';
 | 
				
			||||||
 | 
					        idHash.update(scope.split(/[,\s]+/mg).sort().join(','));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var id = idHash.digest('hex');
 | 
				
			||||||
 | 
					        tokens[id] = rawToken;
 | 
				
			||||||
 | 
					        return write(self._filename, tokens).then(function () {
 | 
				
			||||||
 | 
					          return self.get(id);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  , remove: function removeUserToken(id) {
 | 
				
			||||||
 | 
					      var self = this;
 | 
				
			||||||
 | 
					      return read(self._filename).then(function (tokens) {
 | 
				
			||||||
 | 
					        var present = delete tokens[id];
 | 
				
			||||||
 | 
					        if (!present) {
 | 
				
			||||||
 | 
					          return present;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return write(self._filename, tokens).then(function () {
 | 
				
			||||||
 | 
					          return true;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var mdnsId = {
 | 
					  var mdnsId = {
 | 
				
			||||||
    _filename: 'mdns-id'
 | 
					    _filename: 'mdns-id'
 | 
				
			||||||
  , get: function () {
 | 
					  , get: function () {
 | 
				
			||||||
@ -119,6 +197,7 @@ module.exports.create = function (deps, conf) {
 | 
				
			|||||||
    owners: owners
 | 
					    owners: owners
 | 
				
			||||||
  , config: config
 | 
					  , config: config
 | 
				
			||||||
  , updateConf: updateConf
 | 
					  , updateConf: updateConf
 | 
				
			||||||
 | 
					  , tokens: userTokens
 | 
				
			||||||
  , mdnsId: mdnsId
 | 
					  , mdnsId: mdnsId
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user