1 files changed, 43 insertions, 2 deletions
diff --git a/synapse/api/urls.py b/synapse/api/urls.py
index d077a2c613..655b5edd7a 100644
--- a/synapse/api/urls.py
+++ b/synapse/api/urls.py
@@ -19,10 +19,12 @@
#
#
-"""Contains the URL paths to prefix various aspects of the server with. """
+"""Contains the URL paths to prefix various aspects of the server with."""
+
import hmac
from hashlib import sha256
-from urllib.parse import urlencode
+from typing import Optional
+from urllib.parse import urlencode, urljoin
from synapse.config import ConfigError
from synapse.config.homeserver import HomeServerConfig
@@ -65,3 +67,42 @@ class ConsentURIBuilder:
urlencode({"u": user_id, "h": mac}),
)
return consent_uri
+
+
+class LoginSSORedirectURIBuilder:
+ def __init__(self, hs_config: HomeServerConfig):
+ self._public_baseurl = hs_config.server.public_baseurl
+
+ def build_login_sso_redirect_uri(
+ self, *, idp_id: Optional[str], client_redirect_url: str
+ ) -> str:
+ """Build a `/login/sso/redirect` URI for the given identity provider.
+
+ Builds `/_matrix/client/v3/login/sso/redirect/{idpId}?redirectUrl=xxx` when `idp_id` is specified.
+ Otherwise, builds `/_matrix/client/v3/login/sso/redirect?redirectUrl=xxx` when `idp_id` is `None`.
+
+ Args:
+ idp_id: Optional ID of the identity provider
+ client_redirect_url: URL to redirect the user to after login
+
+ Returns
+ The URI to follow when choosing a specific identity provider.
+ """
+ base_url = urljoin(
+ self._public_baseurl,
+ f"{CLIENT_API_PREFIX}/v3/login/sso/redirect",
+ )
+
+ serialized_query_parameters = urlencode({"redirectUrl": client_redirect_url})
+
+ if idp_id:
+ resultant_url = urljoin(
+ # We have to add a trailing slash to the base URL to ensure that the
+ # last path segment is not stripped away when joining with another path.
+ f"{base_url}/",
+ f"{idp_id}?{serialized_query_parameters}",
+ )
+ else:
+ resultant_url = f"{base_url}?{serialized_query_parameters}"
+
+ return resultant_url
|