diff --git a/changelog.d/6070.feature b/changelog.d/6070.feature new file mode 100644 index 0000000000..95d82bd4d8 --- /dev/null +++ b/changelog.d/6070.feature @@ -0,0 +1 @@ +Handle userid clashes when authenticating via SAML by appending an integer suffix. \ No newline at end of file diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 7615a4dbab..53a83cad88 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -1115,6 +1115,8 @@ saml2_config: # Options include: # * 'hexencode' (which maps unpermitted characters to '=xx') # * 'dotreplace' (which replaces unpermitted characters with '.'). + # * 'dotreplace_email_localpart' (truncates at the first '@' and replaces + # unpermitted characters with '.') # The default is 'hexencode'. # #mxid_mapping: dotreplace diff --git a/synapse/config/saml2_config.py b/synapse/config/saml2_config.py index a022470702..d69ffea38f 100644 --- a/synapse/config/saml2_config.py +++ b/synapse/config/saml2_config.py @@ -184,6 +184,8 @@ class SAML2Config(Config): # Options include: # * 'hexencode' (which maps unpermitted characters to '=xx') # * 'dotreplace' (which replaces unpermitted characters with '.'). + # * 'dotreplace_email_localpart' (truncates at the first '@' and replaces + # unpermitted characters with '.') # The default is 'hexencode'. # #mxid_mapping: dotreplace @@ -210,7 +212,7 @@ DOT_REPLACE_PATTERN = re.compile( ) -def dot_replace_for_mxid(username: str) -> str: +def dotreplace_for_mxid(username: str) -> str: username = username.lower() username = DOT_REPLACE_PATTERN.sub(".", username) @@ -219,7 +221,15 @@ def dot_replace_for_mxid(username: str) -> str: return username +def dotreplace_email_localpart_for_mxid(username: str) -> str: + pos = username.find("@") + if pos >= 0: + username = username[:pos] + return dotreplace_for_mxid(username) + + MXID_MAPPER_MAP = { "hexencode": map_username_to_mxid_localpart, - "dotreplace": dot_replace_for_mxid, + "dotreplace": dotreplace_for_mxid, + "dotreplace_email_localpart": dotreplace_email_localpart_for_mxid, } diff --git a/synapse/handlers/saml_handler.py b/synapse/handlers/saml_handler.py index 5fa8272dc9..f000d2a00f 100644 --- a/synapse/handlers/saml_handler.py +++ b/synapse/handlers/saml_handler.py @@ -111,6 +111,8 @@ class SamlHandler: logger.warning("SAML2 response was not signed") raise SynapseError(400, "SAML2 response was not signed") + logger.info("Got SAML2 reponse with attributes: %s", saml2_auth.ava) + try: remote_user_id = saml2_auth.ava["uid"][0] except KeyError: