MSC2967: Check access token scope for use as user and add guest support

This commit is contained in:
Hugh Nimmo-Smith 2022-11-16 11:05:05 +00:00 committed by Patrick Cloke
parent d20669971a
commit a1374b5c70

View File

@ -25,7 +25,7 @@ from twisted.web.client import readBody
from twisted.web.http_headers import Headers from twisted.web.http_headers import Headers
from synapse.api.auth.base import BaseAuth from synapse.api.auth.base import BaseAuth
from synapse.api.errors import AuthError, StoreError from synapse.api.errors import AuthError, InvalidClientTokenError, StoreError
from synapse.http.site import SynapseRequest from synapse.http.site import SynapseRequest
from synapse.logging.context import make_deferred_yieldable from synapse.logging.context import make_deferred_yieldable
from synapse.types import Requester, UserID, create_requester from synapse.types import Requester, UserID, create_requester
@ -164,18 +164,29 @@ class OAuthDelegatedAuth(BaseAuth):
logger.info(f"Introspection result: {introspection_result!r}") logger.info(f"Introspection result: {introspection_result!r}")
# TODO: introspection verification should be more extensive, especially: # TODO: introspection verification should be more extensive, especially:
# - verify the scopes
# - verify the audience # - verify the audience
if not introspection_result.get("active"): if not introspection_result.get("active"):
raise AuthError( raise InvalidClientTokenError("Token is not active")
403,
"Invalid access token", # Let's look at the scope
) scope: List[str] = scope_to_list(introspection_result.get("scope", ""))
# Determine type of user based on presence of particular scopes
has_admin_scope = "urn:synapse:admin:*" in scope
has_user_scope = "urn:matrix:org.matrix.msc2967.client:api:*" in scope
has_guest_scope = "urn:matrix:org.matrix.msc2967.client:api:guest" in scope
is_user = has_user_scope or has_admin_scope
is_guest = has_guest_scope and not is_user
if not is_user and not is_guest:
raise InvalidClientTokenError("No scope in token granting user rights")
# Match via the sub claim # Match via the sub claim
sub: Optional[str] = introspection_result.get("sub") sub: Optional[str] = introspection_result.get("sub")
if sub is None: if sub is None:
raise AuthError(500, "Invalid sub claim in the introspection result") raise InvalidClientTokenError(
"Invalid sub claim in the introspection result"
)
user_id_str = await self.store.get_user_by_external_id( user_id_str = await self.store.get_user_by_external_id(
OAuthDelegatedAuth.EXTERNAL_ID_PROVIDER, sub OAuthDelegatedAuth.EXTERNAL_ID_PROVIDER, sub
@ -216,10 +227,8 @@ class OAuthDelegatedAuth(BaseAuth):
else: else:
user_id = UserID.from_string(user_id_str) user_id = UserID.from_string(user_id_str)
# Let's look at the scope
scope: List[str] = scope_to_list(introspection_result.get("scope", ""))
device_id = None
# Find device_id in scope # Find device_id in scope
device_id = None
for tok in scope: for tok in scope:
if tok.startswith("urn:matrix:org.matrix.msc2967.client:device:"): if tok.startswith("urn:matrix:org.matrix.msc2967.client:device:"):
parts = tok.split(":") parts = tok.split(":")
@ -250,4 +259,5 @@ class OAuthDelegatedAuth(BaseAuth):
user_id=user_id, user_id=user_id,
device_id=device_id, device_id=device_id,
scope=scope, scope=scope,
is_guest=is_guest,
) )