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

Abstract shared SSO code #8765

Merged
merged 7 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
14 changes: 4 additions & 10 deletions synapse/handlers/oidc_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,20 +864,14 @@ async def _map_userinfo_to_user(
# to be strings.
remote_user_id = str(remote_user_id)

logger.info(
"Looking for existing mapping for user %s:%s",
self._auth_provider_id,
remote_user_id,
)

registered_user_id = await self.store.get_user_by_external_id(
# first of all, check if we already have a mapping for this user
registered_user_id = await self._sso_handler.get_sso_user_by_remote_user_id(
self._auth_provider_id, remote_user_id,
)

if registered_user_id is not None:
logger.info("Found existing mapping %s", registered_user_id)
if registered_user_id:
return registered_user_id

# Otherwise, generate a new user.
try:
attributes = await self._user_mapping_provider.map_user_attributes(
userinfo, token
Expand Down
12 changes: 3 additions & 9 deletions synapse/handlers/saml_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,10 @@ async def _map_saml_response_to_user(

with (await self._mapping_lock.queue(self._auth_provider_id)):
# first of all, check if we already have a mapping for this user
logger.info(
"Looking for existing mapping for user %s:%s",
self._auth_provider_id,
remote_user_id,
registered_user_id = await self._sso_handler.get_sso_user_by_remote_user_id(
self._auth_provider_id, remote_user_id,
)
registered_user_id = await self.store.get_user_by_external_id(
self._auth_provider_id, remote_user_id
)
if registered_user_id is not None:
logger.info("Found existing mapping %s", registered_user_id)
if registered_user_id:
return registered_user_id

# backwards-compatibility hack: see if there is an existing user with a
Expand Down
36 changes: 36 additions & 0 deletions synapse/handlers/sso.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,39 @@ def render_error(
error=error, error_description=error_description
)
respond_with_html(request, 400, html)

async def get_sso_user_by_remote_user_id(
self, auth_provider_id: str, remote_user_id: str
) -> Optional[str]:
"""
Maps the user ID of a remote IdP to a mxid for a previously seen user.

If the user has not been seen yet, this will return None.

Args:
auth_provider_id: A unique identifier for this SSO provider, e.g.
"oidc" or "saml".
remote_user_id: The user ID according to the remote IdP. This might
be an e-mail address, a GUID, or some other form. It must be
unique and immutable.

Returns:
The mxid of a previously seen user.
"""
# Check if we already have a mapping for this user.
logger.info(
"Looking for existing mapping for user %s:%s",
auth_provider_id,
remote_user_id,
)
Comment on lines +75 to +79
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I question whether these need to be at info level.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect it is at info since a server admin might get a report "I can't login via SSO" or something and want to have some logs about what is happening.

(Note that this is also just copied, I didn't change the log level.)

I don't have a strong opinion on this though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect it is at info since a server admin might get a report "I can't login via SSO" or something and want to have some logs about what is happening.

That's a good point.

(Note that this is also just copied, I didn't change the log level.)

Yeah, just questioning it as a drive-by. I have an idea for improvement, but I can drop these changes in a separate PR if you think they make sense:

Perhaps we could ditch/drop down the level of the "Looking" log line, and keep (and extend with more info) the "Found existing mapping" line for when users do have problems?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might work? I think it makes sense as a separate PR since that isn't really abstracting. 😄

registered_user_id = await self.store.get_user_by_external_id(
clokep marked this conversation as resolved.
Show resolved Hide resolved
auth_provider_id, remote_user_id,
)

# A match was found, return the user ID.
if registered_user_id is not None:
logger.info("Found existing mapping %s", registered_user_id)
return registered_user_id

# No match.
return None