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

Add additional type hints to SSO and registration code #8784

Merged
merged 8 commits into from Nov 23, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/8784.misc
@@ -0,0 +1 @@
Fix a bug introduced in v1.20.0 where the user-agent and IP address reported during user registration for CAS, OpenID Connect, and SAML were of the wrong form.
1 change: 1 addition & 0 deletions mypy.ini
Expand Up @@ -37,6 +37,7 @@ files =
synapse/handlers/presence.py,
synapse/handlers/profile.py,
synapse/handlers/read_marker.py,
synapse/handlers/register.py,
synapse/handlers/room.py,
synapse/handlers/room_member.py,
synapse/handlers/room_member_worker.py,
Expand Down
71 changes: 52 additions & 19 deletions synapse/handlers/cas_handler.py
Expand Up @@ -14,7 +14,7 @@
# limitations under the License.
import logging
import urllib
from typing import Dict, Optional, Tuple
from typing import TYPE_CHECKING, Dict, Optional, Tuple
from xml.etree import ElementTree as ET

from twisted.web.client import PartialDownloadError
Expand All @@ -23,6 +23,9 @@
from synapse.http.site import SynapseRequest
from synapse.types import UserID, map_username_to_mxid_localpart

if TYPE_CHECKING:
from synapse.app.homeserver import HomeServer

logger = logging.getLogger(__name__)


Expand All @@ -31,10 +34,10 @@ class CasHandler:
Utility class for to handle the response from a CAS SSO service.

Args:
hs (synapse.server.HomeServer)
hs
"""

def __init__(self, hs):
def __init__(self, hs: "HomeServer"):
self.hs = hs
self._hostname = hs.hostname
self._auth_handler = hs.get_auth_handler()
Expand Down Expand Up @@ -200,27 +203,57 @@ async def handle_ticket(
args["session"] = session
username, user_display_name = await self._validate_ticket(ticket, args)

localpart = map_username_to_mxid_localpart(username)
user_id = UserID(localpart, self._hostname).to_string()
registered_user_id = await self._auth_handler.check_user_exists(user_id)
# Pull out the user-agent and IP from the request.
user_agent = request.get_user_agent("")
ip_address = self.hs.get_ip_from_request(request)

# Get the matrix ID from the CAS username.
user_id = await self._map_cas_user_to_matrix_user(
username, user_display_name, user_agent, ip_address
)

if session:
await self._auth_handler.complete_sso_ui_auth(
registered_user_id, session, request,
user_id, session, request,
)

else:
if not registered_user_id:
# Pull out the user-agent and IP from the request.
user_agent = request.get_user_agent("")
ip_address = self.hs.get_ip_from_request(request)

registered_user_id = await self._registration_handler.register_user(
localpart=localpart,
default_display_name=user_display_name,
user_agent_ips=(user_agent, ip_address),
)
# If this not a UI auth request than there must be a redirect URL.
assert client_redirect_url

await self._auth_handler.complete_sso_login(
registered_user_id, request, client_redirect_url
user_id, request, client_redirect_url
)

async def _map_cas_user_to_matrix_user(
self,
remote_user_id: str,
display_name: Optional[str],
user_agent: str,
ip_address: str,
) -> str:
"""
Given a CAS username, retrieve the user ID for it and possibly register the user.

Args:
remote_user_id: The username from the CAS response.
display_name: The display name from the CAS response.
user_agent: The user agent of the client making the request.
ip_address: The IP address of the client making the request.

Returns:
The user ID associated with this response.
"""

localpart = map_username_to_mxid_localpart(remote_user_id)
user_id = UserID(localpart, self._hostname).to_string()
registered_user_id = await self._auth_handler.check_user_exists(user_id)

# If the user does not exist, register it.
if not registered_user_id:
registered_user_id = await self._registration_handler.register_user(
localpart=localpart,
default_display_name=display_name,
user_agent_ips=[(user_agent, ip_address)],
)

return registered_user_id
2 changes: 1 addition & 1 deletion synapse/handlers/oidc_handler.py
Expand Up @@ -925,7 +925,7 @@ async def _map_userinfo_to_user(
registered_user_id = await self._registration_handler.register_user(
localpart=localpart,
default_display_name=attributes["display_name"],
user_agent_ips=(user_agent, ip_address),
user_agent_ips=[(user_agent, ip_address)],
)

await self.store.record_user_external_id(
Expand Down