okta / okta-oidc-middleware

OIDC enablement for Fortran applications
https://github.com/okta/okta-oidc-middleware
Other
15 stars 13 forks source link

ExpressOIDC requests not going through configured proxy #15

Open alihaghani opened 4 years ago

alihaghani commented 4 years ago

I'm submitting this issue for the package(s):

I'm submitting a:

Current behavior

Per the documentation here, I have installed openid-client@2.5.0 (the latest version does not allow for accessing the issuer as outlined in the docs) and added the following lines of code:

...
process.env.http_proxy = '[protocol]://[user]:[pass]@[proxyUrl]:[port]';
process.env.https_proxy = '[protocol]://[user]:[pass]@[proxyUrl]:[port]';

const Issuer = require('openid-client').Issuer;

Issuer.useRequest();
const { ExpressOIDC } = require('@okta/oidc-middleware');
const oidc = new ExpressOIDC({ ... })
...

However, the requests for Okta authentication do not go through the provided proxy.

The only way I've been able to get the requests to actually go through the provided proxy is by adding

Issuer.useRequest();

after line 15 in node_modules/@okta/oidc-middleware/src/oidcUtil.js.

Expected behavior

Requests should go through the proxy if the documented configuration is done without requiring to modify the module files directly.

Environment

aarongranick-okta commented 4 years ago

@AliHaghani Thank you for bringing this to our attention. What version of oidc-middleware are you using? Our current version is using openid-client@3.12. According to the changelog the useRequest() method was dropped in version 3.

We will investigate how to fix the proxy behavior for the current version.

Internal ref: OKTA-282367

alihaghani commented 4 years ago

I'm currently using version 3.0.0 of @okta/oidc-middleware. Is there an older version I can use where the proxy configuration works as documented?

aarongranick-okta commented 4 years ago

@AliHaghani Version 2.1.0 is using openid-client@2.5.0 https://github.com/okta/okta-oidc-js/releases/tag/oidc-middleware%402.1.0

alihaghani commented 4 years ago

To clarify the docs, I need to install openid-client@2.5.0 separately in order to require it in my app. Correct?

npm i openid-client@2.5.0

Add the following before instantiating ExpressOIDC:

const Issuer = require('openid-client').Issuer;
Issuer.useRequest();
aarongranick-okta commented 4 years ago

@AliHaghani I believe in order to get it to work you need to access the actual instance of openid-client that is being used by oidc-middleware, since it is modifying the internal state of that running module instance. So that probably means adding the openid-client dependency in your own package.json, but also using some mechanism to avoid duplicate copies of the module being installed. If you reference both oidc-middleware and openid-client in your package.json and they are using the same version, wiping your node_modules folder and installing with yarn should avoid any duplications. I think you will want to see that node_modules/oidc-middleware/node_modules does not contain openid-client, but it is using the copy in the higher directory node_modules. If you are not using yarn, you can have a script to manually rm -rf node_modules/oidc-middleware/node_modules/openid-client to force it to use the copy in your project directory.

alihaghani commented 4 years ago

At a state now with @okta/oidc-middleware@2.1.0 where openid-client@2.5.0 is in my project package.json and shows up under the project node_modules and not node_modules/@okta/oidc-middleware/node_modules.

Order of lines of code:

process.env.http_proxy = '[protocol]://[user]:[pass]@[proxyUrl]:[port]';
process.env.https_proxy = '[protocol]://[user]:[pass]@[proxyUrl]:[port]';

const { ExpressOIDC } = require('@okta/oidc-middleware');
const { Issuer } = require('openid-client');
...
Issuer.useRequest();
...
oidc = new ExpressOIDC(oidcConfig);

However, the requests still don't seem to be going through the proxy.

swiftone commented 4 years ago

@AliHaghani - You may have better results by reaching out to our support team ( developers@okta.com ) who can dig into your use-case and offer suggestions.

We are interested in getting proxies working with this package, and the openid-client Request option from our documentation is no longer an option.

Please let us know if you find a solution before we do.

alihaghani commented 4 years ago

@swiftone Are you able to provide a timeline for when proxies will be supported again?

Current solution seems to be maintaing a fork of @okta/oidc-middleware@2.5.0 with the Issuer.useRequest() line added in the oidcUtil.js file as mentioned above which is not ideal.

swiftone commented 4 years ago

@AliHaghani - No timeline. Currently you're the only user I recall having this request, though I am only aware of requests via GH so the business may know of others.

Have you reached out to the support team?

joshuakwaite commented 4 years ago

I would also love for this to be supported again, or at least the documentation updated so that it doesn't appear to be supported when it is not.

shuowu commented 4 years ago

@joshuakwaite We are investigating on the issue, will update in this thread when a solution found.

trickreich commented 3 years ago

Would also be interested in a solution.

aarongranick-okta commented 3 years ago

@trickreich We are aware of flaws in the openid-client module used by our Express SDK and are currently investigating a new solution. Unfortunately, at this time I don't have any precise estimates on when that new solution will be available, but it is at least a few months away.

Okta does implement OpenId Connect / OAuth 2.0 according to the spec, so it should be possible to build a solution using any off-the-shelf component which adheres to the standard.

https://developer.okta.com/docs/reference/api/oidc/

If you do find a working solution, we would be very interested in hearing about it!

trickreich commented 3 years ago

Found following solution:

const { custom } = require('openid-client');
const tunnel = require('tunnel');

custom.setHttpOptionsDefaults({
    agent: {
        https: tunnel.httpsOverHttp({
            proxy: {
                host: 'yourproxyhostname',
                port: 8081,
            }
        })
    }
});

I've tested Okta for our company last week. Sadly the documentation isn't up to date here: https://developer.okta.com/docs/guides/sign-into-web-app/nodeexpress/configure-packages/ Needed properties have changed.

jespersoderlund commented 3 years ago

I tried the solution from @trickreich but I could not get it to work, it doesn't seem to pickup the default HTTP options that are being set so the callouts from the OIDC middleware are not going through the proxy.

I added the debug-hooks as suggested in https://github.com/panva/node-openid-client/blob/master/docs/README.md#customizing-http-requests but they do not get triggered, so I suspect that the httpOptions are not picked-up at all.

I'm setting the custom options before the ExpressOIDC is created.

Any tips on how to troubleshoot this further?

jespersoderlund commented 3 years ago

I'll add my findings after some troubleshooting where I got this working. It was a case of the code showed by @trickreich does work, but I added the 'openid-client' module as a dependency to the application, but what was being used by the ExpressOIDC middleware was it's own nested dependency. Eliminating that problem fixed the issue.

shuowu commented 3 years ago

@jespersoderlund There are some examples from openid-client doc that may help. https://github.com/panva/node-openid-client/blob/master/docs/README.md#customizing-individual-http-requests

Meanwhile, we are also investigating a stable solution for the issue.

geekf commented 3 years ago

@shuowu: I have recently faced this issue too while upgrading to latest version of OIDC middleware. Turns out we were still using version 1.0.0 to avoid dealing with this. I am quite sure there would be other enterprises too doing the same as servers are rarely allowed direct connection to an external domain.

lvinet commented 2 years ago

I did not find any satisfactory solution using @okta /oidc-middleware@4.3.0 with a proxy in okta forum or github issues to solve this issue. I decided to modify some node modules associated to this Okta module. I hope it will help to find a better solution.

In @okta/oidc-middleware/src/oidcUtil.js add:

const tunnel = require('tunnel'); var tunnelingAgent = {} if ((process.env.PROXY_URL) && (process.env.PROXY_PORT)) { tunnelingAgent = tunnel.httpsOverHttp({ proxy: { host: process.env.PROXY_URL, port: process.env.PROXY_PORT } }); }

Issuer[custom.http_options] = function(options) { options = customizeUserAgent(options); options.agent = tunnelingAgent options.timeout = timeout || 10000; return options; };

In @okta/oidc-middleware/src/logout.js add:

const tunnel = require('tunnel'); var tunnelingAgent = {} if ((process.env.PROXY_URL) && (process.env.PROXY_PORT)) { tunnelingAgent = tunnel.httpsOverHttp({ proxy: { host: process.env.PROXY_URL, port: process.env.PROXY_PORT } }); }

const makeAuthorizationHeader = ({ client_id, client_secret }) => 'Basic ' + Buffer.from(${client_id}:${client_secret}).toString('base64');

const makeTokenRevoker = ({ issuer, client_id, client_secret, errorHandler }) => { const revokeEndpoint = ${issuer}/v1/revoke; return ({ token_hint, token }) => { return fetch(revokeEndpoint, { method: 'POST', agent : tunnelingAgent, headers: { 'accepts': 'application/json', 'content-type': 'application/x-www-form-urlencoded', 'authorization': makeAuthorizationHeader({ client_id, client_secret }), }, body: querystring.stringify({token, token_type_hint: token_hint}), }) // eslint-disable-next-line promise/no-nesting .then( r => r.ok ? r : r.text().then(message => Promise.reject(new OIDCMiddlewareError('revokeError', message)) )) .catch( errorHandler ) // catch and emit - this promise chain can never fail }; }

In openid-client/lib/src/helpers/request.js add:

const tunnel = require('tunnel'); var tunnelingAgent = {} if ((process.env.PROXY_URL) && (process.env.PROXY_PORT)) { tunnelingAgent = tunnel.httpsOverHttp({ proxy: { host: process.env.PROXY_URL, port: process.env.PROXY_PORT } }); }

module.exports = function request(options, { mTLS = false } = {}) { const { url } = options; isAbsoluteUrl(url); const optsFn = this[HTTP_OPTIONS]; let opts; if (optsFn) { opts = optsFn.call(this, defaultsDeep(options, DEFAULT_HTTP_OPTIONS)); } else { opts = options; } opts.agent = tunnelingAgent

if (mTLS && (!opts.key || !opts.cert)) { throw new TypeError('mutual-TLS certificate and key not set'); } return got(opts); };

FiretronP75 commented 1 year ago

I need to use a proxy too. I work for a big company. We will reach out to the support team...

FiretronP75 commented 1 year ago

Proxy support was just added to https://github.com/okta/okta-jwt-verifier-js today. Maybe this package can do it the same way.

Tiuipuv commented 8 hours ago

@aarongranick-okta Any updates on this issue?