fix(oidc): fail clearly when no public base URL is configured
CI exposed that getFrontendBaseUrl() returns '' without FRONTEND_URL or the general_site_url setting (local runs were masked by backend/.env): the flow then sent a RELATIVE redirect_uri to the IdP, which surfaced as an opaque IdP-side error. getRedirectUri now throws OIDC_BAD_CONFIG with an actionable message (login route maps it to sso_error=config); the settings GET degrades to an empty redirect_uri instead of 500ing. The test pins FRONTEND_URL explicitly so it runs identically with and without a local .env.
This commit is contained in:
@@ -38,6 +38,10 @@ describe('OIDC SSO (#798)', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
process.env.JWT_SECRET = process.env.JWT_SECRET || 'oidc-test-secret';
|
||||
// The redirect_uri derives from the public base URL — pin it explicitly:
|
||||
// CI has no backend/.env, and getFrontendBaseUrl() returning '' makes
|
||||
// buildAuthorizationRequest fail (by design) with OIDC_BAD_CONFIG.
|
||||
process.env.FRONTEND_URL = 'http://localhost:5199';
|
||||
({ db, cleanup } = await bootCrmDb());
|
||||
|
||||
idp = new MockOidcProvider();
|
||||
|
||||
@@ -390,6 +390,10 @@ router.get('/sso', adminAuth, requirePermission('settings.view'), async (req, re
|
||||
try {
|
||||
const oidcService = require('../services/oidcService');
|
||||
const cfg = await oidcService.getOidcConfig();
|
||||
// No public base URL configured → surface an empty redirect_uri rather
|
||||
// than failing the whole settings read; the login route refuses to start
|
||||
// the flow in that state anyway (OIDC_BAD_CONFIG).
|
||||
const redirectUri = await oidcService.getRedirectUri().catch(() => '');
|
||||
res.json({
|
||||
oidc_enabled: cfg.enabled,
|
||||
oidc_issuer_url: cfg.issuerUrl || '',
|
||||
@@ -399,7 +403,7 @@ router.get('/sso', adminAuth, requirePermission('settings.view'), async (req, re
|
||||
oidc_default_role: cfg.defaultRole,
|
||||
oidc_button_label: cfg.buttonLabel || '',
|
||||
oidc_scopes: cfg.scopes,
|
||||
redirect_uri: await oidcService.getRedirectUri(),
|
||||
redirect_uri: redirectUri,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Failed to read SSO settings', { error: error.message });
|
||||
|
||||
@@ -153,6 +153,14 @@ async function getClient(cfg) {
|
||||
async function getRedirectUri() {
|
||||
const { getFrontendBaseUrl } = require('../utils/frontendUrl');
|
||||
const base = (await getFrontendBaseUrl()).replace(/\/$/, '');
|
||||
if (!base) {
|
||||
// Without a public base URL the redirect_uri would be relative — the IdP
|
||||
// would reject it with an opaque error on ITS side. Fail here with a
|
||||
// clear config message instead.
|
||||
const err = new Error('FRONTEND_URL (or the general_site_url setting) must be set for SSO');
|
||||
err.code = 'OIDC_BAD_CONFIG';
|
||||
throw err;
|
||||
}
|
||||
return `${base}/api/auth/admin/sso/callback`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user