Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

allow emails to be passed through SAML #7385

Merged
merged 3 commits into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7385.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
For SAML authentication, add the ability to pass email addresses to be added to new users' accounts via SAML attributes. Contributed by Christopher Cooper.
2 changes: 2 additions & 0 deletions docs/sso_mapping_providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ A custom mapping provider must specify the following methods:
* `mxid_localpart` - Required. The mxid localpart of the new user.
* `displayname` - The displayname of the new user. If not provided, will default to
the value of `mxid_localpart`.
* `emails` - A list of emails for the new user. If not provided, will
default to an empty list.

### Default SAML Mapping Provider

Expand Down
12 changes: 10 additions & 2 deletions synapse/handlers/saml_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ async def _map_saml_response_to_user(
raise SynapseError(500, "Error parsing SAML2 response")

displayname = attribute_dict.get("displayname")
emails = attribute_dict.get("emails", [])

# Check if this mxid already exists
if not await self._datastore.get_users_by_id_case_insensitive(
Expand All @@ -288,7 +289,9 @@ async def _map_saml_response_to_user(
logger.info("Mapped SAML user to local part %s", localpart)

registered_user_id = await self._registration_handler.register_user(
localpart=localpart, default_display_name=displayname
localpart=localpart,
default_display_name=displayname,
bind_emails=emails,
)

await self._datastore.record_user_external_id(
Expand Down Expand Up @@ -381,6 +384,7 @@ def saml_response_to_user_attributes(
dict: A dict containing new user attributes. Possible keys:
* mxid_localpart (str): Required. The localpart of the user's mxid
* displayname (str): The displayname of the user
* emails (list[str]): Any emails for the user
"""
try:
mxid_source = saml_response.ava[self._mxid_source_attribute][0]
Expand All @@ -403,9 +407,13 @@ def saml_response_to_user_attributes(
# If displayname is None, the mxid_localpart will be used instead
displayname = saml_response.ava.get("displayName", [None])[0]

# Retrieve any emails present in the saml response
emails = saml_response.ava.get("email", [])

return {
"mxid_localpart": localpart,
"displayname": displayname,
"emails": emails,
}

@staticmethod
Expand Down Expand Up @@ -444,4 +452,4 @@ def get_saml_attributes(config: SamlConfig) -> Tuple[Set[str], Set[str]]:
second set consists of those attributes which can be used if
available, but are not necessary
"""
return {"uid", config.mxid_source_attribute}, {"displayName"}
return {"uid", config.mxid_source_attribute}, {"displayName", "email"}