Merge branch 'social_login' into develop
This commit is contained in:
commit
0d81a6fa3e
|
@ -1 +1 @@
|
||||||
Add experimental support for allowing clients to pick an SSO Identity Provider ([MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858).
|
Add experimental support for allowing clients to pick an SSO Identity Provider ([MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858)).
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add experimental support for allowing clients to pick an SSO Identity Provider ([MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858)).
|
|
@ -0,0 +1 @@
|
||||||
|
Add support to the OpenID Connect integration for adding the user's email address.
|
|
@ -225,6 +225,7 @@ Synapse config:
|
||||||
oidc_providers:
|
oidc_providers:
|
||||||
- idp_id: github
|
- idp_id: github
|
||||||
idp_name: Github
|
idp_name: Github
|
||||||
|
idp_brand: "org.matrix.github" # optional: styling hint for clients
|
||||||
discover: false
|
discover: false
|
||||||
issuer: "https://github.com/"
|
issuer: "https://github.com/"
|
||||||
client_id: "your-client-id" # TO BE FILLED
|
client_id: "your-client-id" # TO BE FILLED
|
||||||
|
@ -250,6 +251,7 @@ oidc_providers:
|
||||||
oidc_providers:
|
oidc_providers:
|
||||||
- idp_id: google
|
- idp_id: google
|
||||||
idp_name: Google
|
idp_name: Google
|
||||||
|
idp_brand: "org.matrix.google" # optional: styling hint for clients
|
||||||
issuer: "https://accounts.google.com/"
|
issuer: "https://accounts.google.com/"
|
||||||
client_id: "your-client-id" # TO BE FILLED
|
client_id: "your-client-id" # TO BE FILLED
|
||||||
client_secret: "your-client-secret" # TO BE FILLED
|
client_secret: "your-client-secret" # TO BE FILLED
|
||||||
|
@ -296,6 +298,7 @@ Synapse config:
|
||||||
oidc_providers:
|
oidc_providers:
|
||||||
- idp_id: gitlab
|
- idp_id: gitlab
|
||||||
idp_name: Gitlab
|
idp_name: Gitlab
|
||||||
|
idp_brand: "org.matrix.gitlab" # optional: styling hint for clients
|
||||||
issuer: "https://gitlab.com/"
|
issuer: "https://gitlab.com/"
|
||||||
client_id: "your-client-id" # TO BE FILLED
|
client_id: "your-client-id" # TO BE FILLED
|
||||||
client_secret: "your-client-secret" # TO BE FILLED
|
client_secret: "your-client-secret" # TO BE FILLED
|
||||||
|
|
|
@ -1731,10 +1731,14 @@ saml2_config:
|
||||||
# offer the user a choice of login mechanisms.
|
# offer the user a choice of login mechanisms.
|
||||||
#
|
#
|
||||||
# idp_icon: An optional icon for this identity provider, which is presented
|
# idp_icon: An optional icon for this identity provider, which is presented
|
||||||
# by identity picker pages. If given, must be an MXC URI of the format
|
# by clients and Synapse's own IdP picker page. If given, must be an
|
||||||
# mxc://<server-name>/<media-id>. (An easy way to obtain such an MXC URI
|
# MXC URI of the format mxc://<server-name>/<media-id>. (An easy way to
|
||||||
# is to upload an image to an (unencrypted) room and then copy the "url"
|
# obtain such an MXC URI is to upload an image to an (unencrypted) room
|
||||||
# from the source of the event.)
|
# and then copy the "url" from the source of the event.)
|
||||||
|
#
|
||||||
|
# idp_brand: An optional brand for this identity provider, allowing clients
|
||||||
|
# to style the login flow according to the identity provider in question.
|
||||||
|
# See the spec for possible options here.
|
||||||
#
|
#
|
||||||
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
|
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
|
||||||
# to discover endpoints. Defaults to true.
|
# to discover endpoints. Defaults to true.
|
||||||
|
@ -1795,9 +1799,9 @@ saml2_config:
|
||||||
#
|
#
|
||||||
# For the default provider, the following settings are available:
|
# For the default provider, the following settings are available:
|
||||||
#
|
#
|
||||||
# sub: name of the claim containing a unique identifier for the
|
# subject_claim: name of the claim containing a unique identifier
|
||||||
# user. Defaults to 'sub', which OpenID Connect compliant
|
# for the user. Defaults to 'sub', which OpenID Connect
|
||||||
# providers should provide.
|
# compliant providers should provide.
|
||||||
#
|
#
|
||||||
# localpart_template: Jinja2 template for the localpart of the MXID.
|
# localpart_template: Jinja2 template for the localpart of the MXID.
|
||||||
# If this is not set, the user will be prompted to choose their
|
# If this is not set, the user will be prompted to choose their
|
||||||
|
@ -1806,6 +1810,9 @@ saml2_config:
|
||||||
# display_name_template: Jinja2 template for the display name to set
|
# display_name_template: Jinja2 template for the display name to set
|
||||||
# on first login. If unset, no displayname will be set.
|
# on first login. If unset, no displayname will be set.
|
||||||
#
|
#
|
||||||
|
# email_template: Jinja2 template for the email address of the user.
|
||||||
|
# If unset, no email address will be added to the account.
|
||||||
|
#
|
||||||
# extra_attributes: a map of Jinja2 templates for extra attributes
|
# extra_attributes: a map of Jinja2 templates for extra attributes
|
||||||
# to send back to the client during login.
|
# to send back to the client during login.
|
||||||
# Note that these are non-standard and clients will ignore them
|
# Note that these are non-standard and clients will ignore them
|
||||||
|
@ -1841,6 +1848,12 @@ oidc_providers:
|
||||||
# userinfo_endpoint: "https://accounts.example.com/userinfo"
|
# userinfo_endpoint: "https://accounts.example.com/userinfo"
|
||||||
# jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
|
# jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
|
||||||
# skip_verification: true
|
# skip_verification: true
|
||||||
|
# user_mapping_provider:
|
||||||
|
# config:
|
||||||
|
# subject_claim: "id"
|
||||||
|
# localpart_template: "{ user.login }"
|
||||||
|
# display_name_template: "{ user.name }"
|
||||||
|
# email_template: "{ user.email }"
|
||||||
|
|
||||||
# For use with Keycloak
|
# For use with Keycloak
|
||||||
#
|
#
|
||||||
|
@ -1855,6 +1868,7 @@ oidc_providers:
|
||||||
#
|
#
|
||||||
#- idp_id: github
|
#- idp_id: github
|
||||||
# idp_name: Github
|
# idp_name: Github
|
||||||
|
# idp_brand: org.matrix.github
|
||||||
# discover: false
|
# discover: false
|
||||||
# issuer: "https://github.com/"
|
# issuer: "https://github.com/"
|
||||||
# client_id: "your-client-id" # TO BE FILLED
|
# client_id: "your-client-id" # TO BE FILLED
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import string
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import Iterable, Optional, Tuple, Type
|
from typing import Iterable, Optional, Tuple, Type
|
||||||
|
|
||||||
|
@ -78,10 +77,14 @@ class OIDCConfig(Config):
|
||||||
# offer the user a choice of login mechanisms.
|
# offer the user a choice of login mechanisms.
|
||||||
#
|
#
|
||||||
# idp_icon: An optional icon for this identity provider, which is presented
|
# idp_icon: An optional icon for this identity provider, which is presented
|
||||||
# by identity picker pages. If given, must be an MXC URI of the format
|
# by clients and Synapse's own IdP picker page. If given, must be an
|
||||||
# mxc://<server-name>/<media-id>. (An easy way to obtain such an MXC URI
|
# MXC URI of the format mxc://<server-name>/<media-id>. (An easy way to
|
||||||
# is to upload an image to an (unencrypted) room and then copy the "url"
|
# obtain such an MXC URI is to upload an image to an (unencrypted) room
|
||||||
# from the source of the event.)
|
# and then copy the "url" from the source of the event.)
|
||||||
|
#
|
||||||
|
# idp_brand: An optional brand for this identity provider, allowing clients
|
||||||
|
# to style the login flow according to the identity provider in question.
|
||||||
|
# See the spec for possible options here.
|
||||||
#
|
#
|
||||||
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
|
# discover: set to 'false' to disable the use of the OIDC discovery mechanism
|
||||||
# to discover endpoints. Defaults to true.
|
# to discover endpoints. Defaults to true.
|
||||||
|
@ -142,9 +145,9 @@ class OIDCConfig(Config):
|
||||||
#
|
#
|
||||||
# For the default provider, the following settings are available:
|
# For the default provider, the following settings are available:
|
||||||
#
|
#
|
||||||
# sub: name of the claim containing a unique identifier for the
|
# subject_claim: name of the claim containing a unique identifier
|
||||||
# user. Defaults to 'sub', which OpenID Connect compliant
|
# for the user. Defaults to 'sub', which OpenID Connect
|
||||||
# providers should provide.
|
# compliant providers should provide.
|
||||||
#
|
#
|
||||||
# localpart_template: Jinja2 template for the localpart of the MXID.
|
# localpart_template: Jinja2 template for the localpart of the MXID.
|
||||||
# If this is not set, the user will be prompted to choose their
|
# If this is not set, the user will be prompted to choose their
|
||||||
|
@ -153,6 +156,9 @@ class OIDCConfig(Config):
|
||||||
# display_name_template: Jinja2 template for the display name to set
|
# display_name_template: Jinja2 template for the display name to set
|
||||||
# on first login. If unset, no displayname will be set.
|
# on first login. If unset, no displayname will be set.
|
||||||
#
|
#
|
||||||
|
# email_template: Jinja2 template for the email address of the user.
|
||||||
|
# If unset, no email address will be added to the account.
|
||||||
|
#
|
||||||
# extra_attributes: a map of Jinja2 templates for extra attributes
|
# extra_attributes: a map of Jinja2 templates for extra attributes
|
||||||
# to send back to the client during login.
|
# to send back to the client during login.
|
||||||
# Note that these are non-standard and clients will ignore them
|
# Note that these are non-standard and clients will ignore them
|
||||||
|
@ -188,6 +194,12 @@ class OIDCConfig(Config):
|
||||||
# userinfo_endpoint: "https://accounts.example.com/userinfo"
|
# userinfo_endpoint: "https://accounts.example.com/userinfo"
|
||||||
# jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
|
# jwks_uri: "https://accounts.example.com/.well-known/jwks.json"
|
||||||
# skip_verification: true
|
# skip_verification: true
|
||||||
|
# user_mapping_provider:
|
||||||
|
# config:
|
||||||
|
# subject_claim: "id"
|
||||||
|
# localpart_template: "{{ user.login }}"
|
||||||
|
# display_name_template: "{{ user.name }}"
|
||||||
|
# email_template: "{{ user.email }}"
|
||||||
|
|
||||||
# For use with Keycloak
|
# For use with Keycloak
|
||||||
#
|
#
|
||||||
|
@ -202,6 +214,7 @@ class OIDCConfig(Config):
|
||||||
#
|
#
|
||||||
#- idp_id: github
|
#- idp_id: github
|
||||||
# idp_name: Github
|
# idp_name: Github
|
||||||
|
# idp_brand: org.matrix.github
|
||||||
# discover: false
|
# discover: false
|
||||||
# issuer: "https://github.com/"
|
# issuer: "https://github.com/"
|
||||||
# client_id: "your-client-id" # TO BE FILLED
|
# client_id: "your-client-id" # TO BE FILLED
|
||||||
|
@ -225,11 +238,22 @@ OIDC_PROVIDER_CONFIG_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["issuer", "client_id", "client_secret"],
|
"required": ["issuer", "client_id", "client_secret"],
|
||||||
"properties": {
|
"properties": {
|
||||||
# TODO: fix the maxLength here depending on what MSC2528 decides
|
"idp_id": {
|
||||||
# remember that we prefix the ID given here with `oidc-`
|
"type": "string",
|
||||||
"idp_id": {"type": "string", "minLength": 1, "maxLength": 128},
|
"minLength": 1,
|
||||||
|
# MSC2858 allows a maxlen of 255, but we prefix with "oidc-"
|
||||||
|
"maxLength": 250,
|
||||||
|
"pattern": "^[A-Za-z0-9._~-]+$",
|
||||||
|
},
|
||||||
"idp_name": {"type": "string"},
|
"idp_name": {"type": "string"},
|
||||||
"idp_icon": {"type": "string"},
|
"idp_icon": {"type": "string"},
|
||||||
|
"idp_brand": {
|
||||||
|
"type": "string",
|
||||||
|
# MSC2758-style namespaced identifier
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 255,
|
||||||
|
"pattern": "^[a-z][a-z0-9_.-]*$",
|
||||||
|
},
|
||||||
"discover": {"type": "boolean"},
|
"discover": {"type": "boolean"},
|
||||||
"issuer": {"type": "string"},
|
"issuer": {"type": "string"},
|
||||||
"client_id": {"type": "string"},
|
"client_id": {"type": "string"},
|
||||||
|
@ -348,25 +372,8 @@ def _parse_oidc_config_dict(
|
||||||
config_path + ("user_mapping_provider", "module"),
|
config_path + ("user_mapping_provider", "module"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# MSC2858 will apply certain limits in what can be used as an IdP id, so let's
|
|
||||||
# enforce those limits now.
|
|
||||||
# TODO: factor out this stuff to a generic function
|
|
||||||
idp_id = oidc_config.get("idp_id", "oidc")
|
idp_id = oidc_config.get("idp_id", "oidc")
|
||||||
|
|
||||||
# TODO: update this validity check based on what MSC2858 decides.
|
|
||||||
valid_idp_chars = set(string.ascii_lowercase + string.digits + "-._")
|
|
||||||
|
|
||||||
if any(c not in valid_idp_chars for c in idp_id):
|
|
||||||
raise ConfigError(
|
|
||||||
'idp_id may only contain a-z, 0-9, "-", ".", "_"',
|
|
||||||
config_path + ("idp_id",),
|
|
||||||
)
|
|
||||||
|
|
||||||
if idp_id[0] not in string.ascii_lowercase:
|
|
||||||
raise ConfigError(
|
|
||||||
"idp_id must start with a-z", config_path + ("idp_id",),
|
|
||||||
)
|
|
||||||
|
|
||||||
# prefix the given IDP with a prefix specific to the SSO mechanism, to avoid
|
# prefix the given IDP with a prefix specific to the SSO mechanism, to avoid
|
||||||
# clashes with other mechs (such as SAML, CAS).
|
# clashes with other mechs (such as SAML, CAS).
|
||||||
#
|
#
|
||||||
|
@ -392,6 +399,7 @@ def _parse_oidc_config_dict(
|
||||||
idp_id=idp_id,
|
idp_id=idp_id,
|
||||||
idp_name=oidc_config.get("idp_name", "OIDC"),
|
idp_name=oidc_config.get("idp_name", "OIDC"),
|
||||||
idp_icon=idp_icon,
|
idp_icon=idp_icon,
|
||||||
|
idp_brand=oidc_config.get("idp_brand"),
|
||||||
discover=oidc_config.get("discover", True),
|
discover=oidc_config.get("discover", True),
|
||||||
issuer=oidc_config["issuer"],
|
issuer=oidc_config["issuer"],
|
||||||
client_id=oidc_config["client_id"],
|
client_id=oidc_config["client_id"],
|
||||||
|
@ -422,6 +430,9 @@ class OidcProviderConfig:
|
||||||
# Optional MXC URI for icon for this IdP.
|
# Optional MXC URI for icon for this IdP.
|
||||||
idp_icon = attr.ib(type=Optional[str])
|
idp_icon = attr.ib(type=Optional[str])
|
||||||
|
|
||||||
|
# Optional brand identifier for this IdP.
|
||||||
|
idp_brand = attr.ib(type=Optional[str])
|
||||||
|
|
||||||
# whether the OIDC discovery mechanism is used to discover endpoints
|
# whether the OIDC discovery mechanism is used to discover endpoints
|
||||||
discover = attr.ib(type=bool)
|
discover = attr.ib(type=bool)
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,10 @@ class CasHandler:
|
||||||
# user-facing name of this auth provider
|
# user-facing name of this auth provider
|
||||||
self.idp_name = "CAS"
|
self.idp_name = "CAS"
|
||||||
|
|
||||||
# we do not currently support icons for CAS auth, but this is required by
|
# we do not currently support brands/icons for CAS auth, but this is required by
|
||||||
# the SsoIdentityProvider protocol type.
|
# the SsoIdentityProvider protocol type.
|
||||||
self.idp_icon = None
|
self.idp_icon = None
|
||||||
|
self.idp_brand = None
|
||||||
|
|
||||||
self._sso_handler = hs.get_sso_handler()
|
self._sso_handler = hs.get_sso_handler()
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,9 @@ class OidcProvider:
|
||||||
# MXC URI for icon for this auth provider
|
# MXC URI for icon for this auth provider
|
||||||
self.idp_icon = provider.idp_icon
|
self.idp_icon = provider.idp_icon
|
||||||
|
|
||||||
|
# optional brand identifier for this auth provider
|
||||||
|
self.idp_brand = provider.idp_brand
|
||||||
|
|
||||||
self._sso_handler = hs.get_sso_handler()
|
self._sso_handler = hs.get_sso_handler()
|
||||||
|
|
||||||
self._sso_handler.register_identity_provider(self)
|
self._sso_handler.register_identity_provider(self)
|
||||||
|
@ -1056,7 +1059,8 @@ class OidcSessionData:
|
||||||
|
|
||||||
|
|
||||||
UserAttributeDict = TypedDict(
|
UserAttributeDict = TypedDict(
|
||||||
"UserAttributeDict", {"localpart": Optional[str], "display_name": Optional[str]}
|
"UserAttributeDict",
|
||||||
|
{"localpart": Optional[str], "display_name": Optional[str], "emails": List[str]},
|
||||||
)
|
)
|
||||||
C = TypeVar("C")
|
C = TypeVar("C")
|
||||||
|
|
||||||
|
@ -1135,11 +1139,12 @@ def jinja_finalize(thing):
|
||||||
env = Environment(finalize=jinja_finalize)
|
env = Environment(finalize=jinja_finalize)
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s(slots=True, frozen=True)
|
||||||
class JinjaOidcMappingConfig:
|
class JinjaOidcMappingConfig:
|
||||||
subject_claim = attr.ib(type=str)
|
subject_claim = attr.ib(type=str)
|
||||||
localpart_template = attr.ib(type=Optional[Template])
|
localpart_template = attr.ib(type=Optional[Template])
|
||||||
display_name_template = attr.ib(type=Optional[Template])
|
display_name_template = attr.ib(type=Optional[Template])
|
||||||
|
email_template = attr.ib(type=Optional[Template])
|
||||||
extra_attributes = attr.ib(type=Dict[str, Template])
|
extra_attributes = attr.ib(type=Dict[str, Template])
|
||||||
|
|
||||||
|
|
||||||
|
@ -1156,23 +1161,17 @@ class JinjaOidcMappingProvider(OidcMappingProvider[JinjaOidcMappingConfig]):
|
||||||
def parse_config(config: dict) -> JinjaOidcMappingConfig:
|
def parse_config(config: dict) -> JinjaOidcMappingConfig:
|
||||||
subject_claim = config.get("subject_claim", "sub")
|
subject_claim = config.get("subject_claim", "sub")
|
||||||
|
|
||||||
localpart_template = None # type: Optional[Template]
|
def parse_template_config(option_name: str) -> Optional[Template]:
|
||||||
if "localpart_template" in config:
|
if option_name not in config:
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
localpart_template = env.from_string(config["localpart_template"])
|
return env.from_string(config[option_name])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ConfigError(
|
raise ConfigError("invalid jinja template", path=[option_name]) from e
|
||||||
"invalid jinja template", path=["localpart_template"]
|
|
||||||
) from e
|
|
||||||
|
|
||||||
display_name_template = None # type: Optional[Template]
|
localpart_template = parse_template_config("localpart_template")
|
||||||
if "display_name_template" in config:
|
display_name_template = parse_template_config("display_name_template")
|
||||||
try:
|
email_template = parse_template_config("email_template")
|
||||||
display_name_template = env.from_string(config["display_name_template"])
|
|
||||||
except Exception as e:
|
|
||||||
raise ConfigError(
|
|
||||||
"invalid jinja template", path=["display_name_template"]
|
|
||||||
) from e
|
|
||||||
|
|
||||||
extra_attributes = {} # type Dict[str, Template]
|
extra_attributes = {} # type Dict[str, Template]
|
||||||
if "extra_attributes" in config:
|
if "extra_attributes" in config:
|
||||||
|
@ -1192,6 +1191,7 @@ class JinjaOidcMappingProvider(OidcMappingProvider[JinjaOidcMappingConfig]):
|
||||||
subject_claim=subject_claim,
|
subject_claim=subject_claim,
|
||||||
localpart_template=localpart_template,
|
localpart_template=localpart_template,
|
||||||
display_name_template=display_name_template,
|
display_name_template=display_name_template,
|
||||||
|
email_template=email_template,
|
||||||
extra_attributes=extra_attributes,
|
extra_attributes=extra_attributes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1213,16 +1213,23 @@ class JinjaOidcMappingProvider(OidcMappingProvider[JinjaOidcMappingConfig]):
|
||||||
# a usable mxid.
|
# a usable mxid.
|
||||||
localpart += str(failures) if failures else ""
|
localpart += str(failures) if failures else ""
|
||||||
|
|
||||||
display_name = None # type: Optional[str]
|
def render_template_field(template: Optional[Template]) -> Optional[str]:
|
||||||
if self._config.display_name_template is not None:
|
if template is None:
|
||||||
display_name = self._config.display_name_template.render(
|
return None
|
||||||
user=userinfo
|
return template.render(user=userinfo).strip()
|
||||||
).strip()
|
|
||||||
|
|
||||||
if display_name == "":
|
display_name = render_template_field(self._config.display_name_template)
|
||||||
display_name = None
|
if display_name == "":
|
||||||
|
display_name = None
|
||||||
|
|
||||||
return UserAttributeDict(localpart=localpart, display_name=display_name)
|
emails = [] # type: List[str]
|
||||||
|
email = render_template_field(self._config.email_template)
|
||||||
|
if email:
|
||||||
|
emails.append(email)
|
||||||
|
|
||||||
|
return UserAttributeDict(
|
||||||
|
localpart=localpart, display_name=display_name, emails=emails
|
||||||
|
)
|
||||||
|
|
||||||
async def get_extra_attributes(self, userinfo: UserInfo, token: Token) -> JsonDict:
|
async def get_extra_attributes(self, userinfo: UserInfo, token: Token) -> JsonDict:
|
||||||
extras = {} # type: Dict[str, str]
|
extras = {} # type: Dict[str, str]
|
||||||
|
|
|
@ -78,9 +78,10 @@ class SamlHandler(BaseHandler):
|
||||||
# user-facing name of this auth provider
|
# user-facing name of this auth provider
|
||||||
self.idp_name = "SAML"
|
self.idp_name = "SAML"
|
||||||
|
|
||||||
# we do not currently support icons for SAML auth, but this is required by
|
# we do not currently support icons/brands for SAML auth, but this is required by
|
||||||
# the SsoIdentityProvider protocol type.
|
# the SsoIdentityProvider protocol type.
|
||||||
self.idp_icon = None
|
self.idp_icon = None
|
||||||
|
self.idp_brand = None
|
||||||
|
|
||||||
# a map from saml session id to Saml2SessionData object
|
# a map from saml session id to Saml2SessionData object
|
||||||
self._outstanding_requests_dict = {} # type: Dict[str, Saml2SessionData]
|
self._outstanding_requests_dict = {} # type: Dict[str, Saml2SessionData]
|
||||||
|
|
|
@ -80,6 +80,11 @@ class SsoIdentityProvider(Protocol):
|
||||||
"""Optional MXC URI for user-facing icon"""
|
"""Optional MXC URI for user-facing icon"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def idp_brand(self) -> Optional[str]:
|
||||||
|
"""Optional branding identifier"""
|
||||||
|
return None
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
async def handle_redirect_request(
|
async def handle_redirect_request(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -333,6 +333,8 @@ def _get_auth_flow_dict_for_idp(idp: SsoIdentityProvider) -> JsonDict:
|
||||||
e = {"id": idp.idp_id, "name": idp.idp_name} # type: JsonDict
|
e = {"id": idp.idp_id, "name": idp.idp_name} # type: JsonDict
|
||||||
if idp.idp_icon:
|
if idp.idp_icon:
|
||||||
e["icon"] = idp.idp_icon
|
e["icon"] = idp.idp_icon
|
||||||
|
if idp.idp_brand:
|
||||||
|
e["brand"] = idp.idp_brand
|
||||||
return e
|
return e
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue