From a91160f013a56c9fb1d4488270f472d1735c6cd2 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 17 Aug 2024 11:45:29 +0200 Subject: [PATCH] handle edge case refreshing spotify token --- .../server/providers/spotify/__init__.py | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/music_assistant/server/providers/spotify/__init__.py b/music_assistant/server/providers/spotify/__init__.py index aa1164e6..ec815455 100644 --- a/music_assistant/server/providers/spotify/__init__.py +++ b/music_assistant/server/providers/spotify/__init__.py @@ -769,33 +769,39 @@ class SpotifyProvider(MusicProvider): async def login(self) -> dict: """Log-in Spotify and return Auth/token info.""" # return existing token if we have one in memory - if self._auth_info and (self._auth_info["expires_at"] > (time.time() - 60)): + if self._auth_info and (self._auth_info["expires_at"] > (time.time() - 120)): return self._auth_info if not (refresh_token := self.config.get_value(CONF_REFRESH_TOKEN)): raise LoginFailed("Authentication required") - # refresh token - client_id = self.config.get_value(CONF_CLIENT_ID) or app_var(2) - params = { - "grant_type": "refresh_token", - "refresh_token": refresh_token, - "client_id": client_id, - } - async with self.mass.http_session.post( - "https://accounts.spotify.com/api/token", data=params - ) as response: - if response.status != 200: - err = await response.text() - self.mass.config.set_raw_provider_config_value( - self.instance_id, CONF_REFRESH_TOKEN, None - ) - raise LoginFailed(f"Failed to refresh access token: {err}") - data = await response.json() - access_token = data["access_token"] - refresh_token = data["refresh_token"] - expires_at = int(data["expires_in"] + time.time()) - self.logger.debug("Successfully refreshed access token") + expires_at = self.config.get_value(CONF_AUTH_EXPIRES_AT) or 0 + access_token = self.config.get_value(CONF_ACCESS_TOKEN) + + if expires_at < (time.time() - 300): + # refresh token + client_id = self.config.get_value(CONF_CLIENT_ID) or app_var(2) + params = { + "grant_type": "refresh_token", + "refresh_token": refresh_token, + "client_id": client_id, + } + async with self.mass.http_session.post( + "https://accounts.spotify.com/api/token", data=params + ) as response: + if response.status != 200: + err = await response.text() + if "revoked" in err: + # clear refresh token if it's invalid + self.mass.config.set_raw_provider_config_value( + self.instance_id, CONF_REFRESH_TOKEN, None + ) + raise LoginFailed(f"Failed to refresh access token: {err}") + data = await response.json() + access_token = data.get("access_token") or access_token + refresh_token = data.get("refresh_token") or refresh_token + expires_at = int(data["expires_in"] + time.time()) + self.logger.debug("Successfully refreshed access token") self._auth_info = auth_info = { "access_token": access_token, -- 2.34.1