added authorization check to grant requests

This commit is contained in:
tigerbot 2017-06-30 12:58:27 -06:00
parent c548b44d19
commit c62cd15644
1 changed files with 50 additions and 36 deletions

86
rest.js
View File

@ -83,15 +83,7 @@ module.exports.create = function (bigconf, deps, app) {
jwk.kid = kid;
jwk.sub = req.params.sub;
return req.Store.find({ kid: jwk.kid, sub: jwk.sub}).then(function (results) {
if (!results.length) {
return crypto.randomBytes(32).toString('hex');
} else {
return results[0].id;
}
}).then(function (id) {
return req.Store.upsert(id, jwk);
});
return req.Store.upsert(jwk.sub+'/'+jwk.kid, jwk);
}).then(function () {
return { success: true };
});
@ -99,44 +91,66 @@ module.exports.create = function (bigconf, deps, app) {
app.handlePromise(req, res, promise, "[issuer@oauth3.org] create JWK");
};
Grants.authorizeReq = function (req) {
return PromiseA.resolve().then(function () {
// It might seem unnecessary to wrap a promise in another promise, but this way it will
// catch the error thrown when a token isn't found and verifyAsync isn't a function.
return req.oauth3.verifyAsync();
}).then(function (token) {
// Just because the token is valid doesn't mean the token is authorized to get or save grants.
// The only place that should be allowed to access grants on behalf of the user is the issuer.
if (token.iss !== token.azp) {
throw new Error("token does not allow access to grants");
}
var sub = token.sub || token.ppid || (token.acx && (token.acx.id || token.acx.appScopedId));
if (!sub) {
if (!Array.isArray(token.axs) || !token.axs.length) {
throw new Error("no account pairwise identifier");
}
var allowed = token.axs.some(function (acc) {
return (req.params.sub || req.query.sub) === (acc.id || acc.ppid || acc.appScopedId);
});
if (!allowed) {
throw new Error("no account pairwise identifier matching '" + req.params.sub + "'");
}
sub = req.params.sub || req.query.sub;
}
return sub;
});
};
Grants.restful.get = function (req, res) {
var query = {
sub: req.params.sub || req.query.sub,
azp: req.params.azp || req.query.azp,
};
var promise = req.Store.find(query, function (results) {
if (!results.length) {
var promise = Grants.authorizeReq(req).then(function (sub) {
return req.Store.get(sub+'/'+(req.params.azp || req.query.azp));
}).then(function (result) {
if (!result) {
throw new Error('no grants found');
}
return {
sub: results[0].sub,
azp: results[0].azp,
scope: results[0].scope,
sub: result.sub,
azp: result.azp,
scope: result.scope,
};
});
app.handlePromise(req, res, promise, "[issuer@oauth3.org] retrieve grants");
};
Grants.restful.saveNew = function (req, res) {
var query = {
sub: req.params.sub,
azp: req.params.azp,
};
var promise = PromiseA.resolve().then(function () {
var promise = Grants.authorizeReq(req).then(function (sub) {
if (typeof req.body.scope !== 'string') {
throw new Error("malformed request: 'scope' should be a string");
}
}).then(function () {
return req.Store.find(query, function (results) {
if (!results.length) {
return crypto.randomBytes(32).toString('hex');
} else {
return results[0].id;
}
});
}).then(function (id) {
query.scope = req.body.scope.replace(/ *, */g, ',');
return req.Store.upsert(id, query);
var scope = req.body.scope.split(/[+ ,]+/g).join(',');
var grant = {
sub: sub,
azp: req.params.azp,
scope: scope,
};
return req.Store.upsert(grant.sub+'/'+grant.azp, grant);
}).then(function () {
return {success: true};
});
@ -149,8 +163,8 @@ module.exports.create = function (bigconf, deps, app) {
app.post( '/jwks/:sub', Jwks.restful.saveNew);
app.use( '/grants', attachSiteStore.bind(null, 'IssuerOauth3OrgGrants'));
app.get( '/grants', Grants.restful.check);
app.get( '/grants/:sub/:azp', Grants.restful.check);
app.get( '/grants', Grants.restful.get);
app.get( '/grants/:sub/:azp', Grants.restful.get);
app.post( '/grants/:sub/:azp', Grants.restful.saveNew);
app.use(detachSiteStore);