From 2b432cb36da4fb06f9294e5518934aef8ff57c7c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 4 Dec 2015 21:09:23 +0000 Subject: [PATCH] unfinished cred/profile manangement --- lib/oauth3-auth.js | 166 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 4 deletions(-) diff --git a/lib/oauth3-auth.js b/lib/oauth3-auth.js index b241d82..32cc979 100644 --- a/lib/oauth3-auth.js +++ b/lib/oauth3-auth.js @@ -1,6 +1,7 @@ 'use strict'; var PromiseA = require('bluebird'); +var scoper = require('app-scoped-ids'); module.exports.inject = function (app) { //var jwsUtils = require('./lib/jws-utils').create(signer); @@ -97,10 +98,167 @@ module.exports.inject = function (app) { }); } - app.use('/', function (req, res, next) { - //console.log('[DEBUG CORS]', req.method, req.hostname, req.url); - cors(req, res, next); - }); + function getClient(req, token, priv) { + if (!token) { + token = req.oauth3.token; + } + + var cacheId = '_' + token.k + 'Client'; + + if (priv[cacheId]) { + return PromiseA.resolve(priv[cacheId]); + } + + // TODO could get client directly by token.app (id of client) + priv[cacheId] = ClientsCtrl.login(null, token.k).then(function (apiKey) { + if (!apiKey) { + return PromiseA.reject(new Error("Client no longer valid")); + } + + priv[cacheId + 'Key'] = apiKey; + priv[cacheId] = apiKey.oauthClient; + + return apiKey.oauthClient; + }); + + return priv[cacheId]; + } + + function getLoginId(req, token, priv) { + if (!token) { + token = req.oauth3.token; + } + + var cacheId = '_' + token.idx + 'LoginId'; + + if (priv[cacheId]) { + return PromiseA.resolve(priv[cacheId]); + } + + // TODO + // this ends up defeating part of the purpose of JWT (few database calls) + // perhaps the oauthClient secret should be sent, encrypted with a master key, + // with the request? Or just mash the oauthClient secret with the loginId + // and encrypt with the master key? + priv._loginId = getClient(req, token, priv).then(function (oauthClient) { + var loginId; + + if (token.idx) { + loginId = scoper.unscope(token.idx, oauthClient.secret); + } else { + loginId = token.usr; + } + + priv[cacheId] = loginId; + + return loginId; + }); + + return priv[cacheId]; + } + + function getLogin(req, token, priv) { + if (!token) { + token = req.oauth3.token; + } + + var cacheId = '_' + token.idx + 'Login'; + + if (priv[cacheId]) { + return PromiseA.resolve(priv[cacheId]); + } + + priv[cacheId] = getLoginId(req, token, priv).then(function (loginId) { + return LoginsCtrl.rawGet(loginId).then(function (login) { + priv[cacheId] = login; + + return login; + }); + }); + + return priv[cacheId]; + } + + function getAccountsByLogin(req, token, priv, loginId, decrypt) { + return getClient(req, req.oauth.token, priv).then(function (oauthClient) { + if (decrypt) { + loginId = scoper.unscope(loginId, oauthClient.secret); + } + + return Db.AccountsLogins.find({ loginId: loginId }).then(function (accounts) { + return PromiseA.all(accounts.map(function (obj) { + return Db.Accounts.get(obj.accountId)/*.then(function (account) { + account.appScopedId = weakCipher(oauthClient.secret, account.id); + return account; + })*/; + })); + }); + }); + } + + function getAccountsByArray(req, arr) { + return PromiseA.all(arr.map(function (accountId) { + return Db.Accounts.get(accountId.id || accountId); + })); + } + + function getAccounts(req, token, priv) { + if (!token) { + token = req.oauth3.token; + } + + var err; + + if (priv._accounts) { + return PromiseA.resolve(priv._accounts); + } + + if ((req.oauth3.token.idx || req.oauth3.token.usr) && ('password' === req.oauth3.token.grt || 'login' === req.oauth3.token.as)) { + priv._accounts = getAccountsByLogin(req, req.oauth3.token, priv, (req.oauth3.token.idx || req.oauth3.token.usr), !!req.oauth3.token.idx); + } else if (req.oauth3.token.axs && req.oauth3.token.axs.length || req.oauth3.token.acx) { + req.oauth3._accounts = getAccountsByArray(req, req.oauth3.token.axs && req.oauth3.token.axs.length && req.oauth3.token.axs || [req.oauth3.token.acx]); + } else { + err = new Error("neither login nor accounts were specified"); + err.code = "E_NO_AUTHZ"; + req.oauth3._accounts = PromiseA.reject(err); + } + + req.oauth3._accounts.then(function (accounts) { + req.oauth3._accounts = accounts; + + return accounts; + }); + + return req.oauth3._accounts; + } + + function promiseCredentials(req, res, next) { + var privs = {}; + + // TODO modify prototypes? + req.oauth3.getClient = function (token) { + getClient(req, token || req.oauth3.token, privs); + }; + + req.oauth3.getLoginId = function (token) { + getLoginId(req, token || req.oauth3.token, privs); + }; + + req.oauth3.getLogin = function (token) { + getLogin(req, token || req.oauth3.token, privs); + }; + + // TODO req.oauth3.getAccountIds + req.oauth3.getAccounts = function (token) { + getAccounts(req, token || req.oauth3.token, privs); + }; + + next(); + } + + app.use('/', cors); app.use('/', getToken); + + app.use('/', promiseCredentials); };