def login_with_token(client: GMatrixClient, user_id: str, access_token: str) -> Optional[User]: """Reuse an existing authentication code. If this succeeds it means the user has logged in the past, so we assume the display name is properly set and that there may be rooms open from past executions. """ client.set_access_token(user_id=user_id, token=access_token) try: # Test the credentials. Any API that requries authentication # would be enough. client.api.get_devices() except MatrixRequestError as ex: log.debug( "Couldn't use previous login credentials", node=node_address_from_userid(client.user_id), prev_user_id=user_id, _exception=ex, ) return None log.debug( "Success. Valid previous credentials", node=node_address_from_userid(client.user_id), user_id=user_id, ) return client.get_user(client.user_id)
def _check_previous_login(client: GMatrixClient, prev_user_id: str = None, prev_access_token: str = None, base_username: str = None, server_name: str = None): # log.info("User: "******"Access Token: " + prev_access_token) _match_user = re.match( f"^@{re.escape(base_username)}.*:{re.escape(server_name)}$", prev_user_id or "") if _match_user: # same user as before assert prev_user_id is not None log.info("Trying previous user login", user_id=prev_user_id) client.set_access_token(user_id=prev_user_id, token=prev_access_token) try: client.api.get_devices() except MatrixRequestError as ex: log.debug( "Couldn't use previous login credentials, discarding", prev_user_id=prev_user_id, _exception=ex, ) else: prev_sync_limit = client.set_sync_limit(0) client._sync() # initial_sync client.set_sync_limit(prev_sync_limit) log.info("Success. Valid previous credentials", user_id=prev_user_id) return client.get_user(client.user_id) elif prev_user_id: log.debug( "Different server or account, discarding", prev_user_id=prev_user_id, current_address=base_username, current_server=server_name, )
def login_or_register( client: GMatrixClient, signer: Signer, prev_user_id: str = None, prev_access_token: str = None, ) -> User: """Login to a Raiden matrix server with password and displayname proof-of-keys - Username is in the format: 0x<eth_address>(.<suffix>)?, where the suffix is not required, but a deterministic (per-account) random 8-hex string to prevent DoS by other users registering our address - Password is the signature of the server hostname, verified by the server to prevent account creation spam - Displayname currently is the signature of the whole user_id (including homeserver), to be verified by other peers. May include in the future other metadata such as protocol version Params: client: GMatrixClient instance configured with desired homeserver signer: raiden.utils.signer.Signer instance for signing password and displayname prev_user_id: (optional) previous persisted client.user_id. Must match signer's account prev_access_token: (optional) previous persistend client.access_token for prev_user_id Returns: Own matrix_client.User """ server_url = client.api.base_url server_name = urlparse(server_url).netloc base_username = to_normalized_address(signer.address) _match_user = re.match( f'^@{re.escape(base_username)}.*:{re.escape(server_name)}$', prev_user_id or '', ) if _match_user: # same user as before log.debug('Trying previous user login', user_id=prev_user_id) client.set_access_token(user_id=prev_user_id, token=prev_access_token) try: client.api.get_devices() except MatrixRequestError as ex: log.debug( 'Couldn\'t use previous login credentials, discarding', prev_user_id=prev_user_id, _exception=ex, ) else: prev_sync_limit = client.set_sync_limit(0) client._sync() # initial_sync client.set_sync_limit(prev_sync_limit) log.debug('Success. Valid previous credentials', user_id=prev_user_id) return client.get_user(client.user_id) elif prev_user_id: log.debug( 'Different server or account, discarding', prev_user_id=prev_user_id, current_address=base_username, current_server=server_name, ) # password is signed server address password = encode_hex(signer.sign(server_name.encode())) rand = None # try login and register on first 5 possible accounts for i in range(JOIN_RETRIES): username = base_username if i: if not rand: rand = Random( ) # deterministic, random secret for username suffixes # initialize rand for seed (which requires a signature) only if/when needed rand.seed(int.from_bytes(signer.sign(b'seed')[-32:], 'big')) username = f'{username}.{rand.randint(0, 0xffffffff):08x}' try: client.login(username, password, sync=False) prev_sync_limit = client.set_sync_limit(0) client._sync() # when logging, do initial_sync with limit=0 client.set_sync_limit(prev_sync_limit) log.debug( 'Login', homeserver=server_name, server_url=server_url, username=username, ) break except MatrixRequestError as ex: if ex.code != 403: raise log.debug( 'Could not login. Trying register', homeserver=server_name, server_url=server_url, username=username, ) try: client.register_with_password(username, password) log.debug( 'Register', homeserver=server_name, server_url=server_url, username=username, ) break except MatrixRequestError as ex: if ex.code != 400: raise log.debug('Username taken. Continuing') continue else: raise ValueError('Could not register or login!') name = encode_hex(signer.sign(client.user_id.encode())) user = client.get_user(client.user_id) user.set_display_name(name) return user