forked from coolaj86/goldilocks.js
		
	added interface to save user tokens
This commit is contained in:
		
							parent
							
								
									9c7aaa4f98
								
							
						
					
					
						commit
						cfaa8d4959
					
				@ -50,6 +50,9 @@ module.exports.create = function (deps, conf) {
 | 
			
		||||
    prom.then(function (result) {
 | 
			
		||||
      res.send(deps.recase.snakeCopy(result));
 | 
			
		||||
    }).catch(function (err) {
 | 
			
		||||
      if (conf.debug) {
 | 
			
		||||
        console.log(err);
 | 
			
		||||
      }
 | 
			
		||||
      res.statusCode = err.statusCode || 500;
 | 
			
		||||
      err.message = err.message || err.toString();
 | 
			
		||||
      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);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  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')();
 | 
			
		||||
 | 
			
		||||
  // 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.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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,8 @@
 | 
			
		||||
var PromiseA = require('bluebird');
 | 
			
		||||
var path = require('path');
 | 
			
		||||
var fs = PromiseA.promisifyAll(require('fs'));
 | 
			
		||||
var jwt = require('jsonwebtoken');
 | 
			
		||||
var crypto = require('crypto');
 | 
			
		||||
 | 
			
		||||
module.exports.create = function (deps, conf) {
 | 
			
		||||
  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 = {
 | 
			
		||||
    _filename: 'mdns-id'
 | 
			
		||||
  , get: function () {
 | 
			
		||||
@ -119,6 +197,7 @@ module.exports.create = function (deps, conf) {
 | 
			
		||||
    owners: owners
 | 
			
		||||
  , config: config
 | 
			
		||||
  , updateConf: updateConf
 | 
			
		||||
  , tokens: userTokens
 | 
			
		||||
  , mdnsId: mdnsId
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user