@@ -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 """ """
0 commit comments