feat: improve Login5 authentication with token renewal
Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com>
This commit is contained in:
@@ -63,15 +63,16 @@ class ZeroconfServer(Closeable):
|
||||
def __init__(self, inner: Inner, listen_port):
|
||||
self.__inner = inner
|
||||
self.__keys = DiffieHellman()
|
||||
|
||||
if listen_port == -1:
|
||||
listen_port = random.randint(self.__min_port + 1, self.__max_port)
|
||||
|
||||
self.__runner = ZeroconfServer.HttpRunner(self, listen_port)
|
||||
threading.Thread(target=self.__runner.run,
|
||||
name="zeroconf-http-server",
|
||||
daemon=True).start()
|
||||
|
||||
self.__zeroconf = zeroconf.Zeroconf()
|
||||
|
||||
advertised_ip_str = self._get_local_ip()
|
||||
|
||||
server_hostname = socket.gethostname()
|
||||
@@ -105,7 +106,12 @@ class ZeroconfServer(Closeable):
|
||||
addresses=service_addresses # Pass resolved IP, or None if 0.0.0.0 or conversion failed
|
||||
)
|
||||
|
||||
self.__zeroconf.register_service(self.__service_info)
|
||||
try:
|
||||
self.__zeroconf.register_service(self.__service_info)
|
||||
self.logger.info("Zeroconf service registered successfully!")
|
||||
except Exception as e:
|
||||
self.logger.error("Failed to register zeroconf service: {}".format(e))
|
||||
raise
|
||||
|
||||
def _get_local_ip(self) -> str:
|
||||
"""Tries to determine a non-loopback local IP address for network advertisement."""
|
||||
@@ -184,6 +190,7 @@ class ZeroconfServer(Closeable):
|
||||
|
||||
def handle_add_user(self, __socket: socket.socket, params: dict[str, str],
|
||||
http_version: str) -> None:
|
||||
self.logger.info("Spotify Connect transfer detected")
|
||||
username = params.get("userName")
|
||||
if not username:
|
||||
self.logger.error("Missing userName!")
|
||||
@@ -236,31 +243,42 @@ class ZeroconfServer(Closeable):
|
||||
initial_value=int.from_bytes(
|
||||
iv, "big")))
|
||||
decrypted = aes.decrypt(encrypted)
|
||||
self.close_session()
|
||||
with self.__connection_lock:
|
||||
self.__connecting_username = username
|
||||
self.logger.info("Accepted new user from {}. [deviceId: {}]".format(
|
||||
params.get("deviceName"), self.__inner.device_id))
|
||||
response = json.dumps(self.__default_successful_add_user)
|
||||
__socket.send(http_version.encode())
|
||||
__socket.send(b" 200 OK")
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(b"Content-Length: ")
|
||||
__socket.send(str(len(response)).encode())
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(response.encode())
|
||||
self.__session = Session.Builder(self.__inner.conf) \
|
||||
.set_device_id(self.__inner.device_id) \
|
||||
.set_device_name(self.__inner.device_name) \
|
||||
.set_device_type(self.__inner.device_type) \
|
||||
.set_preferred_locale(self.__inner.preferred_locale) \
|
||||
.blob(username, decrypted) \
|
||||
.create()
|
||||
with self.__connection_lock:
|
||||
self.__connecting_username = None
|
||||
for session_listener in self.__session_listeners:
|
||||
session_listener.session_changed(self.__session)
|
||||
try:
|
||||
self.close_session()
|
||||
with self.__connection_lock:
|
||||
self.__connecting_username = username
|
||||
self.logger.info("Accepted new user from {}. [deviceId: {}]".format(
|
||||
params.get("deviceName"), self.__inner.device_id))
|
||||
|
||||
response = json.dumps(self.__default_successful_add_user)
|
||||
__socket.send(http_version.encode())
|
||||
__socket.send(b" 200 OK")
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(b"Content-Length: ")
|
||||
__socket.send(str(len(response)).encode())
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(self.__eol)
|
||||
__socket.send(response.encode())
|
||||
|
||||
self.__session = Session.Builder(self.__inner.conf) \
|
||||
.set_device_id(self.__inner.device_id) \
|
||||
.set_device_name(self.__inner.device_name) \
|
||||
.set_device_type(self.__inner.device_type) \
|
||||
.set_preferred_locale(self.__inner.preferred_locale) \
|
||||
.blob(username, decrypted) \
|
||||
.create()
|
||||
|
||||
with self.__connection_lock:
|
||||
self.__connecting_username = None
|
||||
|
||||
self.logger.info("Session created for user: {}".format(self.__session.username()))
|
||||
for session_listener in self.__session_listeners:
|
||||
session_listener.session_changed(self.__session)
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error("Error in handle_add_user: {}".format(e))
|
||||
with self.__connection_lock:
|
||||
self.__connecting_username = None
|
||||
|
||||
def handle_get_info(self, __socket: socket.socket,
|
||||
http_version: str) -> None:
|
||||
@@ -289,6 +307,10 @@ class ZeroconfServer(Closeable):
|
||||
self.__session = None
|
||||
return valid
|
||||
|
||||
def get_session(self) -> typing.Union[Session, None]:
|
||||
"""Get the current session if valid, None otherwise"""
|
||||
return self.__session if self.has_valid_session() else None
|
||||
|
||||
def parse_path(self, path: str) -> dict[str, str]:
|
||||
url = "https://host" + path
|
||||
parsed = {}
|
||||
@@ -309,10 +331,10 @@ class ZeroconfServer(Closeable):
|
||||
return self
|
||||
|
||||
def create(self) -> ZeroconfServer:
|
||||
return ZeroconfServer(
|
||||
ZeroconfServer.Inner(self.device_type, self.device_name,
|
||||
self.device_id, self.preferred_locale,
|
||||
self.conf), self.listen_port)
|
||||
inner = ZeroconfServer.Inner(self.device_type, self.device_name,
|
||||
self.device_id, self.preferred_locale,
|
||||
self.conf)
|
||||
return ZeroconfServer(inner, self.listen_port)
|
||||
|
||||
class HttpRunner(Closeable, Runnable):
|
||||
__should_stop = False
|
||||
@@ -392,6 +414,7 @@ class ZeroconfServer(Closeable):
|
||||
|
||||
def handle_request(self, __socket: socket.socket, http_version: str,
|
||||
action: str, params: dict[str, str]) -> None:
|
||||
self.__zeroconf_server.logger.debug("HTTP request received - action: {}, params: {}".format(action, params.keys() if params else "None"))
|
||||
if action == "addUser":
|
||||
if params is None:
|
||||
raise RuntimeError
|
||||
|
||||
Reference in New Issue
Block a user