diff --git a/src/oidc.js b/src/oidc.js index 1d869549b..b2660cd8a 100644 --- a/src/oidc.js +++ b/src/oidc.js @@ -9,29 +9,26 @@ exports = module.exports = { del: clientsDel, update: clientsUpdate, list: clientsList - }, - routes: { - renderInteractionPage, - interactionLogin, - interactionConfirm, - interactionAbort } }; const assert = require('assert'), BoxError = require('./boxerror.js'), + constants = require('./constants.js'), database = require('./database.js'), debug = require('debug')('box:oidc'), ejs = require('ejs'), + express = require('express'), fs = require('fs'), middleware = require('./middleware'), path = require('path'), paths = require('./paths.js'), + http = require('http'), HttpError = require('connect-lastmile').HttpError, - HttpSuccess = require('connect-lastmile').HttpSuccess, - users = require('./users.js'), safe = require('safetydance'), - settings = require('./settings.js'); + settings = require('./settings.js'), + users = require('./users.js'), + util = require('util'); const OIDC_CLIENTS_TABLE_NAME = 'oidcClients'; const OIDC_CLIENTS_FIELDS = [ 'id', 'secret', 'loginRedirectUri', 'logoutRedirectUri' ]; @@ -88,18 +85,17 @@ async function clientsList() { } class CloudronAdapter { - - /** - * - * Creates an instance of MyAdapter for an oidc-provider model. - * - * @constructor - * @param {string} name Name of the oidc-provider model. One of "Grant, "Session", "AccessToken", - * "AuthorizationCode", "RefreshToken", "ClientCredentials", "Client", "InitialAccessToken", - * "RegistrationAccessToken", "DeviceCode", "Interaction", "ReplayDetection", - * "BackchannelAuthenticationRequest", or "PushedAuthorizationRequest" - * - */ + /** + * + * Creates an instance of MyAdapter for an oidc-provider model. + * + * @constructor + * @param {string} name Name of the oidc-provider model. One of "Grant, "Session", "AccessToken", + * "AuthorizationCode", "RefreshToken", "ClientCredentials", "Client", "InitialAccessToken", + * "RegistrationAccessToken", "DeviceCode", "Interaction", "ReplayDetection", + * "BackchannelAuthenticationRequest", or "PushedAuthorizationRequest" + * + */ constructor(name) { this.name = name; @@ -122,18 +118,18 @@ class CloudronAdapter { } } - /** - * - * Update or Create an instance of an oidc-provider model. - * - * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when - * encountered. - * @param {string} id Identifier that oidc-provider will use to reference this model instance for - * future operations. - * @param {object} payload Object with all properties intended for storage. - * @param {integer} expiresIn Number of seconds intended for this model to be stored. - * - */ + /** + * + * Update or Create an instance of an oidc-provider model. + * + * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when + * encountered. + * @param {string} id Identifier that oidc-provider will use to reference this model instance for + * future operations. + * @param {object} payload Object with all properties intended for storage. + * @param {integer} expiresIn Number of seconds intended for this model to be stored. + * + */ async upsert(id, payload, expiresIn) { debug(`[${this.name}] upsert id:${id} expiresIn:${expiresIn}`, payload); @@ -145,16 +141,16 @@ class CloudronAdapter { } } - /** - * - * Return previously stored instance of an oidc-provider model. - * - * @return {Promise} Promise fulfilled with what was previously stored for the id (when found and - * not dropped yet due to expiration) or falsy value when not found anymore. Rejected with error - * when encountered. - * @param {string} id Identifier of oidc-provider model - * - */ + /** + * + * Return previously stored instance of an oidc-provider model. + * + * @return {Promise} Promise fulfilled with what was previously stored for the id (when found and + * not dropped yet due to expiration) or falsy value when not found anymore. Rejected with error + * when encountered. + * @param {string} id Identifier of oidc-provider model + * + */ async find(id) { debug(`[${this.name}] find id:${id}`); @@ -179,31 +175,31 @@ class CloudronAdapter { } } - /** - * - * Return previously stored instance of DeviceCode by the end-user entered user code. You only - * need this method for the deviceFlow feature - * - * @return {Promise} Promise fulfilled with the stored device code object (when found and not - * dropped yet due to expiration) or falsy value when not found anymore. Rejected with error - * when encountered. - * @param {string} userCode the user_code value associated with a DeviceCode instance - * - */ + /** + * + * Return previously stored instance of DeviceCode by the end-user entered user code. You only + * need this method for the deviceFlow feature + * + * @return {Promise} Promise fulfilled with the stored device code object (when found and not + * dropped yet due to expiration) or falsy value when not found anymore. Rejected with error + * when encountered. + * @param {string} userCode the user_code value associated with a DeviceCode instance + * + */ async findByUserCode(userCode) { debug(`[${this.name}] FIXME findByUserCode userCode:${userCode}`); } - /** - * - * Return previously stored instance of Session by its uid reference property. - * - * @return {Promise} Promise fulfilled with the stored session object (when found and not - * dropped yet due to expiration) or falsy value when not found anymore. Rejected with error - * when encountered. - * @param {string} uid the uid value associated with a Session instance - * - */ + /** + * + * Return previously stored instance of Session by its uid reference property. + * + * @return {Promise} Promise fulfilled with the stored session object (when found and not + * dropped yet due to expiration) or falsy value when not found anymore. Rejected with error + * when encountered. + * @param {string} uid the uid value associated with a Session instance + * + */ async findByUid(uid) { debug(`[${this.name}] findByUid uid:${uid}`); @@ -218,17 +214,17 @@ class CloudronAdapter { } } - /** - * - * Mark a stored oidc-provider model as consumed (not yet expired though!). Future finds for this - * id should be fulfilled with an object containing additional property named "consumed" with a - * truthy value (timestamp, date, boolean, etc). - * - * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when - * encountered. - * @param {string} id Identifier of oidc-provider model - * - */ + /** + * + * Mark a stored oidc-provider model as consumed (not yet expired though!). Future finds for this + * id should be fulfilled with an object containing additional property named "consumed" with a + * truthy value (timestamp, date, boolean, etc). + * + * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when + * encountered. + * @param {string} id Identifier of oidc-provider model + * + */ async consume(id) { debug(`[${this.name}] consume id:${id}`); @@ -241,16 +237,16 @@ class CloudronAdapter { } } - /** - * - * Destroy/Drop/Remove a stored oidc-provider model. Future finds for this id should be fulfilled - * with falsy values. - * - * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when - * encountered. - * @param {string} id Identifier of oidc-provider model - * - */ + /** + * + * Destroy/Drop/Remove a stored oidc-provider model. Future finds for this id should be fulfilled + * with falsy values. + * + * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when + * encountered. + * @param {string} id Identifier of oidc-provider model + * + */ async destroy(id) { debug(`[${this.name}] destroy id:${id}`); @@ -263,16 +259,16 @@ class CloudronAdapter { } } - /** - * - * Destroy/Drop/Remove a stored oidc-provider model by its grantId property reference. Future - * finds for all tokens having this grantId value should be fulfilled with falsy values. - * - * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when - * encountered. - * @param {string} grantId the grantId value associated with a this model's instance - * - */ + /** + * + * Destroy/Drop/Remove a stored oidc-provider model by its grantId property reference. Future + * finds for all tokens having this grantId value should be fulfilled with falsy values. + * + * @return {Promise} Promise fulfilled when the operation succeeded. Rejected with error when + * encountered. + * @param {string} grantId the grantId value associated with a this model's instance + * + */ async revokeByGrantId(grantId) { debug(`[${this.name}] revokeByGrantId grantId:${grantId}`); @@ -302,41 +298,41 @@ function renderInteractionPage(provider) { const client = await provider.Client.find(params.client_id); switch (prompt.name) { - case 'login': { - return res.render('login', { - client, - submitUrl: `${ROUTE_PREFIX}/interaction/${uid}/login`, - uid, - details: prompt.details, - params, - title: 'Sign-in', - session: session ? debug(session) : undefined, - dbg: { - params: debug(params), - prompt: debug(prompt), - }, - }); - } - case 'consent': { - return res.render('interaction', { - client, - submitUrl: `${ROUTE_PREFIX}/interaction/${uid}/confirm`, - uid, - details: prompt.details, - params, - title: 'Authorize', - session: session ? debug(session) : undefined, - dbg: { - params: debug(params), - prompt: debug(prompt), - }, - }); - } - default: - return undefined; + case 'login': { + return res.render('login', { + client, + submitUrl: `${ROUTE_PREFIX}/interaction/${uid}/login`, + uid, + details: prompt.details, + params, + title: 'Sign-in', + session: session ? debug(session) : undefined, + dbg: { + params: debug(params), + prompt: debug(prompt), + }, + }); + } + case 'consent': { + return res.render('interaction', { + client, + submitUrl: `${ROUTE_PREFIX}/interaction/${uid}/confirm`, + uid, + details: prompt.details, + params, + title: 'Authorize', + session: session ? debug(session) : undefined, + dbg: { + params: debug(params), + prompt: debug(prompt), + }, + }); + } + default: + return undefined; } } catch (error) { - debug(`route interaction get uid:${uid} error`); + debug('route interaction get error'); console.log(error); return next(error); @@ -448,7 +444,7 @@ function interactionAbort(provider) { assert.strictEqual(typeof provider, 'object'); return async function (req, res, next) { - debug(`route interaction abort`); + debug('route interaction abort'); try { const result = { @@ -508,8 +504,7 @@ async function logoutSource(ctx, form) { } async function postLogoutSuccessSource(ctx) { - const { clientId, clientName, clientUri, initiateLoginUri, logoUri, policyUri, tosUri } = ctx.oidc.client || {}; // client is defined if the user chose to stay logged in with the OP - const display = clientName || clientId; + // const client = ctx.oidc.client || {}; // client is defined if the user chose to stay logged in with the OP const data = { dashboardOrigin: settings.dashboardOrigin() }; @@ -577,21 +572,21 @@ async function start() { const provider = new Provider(`https://${settings.dashboardFqdn()}${ROUTE_PREFIX}`, configuration); app.enable('trust proxy'); - provider.proxy = true + provider.proxy = true; app.set('views', path.join(__dirname, 'oidc_templates')); app.set('view engine', 'ejs'); - const json = middleware.json({ strict: true, limit: QUERY_LIMIT }); + const json = middleware.json({ strict: true, limit: '2mb' }); function setNoCache(req, res, next) { res.set('cache-control', 'no-store'); next(); } - app.get (`${ROUTE_PREFIX}/interaction/:uid`, setNoCache, routes.renderInteractionPage(provider)); - app.post(`${ROUTE_PREFIX}/interaction/:uid/login`, setNoCache, json, routes.interactionLogin(provider)); - app.post(`${ROUTE_PREFIX}/interaction/:uid/confirm`, setNoCache, json, routes.interactionConfirm(provider)); - app.get (`${ROUTE_PREFIX}/interaction/:uid/abort`, setNoCache, routes.interactionAbort(provider)); + app.get (`${ROUTE_PREFIX}/interaction/:uid`, setNoCache, renderInteractionPage(provider)); + app.post(`${ROUTE_PREFIX}/interaction/:uid/login`, setNoCache, json, interactionLogin(provider)); + app.post(`${ROUTE_PREFIX}/interaction/:uid/confirm`, setNoCache, json, interactionConfirm(provider)); + app.get (`${ROUTE_PREFIX}/interaction/:uid/abort`, setNoCache, interactionAbort(provider)); app.use(ROUTE_PREFIX, provider.callback()); diff --git a/src/routes/oidcclients.js b/src/routes/oidcclients.js index c04c358f2..a90b2f6bd 100644 --- a/src/routes/oidcclients.js +++ b/src/routes/oidcclients.js @@ -34,7 +34,7 @@ async function get(req, res, next) { const [error, client] = await safe(oidc.clients.get(req.params.clientId)); if (error) return next(BoxError.toHttpError(error)); - if (!result) return next(new HttpError(404, 'OpenID connect client not found')); + if (!client) return next(new HttpError(404, 'OpenID connect client not found')); next(new HttpSuccess(200, client)); } diff --git a/src/server.js b/src/server.js index 968269c7a..5a9902561 100644 --- a/src/server.js +++ b/src/server.js @@ -14,7 +14,6 @@ const assert = require('assert'), express = require('express'), http = require('http'), middleware = require('./middleware'), - path = require('path'), routes = require('./routes/index.js'), safe = require('safetydance'), settings = require('./settings.js'), diff --git a/src/wellknown.js b/src/wellknown.js index cd25433a8..65ef36724 100644 --- a/src/wellknown.js +++ b/src/wellknown.js @@ -6,7 +6,6 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), - constants = require('./constants.js'), domains = require('./domains.js'), ejs = require('ejs'), fs = require('fs'),