Split federation OpenID userinfo endpoint out of the federation resource

This allows the OpenID userinfo endpoint to be active even if the
federation resource is not active. The OpenID userinfo endpoint
is called by integration managers to verify user actions using the
client API OpenID access token. Without this verification, the
integration manager cannot know that the access token is valid.

The OpenID userinfo endpoint will be loaded in the case that either
"federation" or "openid" resource is defined. The new "openid"
resource is defaulted to active in default configuration.

Signed-off-by: Jason Robinson <jasonr@matrix.org>
This commit is contained in:
Jason Robinson 2019-01-21 01:54:43 +02:00
parent 5336e49b39
commit 82e13662c0
4 changed files with 89 additions and 42 deletions

View File

@ -87,6 +87,13 @@ class FederationReaderServer(HomeServer):
resources.update({ resources.update({
FEDERATION_PREFIX: TransportLayerServer(self), FEDERATION_PREFIX: TransportLayerServer(self),
}) })
if name == "openid" and "federation" not in res["names"]:
# Only load the openid resource separately if federation resource
# is not specified since federation resource includes openid
# resource.
resources.update({
FEDERATION_PREFIX: TransportLayerServer(self, servlet_groups=["openid"]),
})
root_resource = create_resource_tree(resources, NoResource()) root_resource = create_resource_tree(resources, NoResource())

View File

@ -95,6 +95,10 @@ class SynapseHomeServer(HomeServer):
resources = {} resources = {}
for res in listener_config["resources"]: for res in listener_config["resources"]:
for name in res["names"]: for name in res["names"]:
if name == "openid" and "federation" in res["names"]:
# Skip loading openid resource if federation is defined
# since federation resource will include openid
continue
resources.update(self._configure_named_resource( resources.update(self._configure_named_resource(
name, res.get("compress", False), name, res.get("compress", False),
)) ))
@ -192,6 +196,11 @@ class SynapseHomeServer(HomeServer):
FEDERATION_PREFIX: TransportLayerServer(self), FEDERATION_PREFIX: TransportLayerServer(self),
}) })
if name == "openid":
resources.update({
FEDERATION_PREFIX: TransportLayerServer(self, servlet_groups=["openid"]),
})
if name in ["static", "client"]: if name in ["static", "client"]:
resources.update({ resources.update({
STATIC_PREFIX: File( STATIC_PREFIX: File(

View File

@ -151,7 +151,7 @@ class ServerConfig(Config):
"compress": gzip_responses, "compress": gzip_responses,
}, },
{ {
"names": ["federation"], "names": ["federation", "openid"],
"compress": False, "compress": False,
} }
] ]
@ -170,7 +170,7 @@ class ServerConfig(Config):
"compress": gzip_responses, "compress": gzip_responses,
}, },
{ {
"names": ["federation"], "names": ["federation", "openid"],
"compress": False, "compress": False,
} }
] ]
@ -328,7 +328,7 @@ class ServerConfig(Config):
# that can do automatic compression. # that can do automatic compression.
compress: true compress: true
- names: [federation] # Federation APIs - names: [federation, openid] # Federation APIs
compress: false compress: false
# optional list of additional endpoints which can be loaded via # optional list of additional endpoints which can be loaded via
@ -350,7 +350,7 @@ class ServerConfig(Config):
resources: resources:
- names: [client] - names: [client]
compress: true compress: true
- names: [federation] - names: [federation, openid]
compress: false compress: false
# Turn on the twisted ssh manhole service on localhost on the given # Turn on the twisted ssh manhole service on localhost on the given
@ -477,6 +477,7 @@ KNOWN_RESOURCES = (
'keys', 'keys',
'media', 'media',
'metrics', 'metrics',
'openid',
'replication', 'replication',
'static', 'static',
'webclient', 'webclient',

View File

@ -43,9 +43,10 @@ logger = logging.getLogger(__name__)
class TransportLayerServer(JsonResource): class TransportLayerServer(JsonResource):
"""Handles incoming federation HTTP requests""" """Handles incoming federation HTTP requests"""
def __init__(self, hs): def __init__(self, hs, servlet_groups=None):
self.hs = hs self.hs = hs
self.clock = hs.get_clock() self.clock = hs.get_clock()
self.servlet_groups = servlet_groups
super(TransportLayerServer, self).__init__(hs, canonical_json=False) super(TransportLayerServer, self).__init__(hs, canonical_json=False)
@ -67,6 +68,7 @@ class TransportLayerServer(JsonResource):
resource=self, resource=self,
ratelimiter=self.ratelimiter, ratelimiter=self.ratelimiter,
authenticator=self.authenticator, authenticator=self.authenticator,
servlet_groups=self.servlet_groups,
) )
@ -1308,10 +1310,12 @@ FEDERATION_SERVLET_CLASSES = (
FederationClientKeysClaimServlet, FederationClientKeysClaimServlet,
FederationThirdPartyInviteExchangeServlet, FederationThirdPartyInviteExchangeServlet,
On3pidBindServlet, On3pidBindServlet,
OpenIdUserInfo,
FederationVersionServlet, FederationVersionServlet,
) )
OPENID_SERVLET_CLASSES = (
OpenIdUserInfo,
)
ROOM_LIST_CLASSES = ( ROOM_LIST_CLASSES = (
PublicRoomList, PublicRoomList,
@ -1350,44 +1354,70 @@ GROUP_ATTESTATION_SERVLET_CLASSES = (
FederationGroupsRenewAttestaionServlet, FederationGroupsRenewAttestaionServlet,
) )
DEFAULT_SERVLET_GROUPS = (
"federation",
"room_list",
"group_server",
"group_local",
"group_attestation",
"openid",
)
def register_servlets(hs, resource, authenticator, ratelimiter):
for servletclass in FEDERATION_SERVLET_CLASSES:
servletclass(
handler=hs.get_federation_server(),
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)
for servletclass in ROOM_LIST_CLASSES: def register_servlets(hs, resource, authenticator, ratelimiter, servlet_groups=None):
servletclass( if not servlet_groups:
handler=hs.get_room_list_handler(), servlet_groups = DEFAULT_SERVLET_GROUPS
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)
for servletclass in GROUP_SERVER_SERVLET_CLASSES: if "federation" in servlet_groups:
servletclass( for servletclass in FEDERATION_SERVLET_CLASSES:
handler=hs.get_groups_server_handler(), servletclass(
authenticator=authenticator, handler=hs.get_federation_server(),
ratelimiter=ratelimiter, authenticator=authenticator,
server_name=hs.hostname, ratelimiter=ratelimiter,
).register(resource) server_name=hs.hostname,
).register(resource)
for servletclass in GROUP_LOCAL_SERVLET_CLASSES: if "openid" in servlet_groups:
servletclass( for servletclass in OPENID_SERVLET_CLASSES:
handler=hs.get_groups_local_handler(), servletclass(
authenticator=authenticator, handler=hs.get_federation_server(),
ratelimiter=ratelimiter, authenticator=authenticator,
server_name=hs.hostname, ratelimiter=ratelimiter,
).register(resource) server_name=hs.hostname,
).register(resource)
for servletclass in GROUP_ATTESTATION_SERVLET_CLASSES: if "room_list" in servlet_groups:
servletclass( for servletclass in ROOM_LIST_CLASSES:
handler=hs.get_groups_attestation_renewer(), servletclass(
authenticator=authenticator, handler=hs.get_room_list_handler(),
ratelimiter=ratelimiter, authenticator=authenticator,
server_name=hs.hostname, ratelimiter=ratelimiter,
).register(resource) server_name=hs.hostname,
).register(resource)
if "group_server" in servlet_groups:
for servletclass in GROUP_SERVER_SERVLET_CLASSES:
servletclass(
handler=hs.get_groups_server_handler(),
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)
if "group_local" in servlet_groups:
for servletclass in GROUP_LOCAL_SERVLET_CLASSES:
servletclass(
handler=hs.get_groups_local_handler(),
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)
if "group_attestation" in servlet_groups:
for servletclass in GROUP_ATTESTATION_SERVLET_CLASSES:
servletclass(
handler=hs.get_groups_attestation_renewer(),
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)