allow emails to be passed through SAML (#7385)

Signed-off-by: Christopher Cooper <cooperc@ocf.berkeley.edu>
This commit is contained in:
Christopher Cooper 2020-05-27 09:40:08 -07:00 committed by GitHub
parent 5af572ada0
commit c4a820b32a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 2 deletions

1
changelog.d/7385.feature Normal file
View File

@ -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.

View File

@ -138,6 +138,8 @@ A custom mapping provider must specify the following methods:
* `mxid_localpart` - Required. The mxid localpart of the new user. * `mxid_localpart` - Required. The mxid localpart of the new user.
* `displayname` - The displayname of the new user. If not provided, will default to * `displayname` - The displayname of the new user. If not provided, will default to
the value of `mxid_localpart`. 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 ### Default SAML Mapping Provider

View File

@ -271,6 +271,7 @@ class SamlHandler:
raise SynapseError(500, "Error parsing SAML2 response") raise SynapseError(500, "Error parsing SAML2 response")
displayname = attribute_dict.get("displayname") displayname = attribute_dict.get("displayname")
emails = attribute_dict.get("emails", [])
# Check if this mxid already exists # Check if this mxid already exists
if not await self._datastore.get_users_by_id_case_insensitive( if not await self._datastore.get_users_by_id_case_insensitive(
@ -288,7 +289,9 @@ class SamlHandler:
logger.info("Mapped SAML user to local part %s", localpart) logger.info("Mapped SAML user to local part %s", localpart)
registered_user_id = await self._registration_handler.register_user( 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( await self._datastore.record_user_external_id(
@ -381,6 +384,7 @@ class DefaultSamlMappingProvider(object):
dict: A dict containing new user attributes. Possible keys: dict: A dict containing new user attributes. Possible keys:
* mxid_localpart (str): Required. The localpart of the user's mxid * mxid_localpart (str): Required. The localpart of the user's mxid
* displayname (str): The displayname of the user * displayname (str): The displayname of the user
* emails (list[str]): Any emails for the user
""" """
try: try:
mxid_source = saml_response.ava[self._mxid_source_attribute][0] mxid_source = saml_response.ava[self._mxid_source_attribute][0]
@ -403,9 +407,13 @@ class DefaultSamlMappingProvider(object):
# If displayname is None, the mxid_localpart will be used instead # If displayname is None, the mxid_localpart will be used instead
displayname = saml_response.ava.get("displayName", [None])[0] displayname = saml_response.ava.get("displayName", [None])[0]
# Retrieve any emails present in the saml response
emails = saml_response.ava.get("email", [])
return { return {
"mxid_localpart": localpart, "mxid_localpart": localpart,
"displayname": displayname, "displayname": displayname,
"emails": emails,
} }
@staticmethod @staticmethod
@ -444,4 +452,4 @@ class DefaultSamlMappingProvider(object):
second set consists of those attributes which can be used if second set consists of those attributes which can be used if
available, but are not necessary available, but are not necessary
""" """
return {"uid", config.mxid_source_attribute}, {"displayName"} return {"uid", config.mxid_source_attribute}, {"displayName", "email"}