'use strict'; var PromiseA = require('bluebird'); var OpErr = PromiseA.OperationalError; function makeB64UrlSafe(b64) { return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=*$/, ''); } function checkIssuerToken(req, expectedSub) { if (!req.oauth3 || !req.oauth3.verifyAsync) { return PromiseA.reject(new OpErr("request requires a token for authorization")); } return req.oauth3.verifyAsync().then(function (token) { // Now that we've confirmed the token is valid we also need to make sure the issuer, audience, // and authorized party are all us, because no other app should be managing user identity. if (token.iss !== req.experienceId || token.aud !== token.iss || token.azp !== token.iss) { throw new OpErr("token does not allow access to requested resource"); } var sub = token.sub || token.ppid || (token.acx && (token.acx.id || token.acx.appScopedId)); if (!sub) { if (!expectedSub || !Array.isArray(token.axs) || !token.axs.length) { throw new OpErr("no account pairwise identifier"); } var allowed = token.axs.some(function (acc) { return expectedSub === (acc.id || acc.ppid || acc.appScopedId); }); if (!allowed) { throw new OpErr("no account pairwise identifier matching '" + expectedSub + "'"); } sub = expectedSub; } if (expectedSub && expectedSub !== sub) { throw new OpErr("token does not allow access to resources for '"+expectedSub+"'"); } return sub; }); } async function getPrimarySub(grantStore, secondary) { var results = await Promise.all([ grantStore.find({ sub: secondary }), grantStore.find({ azpSub: secondary }), ]); // Extract only the sub field from each row and reduce the duplicates so that each value // can only appear in the final list once. var subList = [].concat.apply([], results).map(grant => grant.sub); subList = subList.filter((sub, ind, list) => list.indexOf(sub) === ind); if (subList.length > 1) { // This should not ever happen since there is a check for PPID collisions when saving // grants, but it's probably better to have this check anyway just incase something // happens that isn't currently accounted for. console.error('acounts ' + JSON.stringify(subList) + ' are all associated with "'+secondary+'"'); throw new Error('PPID collision'); } return subList[0]; } module.exports.checkIssuerToken = checkIssuerToken; module.exports.getPrimarySub = getPrimarySub; module.exports.makeB64UrlSafe = makeB64UrlSafe;