Skip to content

Commit 6c30d29

Browse files
authored
Merge pull request #312 from Googolplexed0/login5-refresh
Improve Login5 Implementation
2 parents 7481dca + 5d0784e commit 6c30d29

File tree

3 files changed

+45
-59
lines changed

3 files changed

+45
-59
lines changed

librespot/core.py

Lines changed: 44 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -910,8 +910,6 @@ class Session(Closeable, MessageListener, SubListener):
910910
__dealer_client: typing.Union[DealerClient, None] = None
911911
__event_service: typing.Union[EventService, None] = None
912912
__keys: DiffieHellman
913-
__login5_access_token: typing.Union[str, None] = None
914-
__login5_token_expiry: typing.Union[int, None] = None
915913
__mercury_client: MercuryClient
916914
__receiver: typing.Union[Receiver, None] = None
917915
__search: typing.Union[SearchManager, None]
@@ -972,7 +970,6 @@ def authenticate(self,
972970
973971
"""
974972
self.__authenticate_partial(credential, False)
975-
self.__authenticate_login5()
976973
with self.__auth_lock:
977974
self.__mercury_client = MercuryClient(self)
978975
self.__token_provider = TokenProvider(self)
@@ -1208,13 +1205,6 @@ def is_valid(self) -> bool:
12081205
self.__wait_auth_lock()
12091206
return self.__ap_welcome is not None and self.connection is not None
12101207

1211-
def login5(self) -> tuple[str, int]:
1212-
""" """
1213-
self.__wait_auth_lock()
1214-
if self.__login5_access_token is None or self.__login5_token_expiry is None:
1215-
raise RuntimeError("Session isn't authenticated!")
1216-
return self.__login5_access_token, self.__login5_token_expiry
1217-
12181208
def mercury(self) -> MercuryClient:
12191209
""" """
12201210
self.__wait_auth_lock()
@@ -1394,43 +1384,6 @@ def __authenticate_partial(self,
13941384
else:
13951385
raise RuntimeError("Unknown CMD 0x" + packet.cmd.hex())
13961386

1397-
def __authenticate_login5(self) -> None:
1398-
"""Authenticate using Login5 to get access token"""
1399-
login5_request = Login5.LoginRequest()
1400-
login5_request.client_info.client_id = MercuryRequests.keymaster_client_id
1401-
login5_request.client_info.device_id = self.__inner.device_id
1402-
1403-
# Set stored credential from APWelcome
1404-
if hasattr(self, '_Session__ap_welcome') and self.__ap_welcome:
1405-
stored_cred = Login5Credentials.StoredCredential()
1406-
stored_cred.username = self.__ap_welcome.canonical_username
1407-
stored_cred.data = self.__ap_welcome.reusable_auth_credentials
1408-
login5_request.stored_credential.CopyFrom(stored_cred)
1409-
1410-
response = requests.post(
1411-
"https://login5.spotify.com/v3/login",
1412-
data=login5_request.SerializeToString(),
1413-
headers={
1414-
"Content-Type": "application/x-protobuf",
1415-
"Accept": "application/x-protobuf"
1416-
}
1417-
)
1418-
1419-
if response.status_code == 200:
1420-
login5_response = Login5.LoginResponse()
1421-
login5_response.ParseFromString(response.content)
1422-
1423-
if login5_response.HasField('ok'):
1424-
self.__login5_access_token = login5_response.ok.access_token
1425-
self.__login5_token_expiry = int(time.time()) + login5_response.ok.access_token_expires_in
1426-
self.logger.info("Login5 authentication successful, got access token")
1427-
else:
1428-
self.logger.warning("Login5 authentication failed: {}".format(login5_response.error))
1429-
else:
1430-
self.logger.warning("Login5 request failed with status: {}".format(response.status_code))
1431-
else:
1432-
self.logger.error("Login5 authentication failed: No APWelcome found")
1433-
14341387
def __send_unchecked(self, cmd: bytes, payload: bytes) -> None:
14351388
self.cipher_pair.send_encoded(self.connection, cmd, payload)
14361389

@@ -2343,22 +2296,55 @@ def get_token(self, *scopes) -> StoredToken:
23432296
if token is not None:
23442297
if token.expired():
23452298
self.__tokens.remove(token)
2299+
self.logger.debug("Login5 token expired, need to re-authenticate")
23462300
else:
23472301
return token
23482302

2349-
login5_token = None
2350-
login5_access_token, login5_token_expiry = self.__session.login5()
2351-
if int(time.time()) < login5_token_expiry - 60: # 60 second buffer
2352-
login5_token = TokenProvider.StoredToken({
2353-
"expiresIn": login5_token_expiry - int(time.time()),
2354-
"accessToken": login5_access_token,
2355-
"scope": scopes
2356-
})
2357-
self.__tokens.append(login5_token)
2303+
token = self.login5(scopes)
2304+
if token is not None:
2305+
self.__tokens.append(token)
23582306
self.logger.debug("Using Login5 access token for scopes: {}".format(scopes))
2307+
return token
2308+
2309+
def login5(self, scopes: typing.List[str]) -> typing.Union[StoredToken, None]:
2310+
"""Submit Login5 request for a fresh access token"""
2311+
2312+
if self.__session.ap_welcome():
2313+
login5_request = Login5.LoginRequest()
2314+
login5_request.client_info.client_id = MercuryRequests.keymaster_client_id
2315+
login5_request.client_info.device_id = self.__session.device_id()
2316+
2317+
stored_cred = Login5Credentials.StoredCredential()
2318+
stored_cred.username = self.__session.username()
2319+
stored_cred.data = self.__session.ap_welcome().reusable_auth_credentials
2320+
login5_request.stored_credential.CopyFrom(stored_cred)
2321+
2322+
response = requests.post(
2323+
"https://login5.spotify.com/v3/login",
2324+
data=login5_request.SerializeToString(),
2325+
headers={
2326+
"Content-Type": "application/x-protobuf",
2327+
"Accept": "application/x-protobuf"
2328+
})
2329+
2330+
if response.status_code == 200:
2331+
login5_response = Login5.LoginResponse()
2332+
login5_response.ParseFromString(response.content)
2333+
2334+
if login5_response.HasField('ok'):
2335+
self.logger.info("Login5 authentication successful, got access token".format(login5_response.ok.access_token))
2336+
token = TokenProvider.StoredToken({
2337+
"expiresIn": login5_response.ok.access_token_expires_in, # approximately one hour
2338+
"accessToken": login5_response.ok.access_token,
2339+
"scope": scopes
2340+
})
2341+
return token
2342+
else:
2343+
self.logger.warning("Login5 authentication failed: {}".format(login5_response.error))
2344+
else:
2345+
self.logger.warning("Login5 request failed with status: {}".format(response.status_code))
23592346
else:
2360-
self.logger.debug("Login5 token expired, need to re-authenticate")
2361-
return login5_token
2347+
self.logger.error("Login5 authentication failed: No APWelcome found")
23622348

23632349
class StoredToken:
23642350
""" """

librespot/proto/spotify/login5/v3/Login5_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

librespot/proto/spotify/login5/v3/identifiers/Identifiers.py renamed to librespot/proto/spotify/login5/v3/identifiers/Identifiers_pb2.py

File renamed without changes.

0 commit comments

Comments
 (0)