[GH-ISSUE #533] SpotifyOAuth Object not prompting user authorization (version 2.13.0) #321

Open
opened 2026-02-27 23:21:59 +03:00 by kerem · 7 comments
Owner

Originally created by @a-camarillo on GitHub (Jul 7, 2020).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/533

I'm currently trying to run the example for the Authorization Code Flow from the docs:

import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = "user-library-read"

sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))

results = sp.current_user_saved_tracks()
for idx, item in enumerate(results['items']):
    track = item['track']
    print(idx, track['artists'][0]['name'], " – ", track['name']) 

I can create the Spotify API client object but SpotifyOAuth never prompts user access.

When I go to run results = sp.current_user_saved_tracks() I get the error:spotipy.oauth2.SpotifyOauthError: You must either set a cache_path or a username.

I'm not sure if the issue is with the Authorization Code Flow or something on my end.

Originally created by @a-camarillo on GitHub (Jul 7, 2020). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/533 I'm currently trying to run the example for the Authorization Code Flow from the docs: ``` import spotipy from spotipy.oauth2 import SpotifyOAuth scope = "user-library-read" sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) results = sp.current_user_saved_tracks() for idx, item in enumerate(results['items']): track = item['track'] print(idx, track['artists'][0]['name'], " – ", track['name']) ``` I can create the Spotify API client object but `SpotifyOAuth` never prompts user access. When I go to run `results = sp.current_user_saved_tracks()` I get the error:`spotipy.oauth2.SpotifyOauthError: You must either set a cache_path or a username.` I'm not sure if the issue is with the Authorization Code Flow or something on my end.
Author
Owner

@a-camarillo commented on GitHub (Jul 8, 2020):

I was able to prompt user authorization by calling get_access_token and specifying a cache_path although I'm not entirely sure how this is processing since the path is to an empty text file which doesn't update with the token information.

Still, I am curious as to why I can't replicate the code from the docs example. I will paste the code which worked for me below in hopes it will help.

# Client ID and Client Secret are set as env variables

import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = "user-top-read"
OAuth = SpotifyOAuth(scope=scope,
                     redirect_uri='http://localhost:8888',
                     cache_path='../cache.txt')
token = OAuth.get_access_token()

# receive the following warning
# __main__:1: DeprecationWarning: You're using 'as_dict = True'.get_access_token will return the token string directly in future 
#  versions. Please adjust your code accordingly, or use get_cached_token instead.
# At this point, I am taken to the user authorization and grant access with the 'user-top-read' scope

sp = spotipy.Spotify(auth_manager=OAuth)
top_tracks = sp.current_user_top_tracks()
<!-- gh-comment-id:655313305 --> @a-camarillo commented on GitHub (Jul 8, 2020): I was able to prompt user authorization by calling `get_access_token` and specifying a cache_path although I'm not entirely sure how this is processing since the path is to an empty text file which doesn't update with the token information. Still, I am curious as to why I can't replicate the code from the docs example. I will paste the code which worked for me below in hopes it will help. ``` # Client ID and Client Secret are set as env variables import spotipy from spotipy.oauth2 import SpotifyOAuth scope = "user-top-read" OAuth = SpotifyOAuth(scope=scope, redirect_uri='http://localhost:8888', cache_path='../cache.txt') token = OAuth.get_access_token() # receive the following warning # __main__:1: DeprecationWarning: You're using 'as_dict = True'.get_access_token will return the token string directly in future # versions. Please adjust your code accordingly, or use get_cached_token instead. # At this point, I am taken to the user authorization and grant access with the 'user-top-read' scope sp = spotipy.Spotify(auth_manager=OAuth) top_tracks = sp.current_user_top_tracks() ```
Author
Owner

@stephanebruckert commented on GitHub (Jul 12, 2020):

I agree that doesn't seem to behave correctly. I see at least two things that we need to fix:

  • we shouldn't have to specify a username and setting one should be optional. So You must either set a cache_path or a username. should be either removed or worse case be a warning
  • SpotifyOAuth is currently not completing the authentication. It just "sets" all the parameters needed and waits for an endpoint to be called. You are right, it should prompt user access immediately
<!-- gh-comment-id:657275172 --> @stephanebruckert commented on GitHub (Jul 12, 2020): I agree that doesn't seem to behave correctly. I see at least two things that we need to fix: - we shouldn't have to specify a username and setting one should be optional. So `You must either set a cache_path or a username.` should be either removed or worse case be a warning - `SpotifyOAuth` is currently not completing the authentication. It just "sets" all the parameters needed and waits for an endpoint to be called. You are right, it should prompt user access immediately
Author
Owner

@a-camarillo commented on GitHub (Jul 24, 2020):

It looks like the SpotifyOAuth class initializes both cache_path and username, but username also looks for an environment variable "client_username". Not entirely sure if this is what is causing the error to be raised

super(SpotifyOAuth, self).__init__(requests_session)

        self.client_id = client_id
        self.client_secret = client_secret
        self.redirect_uri = redirect_uri
        self.state = state
        self.cache_path = cache_path
        self.username = username or os.getenv(
            CLIENT_CREDS_ENV_VARS["client_username"]
        )
        self.scope = self._normalize_scope(scope)
        self.proxies = proxies
        self.requests_timeout = requests_timeout
        self.show_dialog = show_dialog
<!-- gh-comment-id:663717966 --> @a-camarillo commented on GitHub (Jul 24, 2020): It looks like the SpotifyOAuth class initializes both cache_path and username, but username also looks for an environment variable "client_username". Not entirely sure if this is what is causing the error to be raised ``` super(SpotifyOAuth, self).__init__(requests_session) self.client_id = client_id self.client_secret = client_secret self.redirect_uri = redirect_uri self.state = state self.cache_path = cache_path self.username = username or os.getenv( CLIENT_CREDS_ENV_VARS["client_username"] ) self.scope = self._normalize_scope(scope) self.proxies = proxies self.requests_timeout = requests_timeout self.show_dialog = show_dialog
Author
Owner

@vikivanov commented on GitHub (Jul 27, 2020):

I was able to prompt user authorization by calling get_access_token and specifying a cache_path although I'm not entirely sure how this is processing since the path is to an empty text file which doesn't update with the token information.

Still, I am curious as to why I can't replicate the code from the docs example. I will paste the code which worked for me below in hopes it will help.

# Client ID and Client Secret are set as env variables

import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = "user-top-read"
OAuth = SpotifyOAuth(scope=scope,
                     redirect_uri='http://localhost:8888',
                     cache_path='../cache.txt')
token = OAuth.get_access_token()

# receive the following warning
# __main__:1: DeprecationWarning: You're using 'as_dict = True'.get_access_token will return the token string directly in future 
#  versions. Please adjust your code accordingly, or use get_cached_token instead.
# At this point, I am taken to the user authorization and grant access with the 'user-top-read' scope

sp = spotipy.Spotify(auth_manager=OAuth)
top_tracks = sp.current_user_top_tracks()

I recently stumbled into the same issue and this worked for me but there is definitely something going wrong with SpotifyOAuth.

<!-- gh-comment-id:664677518 --> @vikivanov commented on GitHub (Jul 27, 2020): > I was able to prompt user authorization by calling `get_access_token` and specifying a cache_path although I'm not entirely sure how this is processing since the path is to an empty text file which doesn't update with the token information. > > Still, I am curious as to why I can't replicate the code from the docs example. I will paste the code which worked for me below in hopes it will help. > > ``` > # Client ID and Client Secret are set as env variables > > import spotipy > from spotipy.oauth2 import SpotifyOAuth > > scope = "user-top-read" > OAuth = SpotifyOAuth(scope=scope, > redirect_uri='http://localhost:8888', > cache_path='../cache.txt') > token = OAuth.get_access_token() > > # receive the following warning > # __main__:1: DeprecationWarning: You're using 'as_dict = True'.get_access_token will return the token string directly in future > # versions. Please adjust your code accordingly, or use get_cached_token instead. > # At this point, I am taken to the user authorization and grant access with the 'user-top-read' scope > > sp = spotipy.Spotify(auth_manager=OAuth) > top_tracks = sp.current_user_top_tracks() > ``` I recently stumbled into the same issue and this worked for me but there is definitely something going wrong with SpotifyOAuth.
Author
Owner

@DJSdev commented on GitHub (Aug 28, 2020):

The exception is being thrown from here. The reason is because sp.current_user_top_tracks() is calling get_access_token() under the hood, which checks for a cached token first at the cache-path or in a file named .cache-<username>. When this fails due to no username/cache-path, it raises an exception and never reaches the self.get_authorization_code() function (a few lines later) to actually prompt a user to authorize access.

The only reason I can see having need to specify a username is to differentiate cache files in multi-user environments.

@stephanebruckert

  1. I suggest a default filename of something like .cache and if developers anticipate a multi-user environment, they can specify a username/cache-path as they can now.
  2. The constructor could simply call get_access_token() when SpotifyOAuth, SpotifyPKCE, or SpotifyImplicitGrant is inited so it can perform the authorize user steps, retrieved a cached token, or refresh a cached token. Any subsequent calls by the Spotify client would then use the cached token.
<!-- gh-comment-id:682304023 --> @DJSdev commented on GitHub (Aug 28, 2020): The exception is being thrown from [here](https://github.com/plamere/spotipy/blob/5e9f97df8ea15e657cd4e440ae062a7155689f24/spotipy/oauth2.py#L278). The reason is because `sp.current_user_top_tracks()` is calling `get_access_token()` under the hood, which checks for a [cached token first](https://github.com/plamere/spotipy/blob/5e9f97df8ea15e657cd4e440ae062a7155689f24/spotipy/oauth2.py#L461) at the cache-path or in a file named `.cache-<username>`. When this fails due to no username/cache-path, it raises an exception and never reaches the `self.get_authorization_code()` function ([a few lines later](https://github.com/plamere/spotipy/blob/5e9f97df8ea15e657cd4e440ae062a7155689f24/spotipy/oauth2.py#L471)) to actually prompt a user to authorize access. The only reason I can see having need to specify a username is to differentiate cache files in multi-user environments. @stephanebruckert 1. I suggest a default filename of something like `.cache` and if developers anticipate a multi-user environment, they can specify a username/cache-path as they can now. 2. The constructor could simply call `get_access_token()` when SpotifyOAuth, SpotifyPKCE, or SpotifyImplicitGrant is inited so it can perform the authorize user steps, retrieved a cached token, or refresh a cached token. Any subsequent calls by the Spotify client would then use the cached token.
Author
Owner

@stephanebruckert commented on GitHub (Aug 29, 2020):

@DJSdev totally agree, let's do 1 & 2!

<!-- gh-comment-id:683279298 --> @stephanebruckert commented on GitHub (Aug 29, 2020): @DJSdev totally agree, let's do 1 & 2!
Author
Owner

@stephanebruckert commented on GitHub (Aug 30, 2020):

@DJSdev I've implemented point 1 if you want to have a look https://github.com/plamere/spotipy/pull/567

<!-- gh-comment-id:683432872 --> @stephanebruckert commented on GitHub (Aug 30, 2020): @DJSdev I've implemented point 1 if you want to have a look https://github.com/plamere/spotipy/pull/567
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotipy#321
No description provided.