Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SpotifyOAuth Object not prompting user authorization (version 2.13.0) #533

Open
a-camarillo opened this issue Jul 7, 2020 · 7 comments
Open
Labels

Comments

@a-camarillo
Copy link

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.

@a-camarillo a-camarillo changed the title Spotify.OAuth Object not prompting user authorization (version 2.13.0) SpotifyOAuth Object not prompting user authorization (version 2.13.0) Jul 8, 2020
@a-camarillo
Copy link
Author

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()

@stephanebruckert
Copy link
Member

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

@a-camarillo
Copy link
Author

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

@vikivanov
Copy link

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.

@DJSdev
Copy link
Contributor

DJSdev commented 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.

@stephanebruckert
Copy link
Member

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

@stephanebruckert
Copy link
Member

stephanebruckert commented Aug 30, 2020

@DJSdev I've implemented point 1 if you want to have a look #567

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants