-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Summary
The OIDC authorization code exchange flow currently requires the frontend (oclweb3) to hold and transmit the OIDC_RP_CLIENT_SECRET to the backend. Per OAuth 2.0 best practices, confidential client secrets should only be stored and used server-side.
Current behavior
OIDC_RP_CLIENT_SECRETis injected into browser-accessible JavaScript in two ways:- At runtime via
env-config.js(window.OIDC_RP_CLIENT_SECRET) — written bystart-prod.sh - At build time via webpack
DefinePlugin(process.env.OIDC_RP_CLIENT_SECRET) — inwebpack.config.js
- At runtime via
- The
OIDLoginCallbackcomponent (src/components/users/OIDLoginCallback.jsx) reads the secret from the browser context and sends it in a POST request to the backend'soidc/code-exchange/endpoint - The backend (
core/users/views.py—OIDCodeExchangeView) receivesclient_idandclient_secretfrom the request body and uses them to exchange the authorization code for a token
Expected behavior
The backend should store OIDC_RP_CLIENT_ID and OIDC_RP_CLIENT_SECRET in its own environment and use them server-side during the code exchange. The frontend should only send code and redirect_uri.
Step 1: Ecosystem-wide audit (REQUIRED FIRST)
OCL Online is a complex ecosystem with many independent services and applications. Before making any code changes, a thorough audit must be conducted across the entire OCL Online ecosystem to identify all clients, applications, and services that handle OIDC client secrets in a similar way. This includes but is not limited to:
oclweb3andoclweb2(frontends)oclapi2(backend)- Any other services that participate in OIDC flows (e.g. FHIR services, analytics, admin tools)
- Docker compose configurations and deployment scripts across all environments
- KeyCloak client registrations and their configurations
The goal is to ensure that all affected components are revised together, not just the ones identified so far.
Proposed changes (pending audit results)
Backend (oclapi2):
core/settings.py: PopulateOIDC_RP_CLIENT_IDandOIDC_RP_CLIENT_SECRETfrom environment variables (placeholder settings already exist at lines 564-582)core/users/views.py: UpdateOIDCodeExchangeView.post()to readclient_id/client_secretfromsettingsinstead of the request bodycore/integration_tests/tests_users.py: UpdateOIDCodeExchangeViewTestto match new endpoint contract
Frontend (oclweb3):
src/components/users/OIDLoginCallback.jsx: Only sendcodeandredirect_uriin the POST tooidc/code-exchange/webpack.config.js: RemoveOIDC_RP_CLIENT_SECRETfromDefinePluginstart-prod.sh: RemoveOIDC_RP_CLIENT_SECRETfromenv-config.jsgenerationsrc/common/utils.js: UpdateisSSOEnabled()to check onlyLOGIN_REDIRECT_URL+OIDC_RP_CLIENT_ID(since the secret would no longer be in the frontend)
Other services: To be determined by the audit in Step 1.
Deployment note
Requires coordinated deployment: backend first (accept both old and new request formats during transition), then frontends/services, then remove backward compatibility from backend.
Labels
Security, oclweb3, oclapi2