From 9da6a85ad86f5092edb96495eeb1cca22d5334bf Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Sun, 7 Jun 2026 17:55:32 +0300 Subject: [PATCH] fix: SAML provider add guard to skip empty mappings before iterating (#1536) --- cms/version.py | 2 +- saml_auth/adapter.py | 11 +++++++---- saml_auth/custom/provider.py | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/cms/version.py b/cms/version.py index c0a494d8..277de075 100644 --- a/cms/version.py +++ b/cms/version.py @@ -1 +1 @@ -VERSION = "8.2.0" +VERSION = "8.2.1" diff --git a/saml_auth/adapter.py b/saml_auth/adapter.py index f20731a3..45c4d3b9 100644 --- a/saml_auth/adapter.py +++ b/saml_auth/adapter.py @@ -73,7 +73,7 @@ def perform_user_actions(user, social_account, common_fields=None): if social_app: saml_configuration = social_app.saml_configurations.first() - add_user_logo(user, extra_data) + add_user_logo(user, extra_data, saml_configuration) handle_role_mapping(user, extra_data, social_app, saml_configuration) if saml_configuration and saml_configuration.save_saml_response_logs: handle_saml_logs_save(user, extra_data, social_app) @@ -81,10 +81,13 @@ def perform_user_actions(user, social_account, common_fields=None): return user -def add_user_logo(user, extra_data): +def add_user_logo(user, extra_data, saml_configuration=None): + # use the attribute name configured in the SAML Configuration, falling + # back to "jpegPhoto" when it is left empty + logo_key = (saml_configuration.user_logo if saml_configuration and saml_configuration.user_logo else None) or "jpegPhoto" try: - if extra_data.get("jpegPhoto") and user.logo.name in ["userlogos/user.jpg", "", None]: - base64_string = extra_data.get("jpegPhoto")[0] + if extra_data.get(logo_key) and user.logo.name in ["userlogos/user.jpg", "", None]: + base64_string = extra_data.get(logo_key)[0] image_data = base64.b64decode(base64_string) image_content = ContentFile(image_data) user.logo.save('user.jpg', image_content, save=True) diff --git a/saml_auth/custom/provider.py b/saml_auth/custom/provider.py index ebc19d9e..ade68a6e 100644 --- a/saml_auth/custom/provider.py +++ b/saml_auth/custom/provider.py @@ -18,14 +18,28 @@ class CustomSAMLProvider(SAMLProvider): provider_config = self.app.settings raw_attributes = data.get_attributes() + # get_attributes() keys attributes by their full Name. Some IdPs send + # certain attributes only under their FriendlyName, so fall back to the + # FriendlyName-keyed attributes when a Name lookup misses. The Name + # lookup is always preferred, so attributes that already resolve are + # unaffected. + try: + friendly_attributes = data.get_friendlyname_attributes() + except AttributeError: + friendly_attributes = {} attributes = {} attribute_mapping = provider_config.get("attribute_mapping", self.default_attribute_mapping) # map configured provider attributes for key, provider_keys in attribute_mapping.items(): + # skip mappings left empty/None in the SAML Configuration + if not provider_keys: + continue if isinstance(provider_keys, str): provider_keys = [provider_keys] for provider_key in provider_keys: - attribute_list = raw_attributes.get(provider_key, None) + attribute_list = raw_attributes.get(provider_key) + if attribute_list is None: + attribute_list = friendly_attributes.get(provider_key) # if more than one keys, get them all comma separated if attribute_list is not None and len(attribute_list) > 1: attributes[key] = ",".join(attribute_list)