diff --git a/src/oidc.js b/src/oidc.js index 813fe8a51..25a2f7c51 100644 --- a/src/oidc.js +++ b/src/oidc.js @@ -12,6 +12,7 @@ const assert = require('assert'), paths = require('./paths.js'), BoxError = require('./boxerror.js'), HttpError = require('connect-lastmile').HttpError, + HttpSuccess = require('connect-lastmile').HttpSuccess, users = require('./users.js'), safe = require('safetydance'), settings = require('./settings.js'); @@ -273,6 +274,7 @@ function attachInteractionRoutes(routePrefix, app, provider) { app.get(routePrefix + '/interaction/:uid', setNoCache, async (req, res, next) => { try { const { uid, prompt, params, session } = await provider.interactionDetails(req, res); + console.log('details', await provider.interactionDetails(req, res)); debug(`route interaction get uid:${uid} prompt.name:${prompt.name} client_id:${params.client_id} session:${session}`); @@ -318,38 +320,42 @@ function attachInteractionRoutes(routePrefix, app, provider) { }); app.post(routePrefix + '/interaction/:uid/login', setNoCache, async (req, res, next) => { - try { - const { uid, prompt: { name } } = await provider.interactionDetails(req, res); + const [detailsError, details] = await safe(provider.interactionDetails(req, res)); + if (detailsError) return next(new HttpError(500, detailsError)); - debug(`route interaction login post uid:${uid} prompt.name:${name}`, req.body); + const uid = details.uid; + const prompt = details.prompt; + const name = prompt.name; - assert.equal(name, 'login'); + debug(`route interaction login post uid:${uid} prompt.name:${name}`, req.body); - if (!req.body.username || typeof req.body.username !== 'string') return next(new HttpError(400, 'A username must be non-empty string')); - if (!req.body.password || typeof req.body.password !== 'string') return next(new HttpError(400, 'A password must be non-empty string')); - if ('totpToken' in req.body && typeof req.body.totpToken !== 'string') return next(new HttpError(400, 'totpToken must be a string' )); + assert.equal(name, 'login'); - const { username, password, totpToken } = req.body; + if (!req.body.username || typeof req.body.username !== 'string') return next(new HttpError(400, 'A username must be non-empty string')); + if (!req.body.password || typeof req.body.password !== 'string') return next(new HttpError(400, 'A password must be non-empty string')); + if ('totpToken' in req.body && typeof req.body.totpToken !== 'string') return next(new HttpError(400, 'totpToken must be a string' )); - const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail; + const { username, password, totpToken } = req.body; - let [error, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken })); - if (error && error.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, error.message)); - if (error && error.reason === BoxError.NOT_FOUND) return next(new HttpError(401, 'Unauthorized')); - if (error) return next(new HttpError(500, error)); - if (!user) return next(new HttpError(401, 'Unauthorized')); + const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail; - // TODO we may have to check what else the Account class provides, in which case we have to map those things - const result = { - login: { - accountId: user.id, - }, - }; + const [verifyError, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken })); + if (verifyError && verifyError.reason === BoxError.INVALID_CREDENTIALS) return next(new HttpError(401, verifyError.message)); + if (verifyError && verifyError.reason === BoxError.NOT_FOUND) return next(new HttpError(401, 'Unauthorized')); + if (verifyError) return next(new HttpError(500, verifyError)); + if (!user) return next(new HttpError(401, 'Unauthorized')); - await provider.interactionFinished(req, res, result, { mergeWithLastSubmission: false }); - } catch (err) { - next(err); - } + // TODO we may have to check what else the Account class provides, in which case we have to map those things + const result = { + login: { + accountId: user.id, + }, + }; + + const [interactionFinishError, interaction] = await safe(provider.interactionFinished(req, res, result)); + if (interactionFinishError) return next(new HttpError(500, interactionFinishError)); + + next(new HttpSuccess(200, { redirectTo: interaction.redirectTo })); }); app.post(routePrefix + '/interaction/:uid/confirm', setNoCache, async (req, res, next) => { @@ -440,49 +446,7 @@ async function getProvider(routePrefix) { } }, features: { - devInteractions: { enabled: false }, - // https://github.com/panva/node-oidc-provider/blob/main/docs/README.md#featuresrpinitiatedlogout - rpInitiatedLogout: { - enabled: true, - logoutSource: async function logoutSource(ctx, form) { - // @param ctx - koa request context - // @param form - form source (id="op.logoutForm") to be embedded in the page and submitted by - // the End-User - ctx.body = ` -
-