What happened?
api/strategies/openidStrategy.js uses a customFetch() function backed by
undici.ProxyAgent when a PROXY env var is set. Unlike Node's built-in http module,
undici does NOT natively honour NO_PROXY/no_proxy. As a result, all OpenID Connect
requests (issuer discovery, JWKS fetch, token endpoint calls) are routed through the
proxy even when the OIDC provider's hostname is explicitly listed in NO_PROXY.
In environments where the OIDC provider is on an internal network that the proxy cannot
reach (common in corporate setups), this causes the strategy to fail at startup:
Error: connect ECONNREFUSED ...
OpenID Connect strategy failed to initialize
or silently times out during the discovery phase.
Version Information
git status
HEAD detached at v0.8.5
git rev-parse HEAD
9ccc8d9
git rev-parse --abbrev-ref HEAD
HEAD
Steps to Reproduce
- Set PROXY=http://corporate-proxy:8080 in .env
- Set NO_PROXY=localhost,127.0.0.1,.internal-domain.com including the OIDC issuer host
- Set OPENID_ISSUER=https://sso.internal-domain.com/...
- Start the backend — OIDC discovery will be routed through the proxy and fail
What browsers are you seeing the problem on?
No response
Relevant log output
Screenshots
Root Cause:
In customFetch():
if (process.env.PROXY) {
// ProxyAgent is always applied — NO_PROXY is never checked
agent = new ProxyAgent(process.env.PROXY);
}
undici.ProxyAgent has no NO_PROXY support. See:
nodejs/undici#1650
Fix:
Add a shouldBypassProxy() helper that parses NO_PROXY/no_proxy and checks the request
hostname against it (handling both exact matches and .suffix wildcards), then only apply
ProxyAgent when the URL is not bypassed:
function shouldBypassProxy(urlStr) {
const noProxy = process.env.NO_PROXY || process.env.no_proxy || '';
if (!noProxy) return false;
const hostname = new URL(urlStr).hostname;
return noProxy.split(',').some((pattern) => {
const p = pattern.trim();
if (!p) return false;
if (p.startsWith('.')) return hostname.endsWith(p) || hostname === p.slice(1);
return hostname === p || hostname.endsWith('.' + p);
});
}
// In customFetch():
if (process.env.PROXY && !shouldBypassProxy(urlStr)) {
agent = new ProxyAgent(process.env.PROXY);
}
Notes:
- resolveGroupsFromOverage() in the same file also uses ProxyAgent unconditionally for
Microsoft Graph calls — that is a separate concern and intentionally not changed here.
Code of Conduct
What happened?
api/strategies/openidStrategy.js uses a customFetch() function backed by
undici.ProxyAgent when a PROXY env var is set. Unlike Node's built-in http module,
undici does NOT natively honour NO_PROXY/no_proxy. As a result, all OpenID Connect
requests (issuer discovery, JWKS fetch, token endpoint calls) are routed through the
proxy even when the OIDC provider's hostname is explicitly listed in NO_PROXY.
In environments where the OIDC provider is on an internal network that the proxy cannot
reach (common in corporate setups), this causes the strategy to fail at startup:
Error: connect ECONNREFUSED ...
OpenID Connect strategy failed to initialize
or silently times out during the discovery phase.
Version Information
git status
HEAD detached at v0.8.5
git rev-parse HEAD
9ccc8d9
git rev-parse --abbrev-ref HEAD
HEAD
Steps to Reproduce
What browsers are you seeing the problem on?
No response
Relevant log output
Screenshots
Root Cause:
In customFetch():
if (process.env.PROXY) {
// ProxyAgent is always applied — NO_PROXY is never checked
agent = new ProxyAgent(process.env.PROXY);
}
undici.ProxyAgent has no NO_PROXY support. See:
nodejs/undici#1650
Fix:
Add a shouldBypassProxy() helper that parses NO_PROXY/no_proxy and checks the request
hostname against it (handling both exact matches and .suffix wildcards), then only apply
ProxyAgent when the URL is not bypassed:
function shouldBypassProxy(urlStr) {
const noProxy = process.env.NO_PROXY || process.env.no_proxy || '';
if (!noProxy) return false;
const hostname = new URL(urlStr).hostname;
return noProxy.split(',').some((pattern) => {
const p = pattern.trim();
if (!p) return false;
if (p.startsWith('.')) return hostname.endsWith(p) || hostname === p.slice(1);
return hostname === p || hostname.endsWith('.' + p);
});
}
// In customFetch():
if (process.env.PROXY && !shouldBypassProxy(urlStr)) {
agent = new ProxyAgent(process.env.PROXY);
}
Notes:
Microsoft Graph calls — that is a separate concern and intentionally not changed here.
Code of Conduct