pythonoauthauthorizationspotifyspotipy

Spotipy Authorization Code Flow "Only valid bearer authentication" Error


I am trying to understand Spotipy library to create some programs for personal use. Initially I have tried and access Spotify using "Client Credentials Flow" but since "Authorization Code Flow" seems more suited for my use cases currently focused on that.

I believe I have managed to implement the basic flow that checks whether there is a cached token or not. If there is not any cached token, tries to get new one and cache the new token.

The issue is when I try to get currently playing song or user info, API returns "Only valid bearer authentication supported" error. I understand that Spotify API fires this exeption either using non valid token or bearer token does not have the required scope. But still cannot find the issue.

My Client ID, Client Secret and Redirect URI defined as environmental variables.

You can find the code and its output below. (There might be some non-Pythonesque use in the code, I am open to the any suggestions that refines my python skills.)

CODE:

import spotipy
from spotipy import oauth2
from spotipy import cache_handler

import requests
import json
from pprint import pprint

oAuthscope = "user-read-email,user-read-private,user-library-read,user-read-playback-state,user-modify-playback-state,user-read-currently-playing"
Sp_Cache = cache_handler.CacheFileHandler()
auth_manager = spotipy.SpotifyOAuth(scope=oAuthscope,cache_handler=Sp_Cache)
Sp_oAuth = spotipy.Spotify(auth_manager)


def init_Spotify_Session():
    #Define access_token variable
    access_token = ""
    print ("\n Access_Token variable defined!")

    #Try to get cached token
    print ("\n Trying to get cached token!")
    Token_Data = Sp_Cache.get_cached_token()

    if Token_Data is not None:
        print ("\n Cached Token = \n")
        pprint (Token_Data )
        print ("\n\n\n")
    else :
        print ("There is no cached token!!! Token cannot be printed!!")
    
    if not Token_Data:
        print ("There is not any cached token!")

        authorisation_url = auth_manager.get_authorize_url()
        print ("\n Authorisation URL retrieved = " + authorisation_url)
        print ("\n Trying to get authorisation response:")

        oAuth_Response = auth_manager.get_auth_response()
        print ("\n oAuthResponse= ")
        print (type(oAuth_Response))
        print("\n oAuth_Response = " + oAuth_Response + "\n")
        #Sp_Cache.save_token_to_cache(oAuth_Response)

        #auth_Token = auth_manager.get_authorization_code(oAuth_Response)
        #print ("\n CODE = \n" + auth_Token + "\n")

        print ("\n\n\n Trying to get new access token!!! \n\n\n")    
        Token_Data = auth_manager.get_access_token(code=oAuth_Response)
        access_token = Token_Data["access_token"]
        print ("\n Access Token = \n")
        pprint (Token_Data)
        print ("\n\n\n")
        pprint (access_token)
        print ("\n\n\n")


        Sp_Cache.save_token_to_cache(Token_Data)

        print("\n Cached New Token = ")
        print(Sp_Cache.get_cached_token()),print ("\n\n\n")

        


def Get_Current_Song():
    global song_current_track, artist_current_track, cover_art_url
    try:
        response_current_track = Sp_oAuth.current_user_playing_track() # Gets response of currently playing track

        song_current_track = response_current_track["item"]["name"]
        artist_current_track = response_current_track["item"]["album"]["artists"][0]["name"]
        cover_art_url = response_current_track ["item"]["album"]["images"][0]["url"]
        #cover_art = urllib.request.urlretrieve(cover_art_url, "downloaded.jpg")
        cover_art = requests.get(cover_art_url, "downloaded.jpg") ##gpt suggestion
        #cover_art = Image.open("downloaded.jpg")
        #cover_art.show()
        
        print("cover art downloaded!!!")
        

        #pprint(response_current_track) #prints whole response json

        print("**************************")
        print("Currently Playing:")
        pprint(song_current_track) #prints current song title
        pprint(artist_current_track) #prints current song artist
        print("**************************")
    
    except TypeError:
        print(" ")
        print ("Error Occured Details Below:")
        print(" ")
        print("!!!Check if spotify playing!!!")
        print(" ")
        #traceback.print_exc()
    return song_current_track, artist_current_track, cover_art, cover_art_url
        
#Get_Current_Song(

def Get_Queued_Song():
    global song_next_track, artist_next_track
    try:
        
        response_queued_track = Sp_oAuth.queue() #print(json.dumps(results, indent=4)) #Prints out json of 
        #print(list(response_queued_track.keys()))
        #print("____________________________________________")
        song_next_track = response_queued_track["queue"][0]["name"]
        artist_next_track = response_queued_track["queue"][0]["artists"][0]["name"]
        
        print("**************************")
        print("Coming on Next:")
        pprint(song_next_track) #prints current song title
        pprint(artist_next_track) #prints current song artist
        print("**************************")
    
    except:
        print(" ")
        print ("Error Occured Details Below:")
        print(" ")
        print("!!!Check if spotify queue is empty!!!")
        print(" ")
        #traceback.print_exc()
        
    return song_next_track, artist_next_track




init_Spotify_Session()

Get_Current_Song()

OUTPUT:

 Access_Token variable defined!

 Trying to get cached token!

 Cached Token =

{'access_token': 'BQBVdYQaXUI24UZ_f_ttkSYWtRQWc0MGq3zXryEwtYBCBFLUH5AxC-aOnlmz8FmlqHZ7xveU7VeI95whGeitSb6iVuGAydalYcSaDwXFZwxRn24GZpUYYSji09QXaTKSzcTgFV_HtmS3hylvthXM9hAI6AIks1iLA4aU2axT1BjBToiQVagEzqq4pUkgaxHlfLgaIgmTMHe0Lq0mQTTI2Q',
 'expires_at': 1680096145,
 'expires_in': 3600,
 'refresh_token': 'AQCXYYFHq3Xs-DYHsWZHq-TnDAW1OZ-W8TaYqZdSV6LBlJQH6VYqnwrYuEKxy4nsMoMaLHGHxxb8Vf4LZjnkm3E4TRq1QtZ3n5vFg7mZLzTdFaEgPiZhkVBVyRIEL5yW3TY',
 'scope': 'user-library-read user-modify-playback-state '
          'user-read-currently-playing user-read-email '
          'user-read-playback-state user-read-private',
 'token_type': 'Bearer'}




HTTP Error for GET to https://api.spotify.com/v1/me/player/currently-playing with Params: {} returned 400 due to Only valid bearer authentication supported
Traceback (most recent call last):
  File "C:\Users\erensan\AppData\Roaming\Python\Python310\site-packages\spotipy\client.py", line 269, in _internal_call
    response.raise_for_status()
  File "C:\Users\erensan\AppData\Roaming\Python\Python310\site-packages\requests\models.py", line 
1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.spotify.com/v1/me/player/currently-playing

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\erensan\Desktop\Python Dev\Spotipy\oAuth\Spotipy_oAuth_eren2.py", line 141, in <module>
    Get_Current_Song()
  File "C:\Users\erensan\Desktop\Python Dev\Spotipy\oAuth\Spotipy_oAuth_eren2.py", line 78, in Get_Current_Song
    response_current_track = Sp_oAuth.current_user_playing_track() # Gets response of currently playing track
  File "C:\Users\erensan\AppData\Roaming\Python\Python310\site-packages\spotipy\client.py", line 1230, in current_user_playing_track
    return self._get("me/player/currently-playing")
  File "C:\Users\erensan\AppData\Roaming\Python\Python310\site-packages\spotipy\client.py", line 321, in _get
    return self._internal_call("GET", url, payload, kwargs)
  File "C:\Users\erensan\AppData\Roaming\Python\Python310\site-packages\spotipy\client.py", line 291, in _internal_call
    raise SpotifyException(
spotipy.exceptions.SpotifyException: http status: 400, code:-1 - https://api.spotify.com/v1/me/player/currently-playing:
 Only valid bearer authentication supported, reason: None
PS C:\Users\erensan\Desktop\Python Dev\Spotipy\oAuth> 

I have tried the code with clearing the cache, and adding additional scope to the auth_manager but the result is the same.


Solution

  • You missed two items

    #1 it needs to set the environment variables for spotipy

    os.environ["SPOTIPY_CLIENT_ID"] = "<your client ID>"
    os.environ["SPOTIPY_CLIENT_SECRET"] = "<your client Secret>"
    os.environ["SPOTIPY_REDIRECT_URI"] = "<your App's registered redirect URI>"
    

    #2 Spotify() class correct assign initialize with input argument

    From

    spotipy.Spotify(auth_manager)
    

    To

    spotipy.Spotify(auth_manager=auth_manager)
    

    Your approaches

    Demo code

    import spotipy
    from spotipy.oauth2 import SpotifyOAuth
    from spotipy import cache_handler
    import os
    from pprint import pprint
    
    # Set your Spotify API credentials as environment variables, it will pick by spotipy API
    os.environ["SPOTIPY_CLIENT_ID"] = "<your client ID>"
    os.environ["SPOTIPY_CLIENT_SECRET"] = "<your client Secret>"
    os.environ["SPOTIPY_REDIRECT_URI"] = "<your App's registered redirect URI>"
    
    # multiple scopes
    oAuthscope = "user-read-email,user-read-private,user-library-read,user-read-playback-state,user-modify-playback-state,user-read-currently-playing"
    
    Sp_Cache = cache_handler.CacheFileHandler()
    auth_manager = spotipy.SpotifyOAuth(scope=oAuthscope,cache_handler=Sp_Cache)
    Sp_oAuth  = spotipy.Spotify(auth_manager=auth_manager)
    
    def init_Spotify_Session():
        access_token = ""
        print ("\n Access_Token variable defined!")
        Token_Data = Sp_Cache.get_cached_token()
        if Token_Data is not None:
            print ("\n Cached Token = \n")
            pprint (Token_Data )
            print ("\n")
        else :
            print ("There is no cached token!!! Token cannot be printed!!")
    
        if not Token_Data:
            print ("There is not any cached token!")
    
            authorisation_url = auth_manager.get_authorize_url()
            print ("\n Authorisation URL retrieved = " + authorisation_url)
            print ("\n Trying to get authorisation response:")
    
            oAuth_Response = auth_manager.get_auth_response()
            print ("\n oAuthResponse= ")
            print (type(oAuth_Response))
            print("\n oAuth_Response = " + oAuth_Response + "\n")
    
            print ("\n Trying to get new access token!!! \n")
            Token_Data = auth_manager.get_access_token(code=oAuth_Response)
            access_token = Token_Data["access_token"]
            print ("\n Access Token = \n")
            pprint (Token_Data)
            pprint (access_token)
    
            Sp_Cache.save_token_to_cache(Token_Data)
    
            print("\n Cached New Token = ")
            print(Sp_Cache.get_cached_token()),print ("\n")
    
    def Get_Current_Song():
        response_current_track = Sp_oAuth.current_user_playing_track()
        if response_current_track  is not None and response_current_track["item"] is not None:
            song = response_current_track["item"]
            print(song['artists'][0]['name'], " – ", song['name'])
    
    init_Spotify_Session()
    
    Get_Current_Song()
    

    Result enter image description here

    Simple way

    Also you don't necessary to handle a token by your self.

    spotipy works for you. If not exist .cache, will launch browser and login spotify for getting token.

    If exit '.cache, then skip login and pick up the token from .cache` file.

    .cache will includes six information (access_token, token_type, expires_in, refresh_token, scope and expires_at)

    enter image description here

    This simple code

    import spotipy
    from spotipy.oauth2 import SpotifyOAuth
    import os
    
    # Set your Spotify API credentials as environment variables, it will pick by spotipy API
    os.environ["SPOTIPY_CLIENT_ID"] = "<your client ID>"
    os.environ["SPOTIPY_CLIENT_SECRET"] = "<your client Secret>"
    os.environ["SPOTIPY_REDIRECT_URI"] = "<your App's registered redirect URI>"
    
    # multiple scopes
    oAuthscope = "user-read-email,user-read-private,user-library-read,user-read-playback-state,user-modify-playback-state,user-read-currently-playing"
    
    Sp_oAuth = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=oAuthscope))
    
    def Get_Current_Song():
        response_current_track = Sp_oAuth.current_user_playing_track()
        if response_current_track  is not None and response_current_track["item"] is not None:
            song = response_current_track["item"]
            print(song['artists'][0]['name'], " – ", song['name'])
    
    Get_Current_Song()
    

    Result enter image description here