def get_access_token_from_request(request: Request): """Extracts the access_token from the request. Args: request: The http request. Returns: unicode: The access_token Raises: MissingClientTokenError: If there isn't a single access_token in the request """ auth_headers = request.requestHeaders.getRawHeaders(b"Authorization") query_params = request.args.get(b"access_token") if auth_headers: # Try the get the access_token from a "Authorization: Bearer" # header if query_params is not None: raise MissingClientTokenError( "Mixing Authorization headers and access_token query parameters." ) if len(auth_headers) > 1: raise MissingClientTokenError( "Too many Authorization headers.") parts = auth_headers[0].split(b" ") if parts[0] == b"Bearer" and len(parts) == 2: return parts[1].decode("ascii") else: raise MissingClientTokenError("Invalid Authorization header.") else: # Try to get the access_token from the query params. if not query_params: raise MissingClientTokenError() return query_params[0].decode("ascii")
async def get_user_by_req( self, request: SynapseRequest, allow_guest: bool = False, rights: str = "access", allow_expired: bool = False, ) -> Requester: """Get a registered user's ID. Args: request: An HTTP request with an access_token query parameter. allow_guest: If False, will raise an AuthError if the user making the request is a guest. rights: The operation being performed; the access token must allow this allow_expired: If True, allow the request through even if the account is expired, or session token lifetime has ended. Note that /login will deliver access tokens regardless of expiration. Returns: Resolves to the requester Raises: InvalidClientCredentialsError if no user by that token exists or the token is invalid. AuthError if access is denied for the user in the access token """ try: ip_addr = request.getClientIP() user_agent = get_request_user_agent(request) access_token = self.get_access_token_from_request(request) user_id, app_service = await self._get_appservice_user_id(request) if user_id and app_service: if ip_addr and self._track_appservice_user_ips: await self.store.insert_client_ip( user_id=user_id, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id="dummy-device", # stubbed ) requester = create_requester(user_id, app_service=app_service) request.requester = user_id if user_id in self._force_tracing_for_users: opentracing.set_tag(opentracing.tags.SAMPLING_PRIORITY, 1) opentracing.set_tag("authenticated_entity", user_id) opentracing.set_tag("user_id", user_id) opentracing.set_tag("appservice_id", app_service.id) return requester user_info = await self.get_user_by_access_token( access_token, rights, allow_expired=allow_expired) token_id = user_info.token_id is_guest = user_info.is_guest shadow_banned = user_info.shadow_banned # Deny the request if the user account has expired. if self._account_validity_enabled and not allow_expired: if await self.store.is_account_expired(user_info.user_id, self.clock.time_msec()): raise AuthError(403, "User account has expired", errcode=Codes.EXPIRED_ACCOUNT) device_id = user_info.device_id if access_token and ip_addr: await self.store.insert_client_ip( user_id=user_info.token_owner, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id=device_id, ) if is_guest and not allow_guest: raise AuthError( 403, "Guest access not allowed", errcode=Codes.GUEST_ACCESS_FORBIDDEN, ) requester = create_requester( user_info.user_id, token_id, is_guest, shadow_banned, device_id, app_service=app_service, authenticated_entity=user_info.token_owner, ) request.requester = requester if user_info.token_owner in self._force_tracing_for_users: opentracing.set_tag(opentracing.tags.SAMPLING_PRIORITY, 1) opentracing.set_tag("authenticated_entity", user_info.token_owner) opentracing.set_tag("user_id", user_info.user_id) if device_id: opentracing.set_tag("device_id", device_id) return requester except KeyError: raise MissingClientTokenError()
async def _wrapped_get_user_by_req( self, request: SynapseRequest, allow_guest: bool, allow_expired: bool, ) -> Requester: """Helper for get_user_by_req Once get_user_by_req has set up the opentracing span, this does the actual work. """ try: ip_addr = request.getClientAddress().host user_agent = get_request_user_agent(request) access_token = self.get_access_token_from_request(request) ( user_id, device_id, app_service, ) = await self._get_appservice_user_id_and_device_id(request) if user_id and app_service: if ip_addr and self._track_appservice_user_ips: await self.store.insert_client_ip( user_id=user_id, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id="dummy-device" if device_id is None else device_id, # stubbed ) requester = create_requester(user_id, app_service=app_service, device_id=device_id) request.requester = user_id return requester user_info = await self.get_user_by_access_token( access_token, allow_expired=allow_expired) token_id = user_info.token_id is_guest = user_info.is_guest shadow_banned = user_info.shadow_banned # Deny the request if the user account has expired. if not allow_expired: if await self._account_validity_handler.is_user_expired( user_info.user_id): # Raise the error if either an account validity module has determined # the account has expired, or the legacy account validity # implementation is enabled and determined the account has expired raise AuthError( 403, "User account has expired", errcode=Codes.EXPIRED_ACCOUNT, ) device_id = user_info.device_id if access_token and ip_addr: await self.store.insert_client_ip( user_id=user_info.token_owner, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id=device_id, ) # Track also the puppeted user client IP if enabled and the user is puppeting if (user_info.user_id != user_info.token_owner and self._track_puppeted_user_ips): await self.store.insert_client_ip( user_id=user_info.user_id, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id=device_id, ) if is_guest and not allow_guest: raise AuthError( 403, "Guest access not allowed", errcode=Codes.GUEST_ACCESS_FORBIDDEN, ) # Mark the token as used. This is used to invalidate old refresh # tokens after some time. if not user_info.token_used and token_id is not None: await self.store.mark_access_token_as_used(token_id) requester = create_requester( user_info.user_id, token_id, is_guest, shadow_banned, device_id, app_service=app_service, authenticated_entity=user_info.token_owner, ) request.requester = requester return requester except KeyError: raise MissingClientTokenError()
def get_user_by_req( self, request: Request, allow_guest: bool = False, rights: str = "access", allow_expired: bool = False, ): """ Get a registered user's ID. Args: request: An HTTP request with an access_token query parameter. allow_guest: If False, will raise an AuthError if the user making the request is a guest. rights: The operation being performed; the access token must allow this allow_expired: If True, allow the request through even if the account is expired, or session token lifetime has ended. Note that /login will deliver access tokens regardless of expiration. Returns: defer.Deferred: resolves to a `synapse.types.Requester` object Raises: InvalidClientCredentialsError if no user by that token exists or the token is invalid. AuthError if access is denied for the user in the access token """ try: ip_addr = self.hs.get_ip_from_request(request) user_agent = request.requestHeaders.getRawHeaders( b"User-Agent", default=[b""])[0].decode("ascii", "surrogateescape") access_token = self.get_access_token_from_request(request) user_id, app_service = yield self._get_appservice_user_id(request) if user_id: request.authenticated_entity = user_id opentracing.set_tag("authenticated_entity", user_id) opentracing.set_tag("appservice_id", app_service.id) if ip_addr and self._track_appservice_user_ips: yield self.store.insert_client_ip( user_id=user_id, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id="dummy-device", # stubbed ) return synapse.types.create_requester(user_id, app_service=app_service) user_info = yield self.get_user_by_access_token( access_token, rights, allow_expired=allow_expired) user = user_info["user"] token_id = user_info["token_id"] is_guest = user_info["is_guest"] # Deny the request if the user account has expired. if self._account_validity.enabled and not allow_expired: user_id = user.to_string() expiration_ts = yield self.store.get_expiration_ts_for_user( user_id) if (expiration_ts is not None and self.clock.time_msec() >= expiration_ts): raise AuthError(403, "User account has expired", errcode=Codes.EXPIRED_ACCOUNT) # device_id may not be present if get_user_by_access_token has been # stubbed out. device_id = user_info.get("device_id") if user and access_token and ip_addr: yield self.store.insert_client_ip( user_id=user.to_string(), access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id=device_id, ) if is_guest and not allow_guest: raise AuthError( 403, "Guest access not allowed", errcode=Codes.GUEST_ACCESS_FORBIDDEN, ) request.authenticated_entity = user.to_string() opentracing.set_tag("authenticated_entity", user.to_string()) if device_id: opentracing.set_tag("device_id", device_id) return synapse.types.create_requester(user, token_id, is_guest, device_id, app_service=app_service) except KeyError: raise MissingClientTokenError()
def get_user_by_req(self, request, allow_guest=False, rights="access", allow_expired=False): """ Get a registered user's ID. Args: request - An HTTP request with an access_token query parameter. allow_expired - Whether to allow the request through even if the account is expired. If true, Synapse will still require an access token to be provided but won't check if the account it belongs to has expired. This works thanks to /login delivering access tokens regardless of accounts' expiration. Returns: defer.Deferred: resolves to a ``synapse.types.Requester`` object Raises: InvalidClientCredentialsError if no user by that token exists or the token is invalid. AuthError if access is denied for the user in the access token """ try: ip_addr = self.hs.get_ip_from_request(request) user_agent = request.requestHeaders.getRawHeaders( b"User-Agent", default=[b""])[0].decode("ascii", "surrogateescape") access_token = self.get_access_token_from_request(request) user_id, app_service = yield self._get_appservice_user_id(request) if user_id: request.authenticated_entity = user_id if ip_addr and self.hs.config.track_appservice_user_ips: yield self.store.insert_client_ip( user_id=user_id, access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id="dummy-device", # stubbed ) defer.returnValue( synapse.types.create_requester(user_id, app_service=app_service)) user_info = yield self.get_user_by_access_token( access_token, rights) user = user_info["user"] token_id = user_info["token_id"] is_guest = user_info["is_guest"] # Deny the request if the user account has expired. if self._account_validity.enabled and not allow_expired: user_id = user.to_string() expiration_ts = yield self.store.get_expiration_ts_for_user( user_id) if (expiration_ts is not None and self.clock.time_msec() >= expiration_ts): raise AuthError(403, "User account has expired", errcode=Codes.EXPIRED_ACCOUNT) # device_id may not be present if get_user_by_access_token has been # stubbed out. device_id = user_info.get("device_id") if user and access_token and ip_addr: yield self.store.insert_client_ip( user_id=user.to_string(), access_token=access_token, ip=ip_addr, user_agent=user_agent, device_id=device_id, ) if is_guest and not allow_guest: raise AuthError( 403, "Guest access not allowed", errcode=Codes.GUEST_ACCESS_FORBIDDEN, ) request.authenticated_entity = user.to_string() defer.returnValue( synapse.types.create_requester(user, token_id, is_guest, device_id, app_service=app_service)) except KeyError: raise MissingClientTokenError()