From 7de9f5bc7b33beac07bd64eecfce54865bdb4913 Mon Sep 17 00:00:00 2001 From: Steven Giron Date: Thu, 28 May 2026 15:02:30 -0500 Subject: [PATCH] fix: redirect TPA account_settings errors to Account MFE with duplicate_provider param --- .../djangoapps/third_party_auth/pipeline.py | 2 +- common/djangoapps/third_party_auth/urls.py | 2 ++ common/djangoapps/third_party_auth/views.py | 25 +++++++++++++++++++ .../core/djangoapps/user_api/legacy_urls.py | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index 757075a61221..dcce75a5a52b 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -151,7 +151,7 @@ def is_api(auth_entry): AUTH_DISPATCH_URLS = { AUTH_ENTRY_LOGIN: '/login', AUTH_ENTRY_REGISTER: '/register', - AUTH_ENTRY_ACCOUNT_SETTINGS: '/account/settings', + AUTH_ENTRY_ACCOUNT_SETTINGS: '/auth/account_settings_error', } _AUTH_ENTRY_CHOICES = frozenset([ diff --git a/common/djangoapps/third_party_auth/urls.py b/common/djangoapps/third_party_auth/urls.py index 814790bba961..99bb3a31e1a6 100644 --- a/common/djangoapps/third_party_auth/urls.py +++ b/common/djangoapps/third_party_auth/urls.py @@ -4,6 +4,7 @@ from .views import ( IdPRedirectView, + account_settings_error_view, disconnect_json_view, inactive_user_view, lti_login_and_complete_view, @@ -24,6 +25,7 @@ disconnect_json_view, name='custom_disconnect_json_individual' ), + path('auth/account_settings_error', account_settings_error_view, name='tpa_account_settings_error'), path('auth/', include('social_django.urls', namespace='social')), path('auth/saml/v0/', include('common.djangoapps.third_party_auth.saml_configuration.urls')), # NOTE: The following routes under auth/saml/v0/ are registered by the diff --git a/common/djangoapps/third_party_auth/views.py b/common/djangoapps/third_party_auth/views.py index f31dde61005c..dd04e2896f14 100644 --- a/common/djangoapps/third_party_auth/views.py +++ b/common/djangoapps/third_party_auth/views.py @@ -3,9 +3,11 @@ """ import logging +from urllib.parse import quote from django.conf import settings from django.contrib.auth.decorators import login_required +from django.contrib.messages import get_messages from django.core.exceptions import PermissionDenied, ValidationError from django.db import DatabaseError from django.http import ( @@ -273,3 +275,26 @@ def disconnect_json_view(request, backend, association_id=None): 'backend': backend, 'association_id': association_id }, status=500) + +def account_settings_error_view(request): + """ + Intermediate view that reads Django messages left by the social auth + exception middleware and redirects to the Account MFE with the + duplicate_provider query parameter so the frontend can render the error. + """ + account_mfe_url = getattr(settings, 'ACCOUNT_MICROFRONTEND_URL', '/account/').rstrip('/') + all_messages = list(get_messages(request)) + duplicate_backend = pipeline.get_duplicate_provider(all_messages) + + if duplicate_backend: + # Try to get the human-readable name from the first enabled provider + # that uses this backend on the current site. + provider_name = duplicate_backend + enabled_providers = list(provider.Registry.get_enabled_by_backend_name(duplicate_backend)) + if enabled_providers: + provider_name = enabled_providers[0].name + + params = f"duplicate_provider={quote(provider_name)}" + return redirect(f'{account_mfe_url}/?{params}') + + return redirect(f'{account_mfe_url}/?{params}') diff --git a/openedx/core/djangoapps/user_api/legacy_urls.py b/openedx/core/djangoapps/user_api/legacy_urls.py index f2ec67c9cefb..07151a73de6a 100644 --- a/openedx/core/djangoapps/user_api/legacy_urls.py +++ b/openedx/core/djangoapps/user_api/legacy_urls.py @@ -23,7 +23,7 @@ url=configuration_helpers.get_value( 'ACCOUNT_MICROFRONTEND_URL', settings.ACCOUNT_MICROFRONTEND_URL, - )), + ), query_string=True,), ), path('user_api/v1/', include(USER_API_ROUTER.urls)), re_path(