You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We want to retire the legacy server-rendered login/registration page (DEPR openedx/public-engineering#81, tracked in openedx/openedx-platform#38936), but we can't yet, and enterprise is the reason. The legacy page renders an enterprise-branded logistration experience (branded sidebar, provider suppression, consent-gated SSO registration) that frontend-app-authn doesn't, so the platform deliberately keeps enterprise/SSO learners on the old page. You can see the guard in openedx/core/djangoapps/user_authn/views/login_form.py:176-190:
has_external_provider=bool(tpa_hint_providerorsaml_provider)
# NOTE: SAML/TPA users authenticating externally must remain on the legacy login/registration page# because the new AuthN MFE does not yet fully support provider branding, hinted-login dialog, etc.# TODO: Remove the `has_external_provider` check as soon as the AuthN MFE is fully-featured.ifshould_redirect_to_authn_microfrontend() andnothas_external_provider:
returnredirect(settings.AUTHN_MICROFRONTEND_URL+url_path)
This issue is about building that enterprise experience in the MFE so we can drop the guard and remove the legacy page.
Groundwork already in place
The backend was refactored so enterprise logic reaches logistration (the MFE included) through openedx-filters pipeline steps instead of inline platform code:
feat: add pipeline steps for logistration filters edx-enterprise#2551 (2026-08-07) - added the enterprise pipeline steps, including AuthnMFEEnterpriseContextEnricher (enterprise/filters/logistration.py:98), which adds an enterpriseBranding payload to the MFE context, plus LoginFormEnterpriseOverrides / RegistrationFormEnterpriseOverrides.
Enterprise is intentionally not built into the platform by default - that's the whole point of the filter refactor above: the platform ships no enterprise code, and edx-enterprise plugs in. The MFE should hold the same line, so I don't think we want to hardcode the enterprise experience into frontend-app-authn. The likely shape is a frontend plugin that installs into authn plugin slots and renders enterprise from the enterpriseBranding context - the frontend counterpart to how edx-enterprise plugs into the backend - but the details are unclear, and pinning them down is part of this work:
What slots does the authn MFE need to expose for this - an enterprise sidebar region, the provider list, messaging, registration fields? Today there's only LoginComponentSlot, so this overlaps with Plugin slots and customization settings for authn #1686 (plugin slots for authn).
Where does the enterprise plugin live and who owns it - a separate frontend package that's the edx-enterprise counterpart?
How does the plugin get the context - read enterpriseBranding off the mfe_context the core app already fetches, or fetch its own?
So full implementation is unclear precisely because enterprise is meant to be pluggable. Settling this architecture is the first task, ahead of the rendering itself.
What's left to do
1. Populate the enterpriseBranding payload (backend dependency).AuthnMFEEnterpriseContextEnricher builds its payload from build_enterprise_branding_for_authn_mfe(...), which isn't implemented yet - it's imported with a None fallback (edx-enterpriseenterprise/filters/logistration.py:40-41) and is absent from openedx-platform master. This helper (referenced under ENT-11576) has to land so /api/mfe_context actually returns enterprise branding. It may be owned separately; I'm calling it out as a prerequisite.
2. Render the enterprise experience (as a plugin, per the open question above). Today the MFE has none, and the DISABLE_ENTERPRISE_LOGIN flag doesn't help: setting it false only swaps the institution-login button for a link out to the LMS /enterprise/login page (ThirdPartyAuth.jsx:47-72), it doesn't render any enterprise branding, suppression, or consent - so flipping it isn't a solution. EnterpriseSSO.jsx is likewise just a generic single-provider button. We need parity with the legacy openedx/features/enterprise_support/ behavior:
Enterprise sidebar / branding - consume enterpriseBranding and render the enterprise logo + branded welcome.
Generic-provider suppression - in an enterprise SSO context, show only the enterprise provider and hide the generic social/TPA providers.
Consent-gated auto-registration - for skip_registration_form SSO, don't silently auto-submit; show the auto-register welcome message and a "Continue" button.
Enterprise-branded TPA error messaging ("not authorized via this channel / contact your administrator") instead of the generic error.
Enterprise registration-field handling - drop excluded fields (ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS) and show SSO-synced profile fields read-only.
Account-linking + multiple-enterprise selection - the "you already have an account with your {enterprise} email" copy, and routing learners in more than one enterprise to the selection page (/enterprise/select/active, LMS-hosted). Confirm how much of this is MFE-side vs. delegated.
3. Confirm what already flows vs. what's net-new.LoginFormEnterpriseOverrides / RegistrationFormEnterpriseOverrides modify the shared form-description context the MFE already reads, so some of the above (provider suppression, consent-gated auto-register, field handling) may already arrive via /api/mfe_context. Worth auditing which overrides reach the MFE today before building anything new.
4. Remove the platform guard. Once the MFE renders these flows at parity, remove the has_external_provider guard in login_form.py:176-190 so enterprise/SSO learners are served by the MFE. That's the step that finally unblocks the legacy removal.
Definition of done
A decided pluggable architecture - which authn slots to expose and where the enterprise plugin lives - so enterprise stays opt-in, not built into the MFE by default.
/api/mfe_context returns a populated enterpriseBranding payload.
frontend-app-authn renders enterprise SSO / proxy-login flows at parity with the legacy page.
The has_external_provider guard can be removed and enterprise/SSO learners are served by the MFE.
Context
We want to retire the legacy server-rendered login/registration page (DEPR openedx/public-engineering#81, tracked in openedx/openedx-platform#38936), but we can't yet, and enterprise is the reason. The legacy page renders an enterprise-branded logistration experience (branded sidebar, provider suppression, consent-gated SSO registration) that
frontend-app-authndoesn't, so the platform deliberately keeps enterprise/SSO learners on the old page. You can see the guard inopenedx/core/djangoapps/user_authn/views/login_form.py:176-190:This issue is about building that enterprise experience in the MFE so we can drop the guard and remove the legacy page.
Groundwork already in place
The backend was refactored so enterprise logic reaches logistration (the MFE included) through
openedx-filterspipeline steps instead of inline platform code:AuthnMFEContextGenerated.AuthnMFEEnterpriseContextEnricher(enterprise/filters/logistration.py:98), which adds anenterpriseBrandingpayload to the MFE context, plusLoginFormEnterpriseOverrides/RegistrationFormEnterpriseOverrides.user_authn(views/utils.py:162firesAuthnMFEContextGeneratedon the/api/mfe_contextpath).Keeping enterprise pluggable (open question)
Enterprise is intentionally not built into the platform by default - that's the whole point of the filter refactor above: the platform ships no enterprise code, and edx-enterprise plugs in. The MFE should hold the same line, so I don't think we want to hardcode the enterprise experience into
frontend-app-authn. The likely shape is a frontend plugin that installs into authn plugin slots and renders enterprise from theenterpriseBrandingcontext - the frontend counterpart to how edx-enterprise plugs into the backend - but the details are unclear, and pinning them down is part of this work:LoginComponentSlot, so this overlaps with Plugin slots and customization settings for authn #1686 (plugin slots for authn).enterpriseBrandingoff the mfe_context the core app already fetches, or fetch its own?So full implementation is unclear precisely because enterprise is meant to be pluggable. Settling this architecture is the first task, ahead of the rendering itself.
What's left to do
1. Populate the
enterpriseBrandingpayload (backend dependency).AuthnMFEEnterpriseContextEnricherbuilds its payload frombuild_enterprise_branding_for_authn_mfe(...), which isn't implemented yet - it's imported with aNonefallback (edx-enterpriseenterprise/filters/logistration.py:40-41) and is absent fromopenedx-platformmaster. This helper (referenced under ENT-11576) has to land so/api/mfe_contextactually returns enterprise branding. It may be owned separately; I'm calling it out as a prerequisite.2. Render the enterprise experience (as a plugin, per the open question above). Today the MFE has none, and the
DISABLE_ENTERPRISE_LOGINflag doesn't help: setting itfalseonly swaps the institution-login button for a link out to the LMS/enterprise/loginpage (ThirdPartyAuth.jsx:47-72), it doesn't render any enterprise branding, suppression, or consent - so flipping it isn't a solution.EnterpriseSSO.jsxis likewise just a generic single-provider button. We need parity with the legacyopenedx/features/enterprise_support/behavior:enterpriseBrandingand render the enterprise logo + branded welcome.skip_registration_formSSO, don't silently auto-submit; show the auto-register welcome message and a "Continue" button.ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS) and show SSO-synced profile fields read-only./enterprise/select/active, LMS-hosted). Confirm how much of this is MFE-side vs. delegated.3. Confirm what already flows vs. what's net-new.
LoginFormEnterpriseOverrides/RegistrationFormEnterpriseOverridesmodify the shared form-description context the MFE already reads, so some of the above (provider suppression, consent-gated auto-register, field handling) may already arrive via/api/mfe_context. Worth auditing which overrides reach the MFE today before building anything new.4. Remove the platform guard. Once the MFE renders these flows at parity, remove the
has_external_providerguard inlogin_form.py:176-190so enterprise/SSO learners are served by the MFE. That's the step that finally unblocks the legacy removal.Definition of done
/api/mfe_contextreturns a populatedenterpriseBrandingpayload.frontend-app-authnrenders enterprise SSO / proxy-login flows at parity with the legacy page.has_external_providerguard can be removed and enterprise/SSO learners are served by the MFE.References
edx-enterpriseenterprise/filters/logistration.py; platformuser_authn/views/utils.py:162.