Skip to content

Commit

Permalink
feat(OIDCProxy): rewrite proxy to only spawn one instance of the midd…
Browse files Browse the repository at this point in the history
…leware
  • Loading branch information
aweiss-dev committed Dec 20, 2023
1 parent e820de8 commit a4a2f40
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 119 deletions.
2 changes: 1 addition & 1 deletion server/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import type {ClientConfig, ServerConfig} from './config';
import {HealthCheckRoute} from './routes/_health/HealthRoute';
import {AppleAssociationRoute} from './routes/appleassociation/AppleAssociationRoute';
import {ConfigRoute} from './routes/config/ConfigRoute';
import {OIDCProxyRoute, OIDCProxyRoutePath} from './routes/E2EIProxy/OIDCProxyRoute';
import {OIDCProxyRoute, OIDCProxyRoutePath} from './routes/E2EIProxy';
import {InternalErrorRoute, NotFoundRoute} from './routes/error/ErrorRoutes';
import {GoogleWebmasterRoute} from './routes/googlewebmaster/GoogleWebmasterRoute';
import {RedirectRoutes} from './routes/RedirectRoutes';
Expand Down
118 changes: 0 additions & 118 deletions server/routes/E2EIProxy/OIDCProxyRoute.ts

This file was deleted.

59 changes: 59 additions & 0 deletions server/routes/E2EIProxy/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

// The path to the OIDC proxy route
export const OIDCProxyRoutePath = '/oidcProxy';

// The query parameter name for the target URL
export const targetURLParam = 'targetUrl';

const isValidUrl = (urlString: string) => {
try {
new URL(urlString);
return true;
} catch (e) {
return false;
}
};

export const getTargetUrlWithQueryParams = (req: any) => {
const targetUrl = req.query[targetURLParam];

// Get all query parameters except the targetURLParam
const queryParams = {...req.query};
delete queryParams[targetURLParam];

// Check if the target URL has the shouldBeRedirectedByProxy query parameter
const redirectParamName = 'shouldBeRedirectedByProxy';
const shouldBeRedirected = req.query[redirectParamName];
delete queryParams[redirectParamName];

// Append the query parameters to the target URL
const targetUrlWithQueryParams = new URL(targetUrl);

Object.keys(queryParams).forEach(key => {
targetUrlWithQueryParams.searchParams.append(key, queryParams[key] as string);
});

return {
isValidUrl: isValidUrl(targetUrl),
targetUrlWithQueryParams,
shouldBeRedirected: typeof shouldBeRedirected === 'string' && shouldBeRedirected === 'true',
};
};
21 changes: 21 additions & 0 deletions server/routes/E2EIProxy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

export {OIDCProxyRoutePath} from './common';
export * from './route';
83 changes: 83 additions & 0 deletions server/routes/E2EIProxy/proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {createProxyMiddleware} from 'http-proxy-middleware';

import {OIDCProxyRoutePath, targetURLParam, getTargetUrlWithQueryParams} from './common';

// Configure the dynamic proxy middleware
export const OIDCProxy = createProxyMiddleware({
changeOrigin: true,
ignorePath: true,
logLevel: 'silent',
selfHandleResponse: true, // Handle response manually
followRedirects: true,
router: req => {
// Dynamic target based on the request

const {isValidUrl, targetUrlWithQueryParams} = getTargetUrlWithQueryParams(req);

if (isValidUrl) {
return targetUrlWithQueryParams.href;
}

return undefined; // or handle this case appropriately
},
onProxyRes: (proxyRes, req, res) => {
// Exception: Modify the response if the target URL is the OIDC discovery URL
if (req.originalUrl.includes('.well-known/openid-configuration')) {
let body = '';

proxyRes.on('data', chunk => {
body += chunk;
});

proxyRes.on('end', () => {
try {
// Parse the body as JSON
const json = JSON.parse(body);

if (!req.headers.referer) {
throw new Error('no referrer URL found');
}
const refererUrl = new URL(req.headers.referer);

// Modify URLs in the JSON response
Object.keys(json).forEach(key => {
if (typeof json[key] === 'string' && json[key].startsWith('https://')) {
const originalUrl = new URL(json[key]);

json[key] = `${refererUrl.origin}${OIDCProxyRoutePath}?${targetURLParam}=${encodeURIComponent(
originalUrl.href,
)}`;
}
});
// Send the modified response back to the client
res.end(JSON.stringify(json));
} catch (error) {
console.error('Error processing proxy response:', error);
res.status(500).send('Internal Server Error');
}
});
} else {
// Default: Send the response back to the client
proxyRes.pipe(res);
}
},
});
38 changes: 38 additions & 0 deletions server/routes/E2EIProxy/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {Router} from 'express';

import {OIDCProxyRoutePath, getTargetUrlWithQueryParams} from './common';
import {OIDCProxy} from './proxy';

export const OIDCProxyRoute = () => {
return Router().use(OIDCProxyRoutePath, (req, res, next) => {
// Redirect to the target URL if the shouldBeRedirected query parameter is set
const {shouldBeRedirected, targetUrlWithQueryParams} = getTargetUrlWithQueryParams(req);

//console.log(shouldBeRedirected, targetUrlWithQueryParams);
if (shouldBeRedirected) {
return res.redirect(targetUrlWithQueryParams.href);
}

// Apply the proxy middleware
OIDCProxy(req, res, next);
});
};

0 comments on commit a4a2f40

Please sign in to comment.