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

Commit ffd0851

Browse files
committed
Add support for icons for identity providers
1 parent 6ccb88f commit ffd0851

File tree

6 files changed

+56
-0
lines changed

6 files changed

+56
-0
lines changed

docs/sample_config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,10 @@ saml2_config:
17231723
# idp_name: A user-facing name for this identity provider, which is used to
17241724
# offer the user a choice of login mechanisms.
17251725
#
1726+
# idp_icon: An optional icon for this identity provider, which is presented
1727+
# by identity picker pages. If given, must be an MXC URI of the format
1728+
# mxc://<server-name>/<media-id>
1729+
#
17261730
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
17271731
# to discover endpoints. Defaults to true.
17281732
#

synapse/config/oidc_config.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from synapse.python_dependencies import DependencyException, check_requirements
2424
from synapse.types import Collection, JsonDict
2525
from synapse.util.module_loader import load_module
26+
from synapse.util.stringutils import parse_and_validate_mxc_uri
2627

2728
from ._base import Config, ConfigError
2829

@@ -68,6 +69,10 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
6869
# idp_name: A user-facing name for this identity provider, which is used to
6970
# offer the user a choice of login mechanisms.
7071
#
72+
# idp_icon: An optional icon for this identity provider, which is presented
73+
# by identity picker pages. If given, must be an MXC URI of the format
74+
# mxc://<server-name>/<media-id>
75+
#
7176
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
7277
# to discover endpoints. Defaults to true.
7378
#
@@ -209,6 +214,7 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
209214
"properties": {
210215
"idp_id": {"type": "string", "minLength": 1, "maxLength": 128},
211216
"idp_name": {"type": "string"},
217+
"idp_icon": {"type": "string"},
212218
"discover": {"type": "boolean"},
213219
"issuer": {"type": "string"},
214220
"client_id": {"type": "string"},
@@ -338,9 +344,20 @@ def _parse_oidc_config_dict(
338344
config_path + ("idp_id",),
339345
)
340346

347+
# MSC2858 also specifies that the idp_icon must be a valid MXC uri
348+
idp_icon = oidc_config.get("idp_icon")
349+
if idp_icon is not None:
350+
try:
351+
parse_and_validate_mxc_uri(idp_icon)
352+
except ValueError as e:
353+
raise ConfigError(
354+
"idp_icon must be a valid MXC URI", config_path + ("idp_icon",)
355+
) from e
356+
341357
return OidcProviderConfig(
342358
idp_id=idp_id,
343359
idp_name=oidc_config.get("idp_name", "OIDC"),
360+
idp_icon=idp_icon,
344361
discover=oidc_config.get("discover", True),
345362
issuer=oidc_config["issuer"],
346363
client_id=oidc_config["client_id"],
@@ -368,6 +385,9 @@ class OidcProviderConfig:
368385
# user-facing name for this identity provider.
369386
idp_name = attr.ib(type=str)
370387

388+
# Optional MXC URI for icon for this IdP.
389+
idp_icon = attr.ib(type=Optional[str])
390+
371391
# whether the OIDC discovery mechanism is used to discover endpoints
372392
discover = attr.ib(type=bool)
373393

synapse/handlers/oidc_handler.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ def __init__(
271271
# user-facing name of this auth provider
272272
self.idp_name = provider.idp_name
273273

274+
# MXC URI for icon for this auth provider
275+
self.idp_icon = provider.idp_icon
276+
274277
self._sso_handler = hs.get_sso_handler()
275278

276279
self._sso_handler.register_identity_provider(self)

synapse/handlers/sso.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ def idp_id(self) -> str:
7575
def idp_name(self) -> str:
7676
"""User-facing name for this provider"""
7777

78+
@property
79+
def idp_icon(self) -> Optional[str]:
80+
"""Optional MXC URI for user-facing icon"""
81+
return None
82+
7883
@abc.abstractmethod
7984
async def handle_redirect_request(
8085
self,

synapse/res/templates/sso_login_idp_picker.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ <h1 id="title">{{server_name | e}} Login</h1>
1717
<li>
1818
<input type="radio" name="idp" id="prov{{loop.index}}" value="{{p.idp_id}}">
1919
<label for="prov{{loop.index}}">{{p.idp_name | e}}</label>
20+
{% if p.idp_icon %}
21+
<img src="{{p.idp_icon | mxc_to_http(32, 32)}}"/>
22+
{% endif %}
2023
</li>
2124
{% endfor %}
2225
</ul>

synapse/util/stringutils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ def parse_and_validate_server_name(server_name: str) -> Tuple[str, Optional[int]
130130
return host, port
131131

132132

133+
def parse_and_validate_mxc_uri(mxc: str) -> Tuple[str, Optional[int], str]:
134+
"""Parse the given string as an MXC URI
135+
136+
Checks that the "server name" part is a valid server name
137+
138+
Args:
139+
mxc: the (alleged) MXC URI to be checked
140+
Returns:
141+
hostname, port, media id
142+
Raises:
143+
ValueError if the URI cannot be parsed
144+
"""
145+
m = mxc_re.match(mxc)
146+
if not m:
147+
raise ValueError("mxc URI %r did not match expected format" % (mxc,))
148+
server_name = m.group(1)
149+
media_id = m.group(2)
150+
host, port = parse_and_validate_server_name(server_name)
151+
return host, port, media_id
152+
153+
133154
def shortstr(iterable: Iterable, maxitems: int = 5) -> str:
134155
"""If iterable has maxitems or fewer, return the stringification of a list
135156
containing those items.

0 commit comments

Comments
 (0)