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