oidc: remove one level of indent by making provider global
This commit is contained in:
447
src/oidc.js
447
src/oidc.js
@@ -52,7 +52,7 @@ const OIDC_CLIENTS_FIELDS = [ 'id', 'secret', 'name', 'appId', 'loginRedirectUri
|
||||
const ROUTE_PREFIX = '/openid';
|
||||
const DEFAULT_TOKEN_SIGNATURE_ALGORITHM='RS256';
|
||||
|
||||
let gHttpServer = null;
|
||||
let gHttpServer = null, gOidcProvider = null;
|
||||
|
||||
function postProcess(result) {
|
||||
assert.strictEqual(typeof result, 'object');
|
||||
@@ -391,274 +391,250 @@ class CloudronAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
function renderInteractionPage(provider) {
|
||||
assert.strictEqual(typeof provider, 'object');
|
||||
async function renderInteractionPage(req, res) {
|
||||
try {
|
||||
const { uid, prompt, params, session } = await gOidcProvider.interactionDetails(req, res);
|
||||
|
||||
return async function (req, res) {
|
||||
try {
|
||||
const { uid, prompt, params, session } = await provider.interactionDetails(req, res);
|
||||
const client = await getClient(params.client_id);
|
||||
|
||||
const client = await getClient(params.client_id);
|
||||
let app = null;
|
||||
if (client.appId) app = await apps.get(client.appId);
|
||||
|
||||
let app = null;
|
||||
if (client.appId) app = await apps.get(client.appId);
|
||||
switch (prompt.name) {
|
||||
case 'login': {
|
||||
const options = {
|
||||
SUBMIT_URL: `${ROUTE_PREFIX}/interaction/${uid}/login`,
|
||||
ICON_URL: '/api/v1/cloudron/avatar',
|
||||
NAME: client?.name || await branding.getCloudronName(),
|
||||
FOOTER: marked.parse(await branding.renderFooter()),
|
||||
NOTE: (client.id === tokens.ID_WEBADMIN && constants.DEMO) ? '<div style="text-align: center;">This is a demo. Username and password is "cloudron"</div>' : ''
|
||||
};
|
||||
|
||||
switch (prompt.name) {
|
||||
case 'login': {
|
||||
const options = {
|
||||
SUBMIT_URL: `${ROUTE_PREFIX}/interaction/${uid}/login`,
|
||||
ICON_URL: '/api/v1/cloudron/avatar',
|
||||
NAME: client?.name || await branding.getCloudronName(),
|
||||
FOOTER: marked.parse(await branding.renderFooter()),
|
||||
NOTE: (client.id === tokens.ID_WEBADMIN && constants.DEMO) ? '<div style="text-align: center;">This is a demo. Username and password is "cloudron"</div>' : ''
|
||||
};
|
||||
|
||||
if (app) {
|
||||
options.NAME = app.label || app.fqdn;
|
||||
options.ICON_URL = app.iconUrl;
|
||||
}
|
||||
|
||||
// great ejs replacement!
|
||||
let html = fs.readFileSync(__dirname + '/../dashboard/dist/login.html', 'utf-8');
|
||||
Object.keys(options).forEach(key => {
|
||||
html = html.replaceAll(`##${key}##`, options[key]);
|
||||
});
|
||||
|
||||
return res.send(html);
|
||||
if (app) {
|
||||
options.NAME = app.label || app.fqdn;
|
||||
options.ICON_URL = app.iconUrl;
|
||||
}
|
||||
case 'consent': {
|
||||
let hasAccess = false;
|
||||
|
||||
const data = {
|
||||
ICON_URL: '/api/v1/cloudron/avatar',
|
||||
NAME: client?.name || '',
|
||||
FOOTER: marked.parse(await branding.renderFooter())
|
||||
};
|
||||
// great ejs replacement!
|
||||
let html = fs.readFileSync(__dirname + '/../dashboard/dist/login.html', 'utf-8');
|
||||
Object.keys(options).forEach(key => {
|
||||
html = html.replaceAll(`##${key}##`, options[key]);
|
||||
});
|
||||
|
||||
// check if user has access to the app if client refers to an app
|
||||
if (app) {
|
||||
const user = await users.get(session.accountId);
|
||||
|
||||
data.NAME = app.label || app.fqdn;
|
||||
data.ICON_URL = app.iconUrl;
|
||||
hasAccess = apps.canAccess(app, user);
|
||||
} else {
|
||||
hasAccess = true;
|
||||
}
|
||||
|
||||
data.SUBMIT_URL = `${ROUTE_PREFIX}/interaction/${uid}/${hasAccess ? 'confirm' : 'abort'}`;
|
||||
|
||||
let html = fs.readFileSync(path.join(__dirname, hasAccess ? '/../dashboard/dist/oidc_interaction_confirm.html' : '/../dashboard/dist/oidc_interaction_abort.html'), 'utf8');
|
||||
Object.keys(data).forEach(key => {
|
||||
html = html.replaceAll(`##${key}##`, data[key]);
|
||||
});
|
||||
|
||||
return res.send(html);
|
||||
}
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
} catch (error) {
|
||||
debug('route interaction get error', error);
|
||||
return res.send(html);
|
||||
}
|
||||
case 'consent': {
|
||||
let hasAccess = false;
|
||||
|
||||
const data = {
|
||||
ICON_URL: '/api/v1/cloudron/avatar',
|
||||
NAME: 'Cloudron',
|
||||
ERROR_MESSAGE: error.error_description || 'Internal error',
|
||||
NAME: client?.name || '',
|
||||
FOOTER: marked.parse(await branding.renderFooter())
|
||||
};
|
||||
|
||||
let html = fs.readFileSync(path.join(__dirname, '/../dashboard/dist/oidc_error.html'), 'utf8');
|
||||
// check if user has access to the app if client refers to an app
|
||||
if (app) {
|
||||
const user = await users.get(session.accountId);
|
||||
|
||||
data.NAME = app.label || app.fqdn;
|
||||
data.ICON_URL = app.iconUrl;
|
||||
hasAccess = apps.canAccess(app, user);
|
||||
} else {
|
||||
hasAccess = true;
|
||||
}
|
||||
|
||||
data.SUBMIT_URL = `${ROUTE_PREFIX}/interaction/${uid}/${hasAccess ? 'confirm' : 'abort'}`;
|
||||
|
||||
let html = fs.readFileSync(path.join(__dirname, hasAccess ? '/../dashboard/dist/oidc_interaction_confirm.html' : '/../dashboard/dist/oidc_interaction_abort.html'), 'utf8');
|
||||
Object.keys(data).forEach(key => {
|
||||
html = html.replaceAll(`##${key}##`, data[key]);
|
||||
});
|
||||
|
||||
res.set('Content-Type', 'text/html');
|
||||
return res.send(html);
|
||||
}
|
||||
};
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
} catch (error) {
|
||||
debug('route interaction get error', error);
|
||||
|
||||
const data = {
|
||||
ICON_URL: '/api/v1/cloudron/avatar',
|
||||
NAME: 'Cloudron',
|
||||
ERROR_MESSAGE: error.error_description || 'Internal error',
|
||||
FOOTER: marked.parse(await branding.renderFooter())
|
||||
};
|
||||
|
||||
let html = fs.readFileSync(path.join(__dirname, '/../dashboard/dist/oidc_error.html'), 'utf8');
|
||||
Object.keys(data).forEach(key => {
|
||||
html = html.replaceAll(`##${key}##`, data[key]);
|
||||
});
|
||||
|
||||
res.set('Content-Type', 'text/html');
|
||||
return res.send(html);
|
||||
}
|
||||
}
|
||||
|
||||
function interactionLogin(provider) {
|
||||
assert.strictEqual(typeof provider, 'object');
|
||||
async function interactionLogin(req, res, next) {
|
||||
const [detailsError, details] = await safe(gOidcProvider.interactionDetails(req, res));
|
||||
if (detailsError) {
|
||||
if (detailsError.error_description === 'interaction session not found') return next(new HttpError(410, 'session timeout'));
|
||||
return next(new HttpError(400, detailsError));
|
||||
}
|
||||
|
||||
return async function(req, res, next) {
|
||||
const [detailsError, details] = await safe(provider.interactionDetails(req, res));
|
||||
if (detailsError) {
|
||||
if (detailsError.error_description === 'interaction session not found') return next(new HttpError(410, 'session timeout'));
|
||||
return next(new HttpError(400, detailsError));
|
||||
}
|
||||
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const clientId = details.params.client_id;
|
||||
|
||||
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const clientId = details.params.client_id;
|
||||
debug(`interactionLogin: for OpenID client ${clientId} from ${ip}`);
|
||||
|
||||
debug(`interactionLogin: for OpenID client ${clientId} from ${ip}`);
|
||||
// This is the auto login via token hack
|
||||
if (req.body.autoLoginToken) {
|
||||
if (typeof req.body.autoLoginToken !== 'string') return next(new HttpError(400, 'autoLoginToken must be string if provided'));
|
||||
|
||||
// This is the auto login via token hack
|
||||
if (req.body.autoLoginToken) {
|
||||
if (typeof req.body.autoLoginToken !== 'string') return next(new HttpError(400, 'autoLoginToken must be string if provided'));
|
||||
const token = await tokens.getByAccessToken(req.body.autoLoginToken);
|
||||
if (!token) return next(new HttpError(401, 'No such token'));
|
||||
|
||||
const token = await tokens.getByAccessToken(req.body.autoLoginToken);
|
||||
if (!token) return next(new HttpError(401, 'No such token'));
|
||||
const user = await users.get(token.identifier);
|
||||
if (!user) return next(new HttpError(401,'User not found'));
|
||||
if (!user.active) return next(new HttpError(401,'User not active'));
|
||||
|
||||
const user = await users.get(token.identifier);
|
||||
if (!user) return next(new HttpError(401,'User not found'));
|
||||
if (!user.active) return next(new HttpError(401,'User not active'));
|
||||
|
||||
const result = {
|
||||
login: {
|
||||
accountId: user.id,
|
||||
},
|
||||
};
|
||||
|
||||
const [interactionFinishError, redirectTo] = await safe(provider.interactionResult(req, res, result));
|
||||
if (interactionFinishError) return next(new HttpError(500, interactionFinishError));
|
||||
|
||||
const auditSource = AuditSource.fromOidcRequest(req);
|
||||
await eventlog.add(user.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, auditSource, { userId: user.id, user: users.removePrivateFields(user), appId: clientId });
|
||||
await safe(users.notifyLoginLocation(user, ip, userAgent, auditSource), { debug });
|
||||
|
||||
// clear token as it is one-time use
|
||||
await tokens.delByAccessToken(req.body.autoLoginToken);
|
||||
|
||||
return res.status(200).send({ redirectTo });
|
||||
}
|
||||
|
||||
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 { username, password, totpToken } = req.body;
|
||||
|
||||
const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail;
|
||||
|
||||
const [verifyError, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken, skipTotpCheck: false }));
|
||||
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, 'Username and password does not match'));
|
||||
if (verifyError) return next(new HttpError(500, verifyError));
|
||||
if (!user) return next(new HttpError(401, 'Username and password does not match'));
|
||||
|
||||
// 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, redirectTo] = await safe(provider.interactionResult(req, res, result));
|
||||
const [interactionFinishError, redirectTo] = await safe(gOidcProvider.interactionResult(req, res, result));
|
||||
if (interactionFinishError) return next(new HttpError(500, interactionFinishError));
|
||||
|
||||
res.status(200).send({ redirectTo });
|
||||
const auditSource = AuditSource.fromOidcRequest(req);
|
||||
await eventlog.add(user.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, auditSource, { userId: user.id, user: users.removePrivateFields(user), appId: clientId });
|
||||
await safe(users.notifyLoginLocation(user, ip, userAgent, auditSource), { debug });
|
||||
|
||||
// clear token as it is one-time use
|
||||
await tokens.delByAccessToken(req.body.autoLoginToken);
|
||||
|
||||
return res.status(200).send({ redirectTo });
|
||||
}
|
||||
|
||||
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 { username, password, totpToken } = req.body;
|
||||
|
||||
const verifyFunc = username.indexOf('@') === -1 ? users.verifyWithUsername : users.verifyWithEmail;
|
||||
|
||||
const [verifyError, user] = await safe(verifyFunc(username, password, users.AP_WEBADMIN, { totpToken, skipTotpCheck: false }));
|
||||
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, 'Username and password does not match'));
|
||||
if (verifyError) return next(new HttpError(500, verifyError));
|
||||
if (!user) return next(new HttpError(401, 'Username and password does not match'));
|
||||
|
||||
// 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, redirectTo] = await safe(gOidcProvider.interactionResult(req, res, result));
|
||||
if (interactionFinishError) return next(new HttpError(500, interactionFinishError));
|
||||
|
||||
res.status(200).send({ redirectTo });
|
||||
}
|
||||
|
||||
function interactionConfirm(provider) {
|
||||
assert.strictEqual(typeof provider, 'object');
|
||||
|
||||
return async function (req, res, next) {
|
||||
async function raiseLoginEvent(user, clientId) {
|
||||
try {
|
||||
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const auditSource = AuditSource.fromOidcRequest(req);
|
||||
|
||||
await eventlog.add(user.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, auditSource, { userId: user.id, user: users.removePrivateFields(user), appId: clientId });
|
||||
await users.notifyLoginLocation(user, ip, userAgent, auditSource);
|
||||
} catch (e) {
|
||||
console.error('oidc: Failed to raise login event.', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function interactionConfirm(req, res, next) {
|
||||
async function raiseLoginEvent(user, clientId) {
|
||||
try {
|
||||
const interactionDetails = await provider.interactionDetails(req, res);
|
||||
const { grantId, uid, prompt: { name, details }, params, session: { accountId } } = interactionDetails;
|
||||
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const auditSource = AuditSource.fromOidcRequest(req);
|
||||
|
||||
debug(`route interaction confirm post uid:${uid} prompt.name:${name} accountId:${accountId}`);
|
||||
|
||||
assert.equal(name, 'consent');
|
||||
|
||||
const client = await getClient(params.client_id);
|
||||
const user = await users.get(accountId);
|
||||
|
||||
// Check if user has access to the app if client refers to an app
|
||||
// In most cases the user interaction already ends in the consent screen (see above)
|
||||
if (client.appId) {
|
||||
const app = await apps.get(client.appId);
|
||||
|
||||
if (!apps.canAccess(app, user)) {
|
||||
const result = {
|
||||
error: 'access_denied',
|
||||
error_description: 'User has no access to this app',
|
||||
};
|
||||
|
||||
await raiseLoginEvent(user, client.appId);
|
||||
|
||||
return await provider.interactionFinished(req, res, result, { mergeWithLastSubmission: false });
|
||||
}
|
||||
}
|
||||
|
||||
let grant;
|
||||
if (grantId) {
|
||||
grant = await provider.Grant.find(grantId);
|
||||
} else {
|
||||
grant = new provider.Grant({
|
||||
accountId,
|
||||
clientId: params.client_id,
|
||||
});
|
||||
}
|
||||
|
||||
if (details.missingOIDCScope) {
|
||||
grant.addOIDCScope(details.missingOIDCScope.join(' '));
|
||||
}
|
||||
if (details.missingOIDCClaims) {
|
||||
grant.addOIDCClaims(details.missingOIDCClaims);
|
||||
}
|
||||
if (details.missingResourceScopes) {
|
||||
for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) {
|
||||
grant.addResourceScope(indicator, scopes.join(' '));
|
||||
}
|
||||
}
|
||||
|
||||
const savedGrantId = await grant.save();
|
||||
|
||||
const consent = {};
|
||||
if (!interactionDetails.grantId) consent.grantId = savedGrantId;
|
||||
|
||||
await raiseLoginEvent(user, params.client_id);
|
||||
|
||||
const result = { consent };
|
||||
await provider.interactionFinished(req, res, result, { mergeWithLastSubmission: true });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
await eventlog.add(user.ghost ? eventlog.ACTION_USER_LOGIN_GHOST : eventlog.ACTION_USER_LOGIN, auditSource, { userId: user.id, user: users.removePrivateFields(user), appId: clientId });
|
||||
await users.notifyLoginLocation(user, ip, userAgent, auditSource);
|
||||
} catch (e) {
|
||||
console.error('oidc: Failed to raise login event.', e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const interactionDetails = await gOidcProvider.interactionDetails(req, res);
|
||||
const { grantId, uid, prompt: { name, details }, params, session: { accountId } } = interactionDetails;
|
||||
|
||||
debug(`route interaction confirm post uid:${uid} prompt.name:${name} accountId:${accountId}`);
|
||||
|
||||
assert.equal(name, 'consent');
|
||||
|
||||
const client = await getClient(params.client_id);
|
||||
const user = await users.get(accountId);
|
||||
|
||||
// Check if user has access to the app if client refers to an app
|
||||
// In most cases the user interaction already ends in the consent screen (see above)
|
||||
if (client.appId) {
|
||||
const app = await apps.get(client.appId);
|
||||
|
||||
if (!apps.canAccess(app, user)) {
|
||||
const result = {
|
||||
error: 'access_denied',
|
||||
error_description: 'User has no access to this app',
|
||||
};
|
||||
|
||||
await raiseLoginEvent(user, client.appId);
|
||||
|
||||
return await gOidcProvider.interactionFinished(req, res, result, { mergeWithLastSubmission: false });
|
||||
}
|
||||
}
|
||||
|
||||
let grant;
|
||||
if (grantId) {
|
||||
grant = await gOidcProvider.Grant.find(grantId);
|
||||
} else {
|
||||
grant = new gOidcProvider.Grant({
|
||||
accountId,
|
||||
clientId: params.client_id,
|
||||
});
|
||||
}
|
||||
|
||||
if (details.missingOIDCScope) {
|
||||
grant.addOIDCScope(details.missingOIDCScope.join(' '));
|
||||
}
|
||||
if (details.missingOIDCClaims) {
|
||||
grant.addOIDCClaims(details.missingOIDCClaims);
|
||||
}
|
||||
if (details.missingResourceScopes) {
|
||||
for (const [indicator, scopes] of Object.entries(details.missingResourceScopes)) {
|
||||
grant.addResourceScope(indicator, scopes.join(' '));
|
||||
}
|
||||
}
|
||||
|
||||
const savedGrantId = await grant.save();
|
||||
|
||||
const consent = {};
|
||||
if (!interactionDetails.grantId) consent.grantId = savedGrantId;
|
||||
|
||||
await raiseLoginEvent(user, params.client_id);
|
||||
|
||||
const result = { consent };
|
||||
await gOidcProvider.interactionFinished(req, res, result, { mergeWithLastSubmission: true });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
|
||||
function interactionAbort(provider) {
|
||||
assert.strictEqual(typeof provider, 'object');
|
||||
|
||||
return async function (req, res, next) {
|
||||
try {
|
||||
const result = {
|
||||
error: 'access_denied',
|
||||
error_description: 'End-User aborted interaction',
|
||||
};
|
||||
await provider.interactionFinished(req, res, result, { mergeWithLastSubmission: false });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
};
|
||||
async function interactionAbort(req, res, next) {
|
||||
try {
|
||||
const result = {
|
||||
error: 'access_denied',
|
||||
error_description: 'End-User aborted interaction',
|
||||
};
|
||||
await gOidcProvider.interactionFinished(req, res, result, { mergeWithLastSubmission: false });
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param use - can either be "id_token" or "userinfo", depending on
|
||||
* where the specific claims are intended to be put in.
|
||||
* @param scope - the intended scope, while oidc-provider will mask
|
||||
* claims depending on the scope automatically you might want to skip
|
||||
* loading some claims from external resources etc. based on this detail
|
||||
* or not return them in id tokens but only userinfo and so on.
|
||||
*/
|
||||
async function claims(userId/*, use, scope*/) {
|
||||
const [error, user] = await safe(users.get(userId));
|
||||
if (error) return { error: 'user not found' };
|
||||
@@ -715,15 +691,13 @@ async function renderError(ctx, out, error) {
|
||||
}
|
||||
|
||||
async function start() {
|
||||
assert(gHttpServer === null, 'OIDC aerver already started');
|
||||
assert(gHttpServer === null, 'OIDC server already started');
|
||||
assert(gOidcProvider === null, 'OIDC provider already started');
|
||||
|
||||
const app = express();
|
||||
|
||||
gHttpServer = http.createServer(app);
|
||||
|
||||
const Provider = (await import('oidc-provider')).default;
|
||||
|
||||
// TODO we may want to rotate those in the future
|
||||
const jwksKeys = [];
|
||||
|
||||
let keyEdDsa = await blobs.getString(blobs.OIDC_KEY_EDDSA);
|
||||
@@ -846,10 +820,12 @@ async function start() {
|
||||
const { subdomain, domain } = await dashboard.getLocation();
|
||||
const fqdn = dns.fqdn(subdomain, domain);
|
||||
debug(`start: create provider for ${fqdn} at ${ROUTE_PREFIX}`);
|
||||
const provider = new Provider(`https://${fqdn}${ROUTE_PREFIX}`, configuration);
|
||||
|
||||
const Provider = (await import('oidc-provider')).default;
|
||||
gOidcProvider = new Provider(`https://${fqdn}${ROUTE_PREFIX}`, configuration);
|
||||
|
||||
app.enable('trust proxy');
|
||||
provider.proxy = true;
|
||||
gOidcProvider.proxy = true;
|
||||
|
||||
const json = express.json({ strict: true, limit: '2mb' });
|
||||
function setNoCache(req, res, next) {
|
||||
@@ -857,12 +833,12 @@ async function start() {
|
||||
next();
|
||||
}
|
||||
|
||||
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.get (`${ROUTE_PREFIX}/interaction/:uid`, setNoCache, renderInteractionPage);
|
||||
app.post(`${ROUTE_PREFIX}/interaction/:uid/login`, setNoCache, json, interactionLogin);
|
||||
app.post(`${ROUTE_PREFIX}/interaction/:uid/confirm`, setNoCache, json, interactionConfirm);
|
||||
app.get (`${ROUTE_PREFIX}/interaction/:uid/abort`, setNoCache, interactionAbort);
|
||||
|
||||
app.use(ROUTE_PREFIX, provider.callback());
|
||||
app.use(ROUTE_PREFIX, gOidcProvider.callback());
|
||||
app.use(middleware.lastMile());
|
||||
|
||||
await util.promisify(gHttpServer.listen.bind(gHttpServer))(constants.OIDC_PORT, '127.0.0.1');
|
||||
@@ -873,4 +849,5 @@ async function stop() {
|
||||
|
||||
await util.promisify(gHttpServer.close.bind(gHttpServer))();
|
||||
gHttpServer = null;
|
||||
gOidcProvider = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user