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

Implement config option sso.update_profile_information #10108

Merged
merged 21 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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/10108.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement config option `sso.update_profile_information` to sync SSO users' profile information with the identity provider each time they login. Currently only displayname is supported.
11 changes: 11 additions & 0 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1975,6 +1975,17 @@ sso:
# - https://riot.im/develop
# - https://my.custom.client/

# Uncomment to keep a user's profile fields in sync with information from
# the identity provider. Currently only syncing the displayname is
# supported. Fields are checked on every SSO login, and are updated
# if necessary.
#
# Note that enabling this option will override user profile information,
# regardless of whether users have opted-out of syncing that
# information when first signing in. Defaults to false.
#
#update_profile_information: true

# Directory in which Synapse will try to find the template files below.
# If not set, or the files named below are not found within the template
# directory, default templates from within the Synapse package will be used.
Expand Down
15 changes: 15 additions & 0 deletions synapse/config/sso.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def read_config(self, config, **kwargs):

self.sso_client_whitelist = sso_config.get("client_whitelist") or []

self.sso_update_profile_information = (
sso_config.get("update_profile_information") or False
)

# Attempt to also whitelist the server's login fallback, since that fallback sets
# the redirect URL to itself (so it can process the login token then return
# gracefully to the client). This would make it pointless to ask the user for
Expand Down Expand Up @@ -111,6 +115,17 @@ def generate_config_section(self, **kwargs):
# - https://riot.im/develop
# - https://my.custom.client/
jkanefendt marked this conversation as resolved.
Show resolved Hide resolved

# Uncomment to keep a user's profile fields in sync with information from
# the identity provider. Currently only syncing the displayname is
# supported. Fields are checked on every SSO login, and are updated
# if necessary.
#
jkanefendt marked this conversation as resolved.
Show resolved Hide resolved
# Note that enabling this option will override user profile information,
# regardless of whether users have opted-out of syncing that
# information when first signing in. Defaults to false.
#
#update_profile_information: true

# Directory in which Synapse will try to find the template files below.
# If not set, or the files named below are not found within the template
# directory, default templates from within the Synapse package will be used.
Expand Down
25 changes: 24 additions & 1 deletion synapse/handlers/sso.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@
from synapse.http import get_request_user_agent
from synapse.http.server import respond_with_html, respond_with_redirect
from synapse.http.site import SynapseRequest
from synapse.types import JsonDict, UserID, contains_invalid_mxid_characters
from synapse.types import (
JsonDict,
UserID,
contains_invalid_mxid_characters,
create_requester,
)
from synapse.util.async_helpers import Linearizer
from synapse.util.stringutils import random_string

Expand Down Expand Up @@ -185,11 +190,14 @@ def __init__(self, hs: "HomeServer"):
self._auth_handler = hs.get_auth_handler()
self._error_template = hs.config.sso_error_template
self._bad_user_template = hs.config.sso_auth_bad_user_template
self._profile_handler = hs.get_profile_handler()

# The following template is shown after a successful user interactive
# authentication session. It tells the user they can close the window.
self._sso_auth_success_template = hs.config.sso_auth_success_template

self._sso_update_profile_information = hs.config.sso_update_profile_information

# a lock on the mappings
self._mapping_lock = Linearizer(name="sso_user_mapping", clock=hs.get_clock())

Expand Down Expand Up @@ -458,6 +466,21 @@ async def complete_sso_login_request(
request.getClientIP(),
)
new_user = True
elif self._sso_update_profile_information:
attributes = await self._call_attribute_mapper(sso_to_matrix_id_mapper)
if attributes.display_name:
user_id_obj = UserID.from_string(user_id)
profile_display_name = await self._profile_handler.get_displayname(
user_id_obj
)
if profile_display_name != attributes.display_name:
requester = create_requester(
user_id,
authenticated_entity=user_id,
)
await self._profile_handler.set_displayname(
user_id_obj, requester, attributes.display_name, True
)

await self._auth_handler.complete_sso_login(
user_id,
Expand Down