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) {
|
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…
Reference in New Issue