From 8397b8a38cf6fb04c9d532cf2594551f53287326 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 2 Dec 2017 08:43:45 +0000 Subject: [PATCH] WIP token exchange --- accounts.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++------ rest.js | 1 + 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/accounts.js b/accounts.js index 6429c03..3fa7815 100644 --- a/accounts.js +++ b/accounts.js @@ -210,10 +210,56 @@ function create(app) { console.log('[exchangeToken] OAUTH3.jwk:'); console.log(OAUTH3.jwk); - var promise = OAUTH3.jwk.verifyToken(req.oauth3.encodedToken).then(function (result) { - console.log('[exchangeToken] verifyToken result:'); - console.log(result); - return { error: { code: "E_NO_IMPL", message: "not implemented [183]" } }; + var promise = OAUTH3.jwk.verifyToken(req.oauth3.encodedToken).then(function (decoded) { + console.log('[exchangeToken] verified token:'); + console.log(decoded); + // TODO handle opaque tokens by exchanging at issuer -- if (!token.sub && token.jti) { ... } + return req.Models.IssuerOauth3OrgCredentialsProfiles.find({ + credentialId: decoded.payload.sub + '@' + decoded.payload.iss + //, sub: decoded.payload.sub + //, iss: decoded.payload.iss + }).then(function (results) { + console.log('[exchangeToken] credentials profiles:'); + console.log(results); + + if (!results) { + return { tokens: [] }; + } + + results = results.filter(function (el) { + return !el.revokedAt && !el.deletedAt; + }); + + if (!results.length) { + return { tokens: [] }; + } + + return req.Models.IssuerOauth3OrgAccounts.find({ + accountId: 'IN ' + results.map(function (el) { return el.credentialId }).join(',') + }).then(function (profiles) { + if (!results) { + return { tokens: [] }; + } + + profiles = profiles.filter(function (el) { + return !el.revokedAt && !el.deletedAt; + }); + + if (!results.length) { + return { tokens: [] }; + } + + return req.deps.Promise.all(profiles.map(function (profile) { + var tokenInfo = { sub: profile.sub, iss: profile.iss, azp: profile.iss, aud: profile.iss }; + return restful.createToken._helper(req, res, tokenInfo); + })).then(function (tokens) { + return { + error: { code: "E_NO_IMPL", message: "not implemented [172]" } + , tokens: tokens + }; + }); + }); + }); }); app.handlePromise(req, res, promise, '[issuer@oauth3.org] exchangeToken'); @@ -236,9 +282,19 @@ function create(app) { if (req.body.grant_type === 'refresh_token') { return restful.createToken.refreshToken(req); } + if (req.body.grant_type === 'exchange_token') { + return restful.exchangeToken(req); + } throw new OpErr("unknown or un-implemented grant_type '"+req.body.grant_type+"'"); }).then(function (token_info) { + return restful.createToken._helper(req, res, token_info); + }); + + app.handlePromise(req, res, promise, '[issuer@oauth3.org] create tokens'); + }; + restful.createToken._helper = function (req, res, token_info) { + return req.deps.Promise.resolve().then(function () { token_info.iss = req.experienceId; if (!token_info.aud) { throw new OpErr("missing required token field 'aud'"); @@ -251,16 +307,17 @@ function create(app) { // We don't have normal grants for the issuer, so we don't need to look the // azpSub or the grants up in the database. token_info.azpSub = token_info.sub; - token_info.scope = ''; + token_info.scope = '*'; return token_info; } var search = {}; - ['sub', 'azp', 'azpSub'].forEach(function (key) { + [ 'sub', 'azp', 'azpSub' ].forEach(function (key) { if (token_info[key]) { search[key] = token_info[key]; } }); + return store.IssuerOauth3OrgGrants.find(search).then(function (grants) { if (!grants.length) { throw new OpErr("'"+token_info.azp+"' not given any grants from '"+(token_info.sub || token_info.azpSub)+"'"); @@ -317,8 +374,6 @@ function create(app) { return result; }); }); - - app.handlePromise(req, res, promise, '[issuer@oauth3.org] create tokens'); }; restful.createToken.password = function (req) { var params = req.body; diff --git a/rest.js b/rest.js index 056241a..c2d9e56 100644 --- a/rest.js +++ b/rest.js @@ -48,6 +48,7 @@ module.exports.create = function (bigconf, deps, app) { app.post( '/access_token/:sub/:aud/:azp', Accounts.restful.createToken); app.post( '/access_token', Accounts.restful.createToken); + app.use( '/exchange_token', attachSiteModels); app.post( '/exchange_token', Accounts.restful.exchangeToken); app.use( '/acl/profile', attachSiteModels);