Spotipy Refreshing a token with authorization code flow
Question:
I have a long-running script using spotipy. After an hour (per the Spotify API), my access token expires. I am catching this successfully, but I don’t know where to go from there in regards to actually refreshing the token. I am using the authorization code flow, not client credentials. Here’s how I authorize:
token = util.prompt_for_user_token(username,scope=scopes,client_id=client_id,client_secret=client_secret, redirect_uri=redirect_uri)
sp = spotipy.Spotify(auth=token)
All refresh examples I’ve seen involve an oauth2
object (ex. oauth.refresh_access_token()
), and the docs list only that function as a method of refreshing your token. It’s my understanding that with authorization code flow, you don’t need an oauth
object (because you authenticate with prompt_for_user_token()
). If that’s the case, how do I refresh my token?
Answers:
After receiving no response on my github issue, it appears to me that there’s no way to refresh a token without using OAuth2. This goes against what is stated in the Spotipy docs:
The Authorization Code flow: This method is suitable for long-running applications which the user logs into once. It provides an access token that can be refreshed.
Their example for Authorization Code flow uses prompt_for_user_token().
I switched to the OAuth approach, which is a pain because it requires re-authorization every time I run the program (really only a problem while I was testing but a problem nonetheless). Since there are no examples of OAuth2 in the Spotipy docs, I’ll paste mine here.
sp_oauth = oauth2.SpotifyOAuth(client_id=client_id,client_secret=client_secret,redirect_uri=redirect_uri,scope=scopes)
token_info = sp_oauth.get_cached_token()
if not token_info:
auth_url = sp_oauth.get_authorize_url(show_dialog=True)
print(auth_url)
response = input('Paste the above link into your browser, then paste the redirect url here: ')
code = sp_oauth.parse_response_code(response)
token_info = sp_oauth.get_access_token(code)
token = token_info['access_token']
sp = spotipy.Spotify(auth=token)
To refresh my token (required every hour), I use this function. When and where you call it depends on your program.
def refresh():
global token_info, sp
if sp_oauth.is_token_expired(token_info):
token_info = sp_oauth.refresh_access_token(token_info['refresh_token'])
token = token_info['access_token']
sp = spotipy.Spotify(auth=token)
I think that the spotipy docs are misleading when it comes to this problem.
I have spent some time trying to solve this problem.
A similar question has been previously asked: Link here
I found the answer to the question be really useful and would summarise it as such: The function util.prompt_user_for_token()
can be recycled and return a token without being prompted to reauthorise (giving an input as seen your solution). I think this is why spotipy docs claim that it can "refresh" on its own. But in reality, requires some prompting.
For example, I adopted a similar solution to your solution in my project here:
def refresh_token():
token = spotipy.util.prompt_for_user_token(user_id, scopes)
last_refresh = datetime.now()
return {'token': token, 'last_refresh': last_refresh}
And I would simply call this function based on the last_refresh time (with a limit of an hour).
I hope this helps, apologies if not useful.
I have a long-running script using spotipy. After an hour (per the Spotify API), my access token expires. I am catching this successfully, but I don’t know where to go from there in regards to actually refreshing the token. I am using the authorization code flow, not client credentials. Here’s how I authorize:
token = util.prompt_for_user_token(username,scope=scopes,client_id=client_id,client_secret=client_secret, redirect_uri=redirect_uri)
sp = spotipy.Spotify(auth=token)
All refresh examples I’ve seen involve an oauth2
object (ex. oauth.refresh_access_token()
), and the docs list only that function as a method of refreshing your token. It’s my understanding that with authorization code flow, you don’t need an oauth
object (because you authenticate with prompt_for_user_token()
). If that’s the case, how do I refresh my token?
After receiving no response on my github issue, it appears to me that there’s no way to refresh a token without using OAuth2. This goes against what is stated in the Spotipy docs:
The Authorization Code flow: This method is suitable for long-running applications which the user logs into once. It provides an access token that can be refreshed.
Their example for Authorization Code flow uses prompt_for_user_token().
I switched to the OAuth approach, which is a pain because it requires re-authorization every time I run the program (really only a problem while I was testing but a problem nonetheless). Since there are no examples of OAuth2 in the Spotipy docs, I’ll paste mine here.
sp_oauth = oauth2.SpotifyOAuth(client_id=client_id,client_secret=client_secret,redirect_uri=redirect_uri,scope=scopes)
token_info = sp_oauth.get_cached_token()
if not token_info:
auth_url = sp_oauth.get_authorize_url(show_dialog=True)
print(auth_url)
response = input('Paste the above link into your browser, then paste the redirect url here: ')
code = sp_oauth.parse_response_code(response)
token_info = sp_oauth.get_access_token(code)
token = token_info['access_token']
sp = spotipy.Spotify(auth=token)
To refresh my token (required every hour), I use this function. When and where you call it depends on your program.
def refresh():
global token_info, sp
if sp_oauth.is_token_expired(token_info):
token_info = sp_oauth.refresh_access_token(token_info['refresh_token'])
token = token_info['access_token']
sp = spotipy.Spotify(auth=token)
I think that the spotipy docs are misleading when it comes to this problem.
I have spent some time trying to solve this problem.
A similar question has been previously asked: Link here
I found the answer to the question be really useful and would summarise it as such: The function util.prompt_user_for_token()
can be recycled and return a token without being prompted to reauthorise (giving an input as seen your solution). I think this is why spotipy docs claim that it can "refresh" on its own. But in reality, requires some prompting.
For example, I adopted a similar solution to your solution in my project here:
def refresh_token():
token = spotipy.util.prompt_for_user_token(user_id, scopes)
last_refresh = datetime.now()
return {'token': token, 'last_refresh': last_refresh}
And I would simply call this function based on the last_refresh time (with a limit of an hour).
I hope this helps, apologies if not useful.