mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-04-27 08:35:49 +03:00
[GH-ISSUE #672] Querying my own user data without going throught auth2 #399
Labels
No labels
api-bug
bug
dependencies
documentation
duplicate
enhancement
external-ide
headless-mode
implicit-grant-flow
invalid
missing-endpoint
pr-welcome
private-api
pull-request
question
spotipy3
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/spotipy#399
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jiwidi on GitHub (Apr 18, 2021).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/672
Hi!
First, thanks for the hard work on the library, seems pretty cool.
I'm using the library and I would like to query my recent listened tracks. I know there is a method for that
current_user_recently_playedbut it requires the spotipy client to have a current user, for that you have to go through a auth2 process (If I'm not mistaken). I would like to be able to query my own user recent songs without going through the manual authentication phase as I want to automate this in a script. If I could automate the authentication with a personal token that would work for me.Is there a way to do that with this library? I thought I could probably generate an auth2 token from spotify and use it as seen in their example: https://developer.spotify.com/console/get-recently-played/?limit=&after=&before= but the tokens there expire in less than a day and I haven't seen any other way.
Best,
Jaime
@stephanebruckert commented on GitHub (Apr 18, 2021):
You have to go through the oauth process just once. Then re-running the script at any time will use the refresh_token to build a new token that will be valid for 1 hour.
@jiwidi commented on GitHub (Apr 18, 2021):
That token will only be valid for 1 hour? Is there a way to extend it?
@stephanebruckert commented on GitHub (Apr 18, 2021):
It will automatically refresh so you won't have to worry about it
@jiwidi commented on GitHub (Apr 18, 2021):
Sorry I didnt phrased it correctly. Is there any way to extend how long it will last so I dont have to refresh it every hour by running the script? I was thinking on running this script daily but will have to cut it down to hourly if the token can only last 1 hour without refresh
@stephanebruckert commented on GitHub (Apr 18, 2021):
If the token expires, spotipy will automatically use the refresh token to retrieve a new token. And that refresh_token never expires! In your case running it daily will just work
@jiwidi commented on GitHub (Apr 18, 2021):
Hi again,
How should I instantiate the spotipy client for it to use the refresh token? My token just expired and it didnt automatically ask for refresh token.
Script code:
The token I'm using there I got it from the following script:
Should I instantiate spotipy client differently in my script? Or what am I missing so the client refreshes the token by itself.
@Peter-Schorn commented on GitHub (Apr 18, 2021):
Don't use
prompt_for_user_token; it's been deprecated because it does not automatically refresh the access token. Instead, do this:The token info will be saved to a file and automatically refreshed when necessary.
@stephanebruckert commented on GitHub (Apr 18, 2021):
Yes ⬆️
I also see you are passing the token through an environment variable and I guess you are doing that to pass the token from your local machine to the server? Depending on where your app will be deployed, you will have to adapt the code a bit:
open_browser=Falseif you have access to a terminal on the server side, this way the login URL will be printed instead of opened,Where do you plan to deploy your code?
@jiwidi commented on GitHub (Apr 18, 2021):
I see, for what I have just tested if that file is missing it will ask for authentication again right? I'm planning to run this script with github actions so its going to be a spin up VM and state won't be maintained between runs (neither I want to save the file in the repo)
Is there any way to save the refresh token and pass it to the SpotifyOAuth/CacheFileHandler every time? This way I can save the refreshtoken as a github repository secret and the main token will be refreshed every execution.
edit: Now that I think about it there could be a workaround where I save the whole file content as a secret in the github repository, save it as a file in running time and save the values again when finished. This is an option in case the refresh token secret can't work.
@jiwidi commented on GitHub (Apr 18, 2021):
I plan to run it with github actions so saving into a common cache file shared between executions is a no go. Unless there is a way to pass the refresh token to SpotifyOAuth(then I can use github repo secrets to do so) instead from reading from a file I think is hard.
The other idea is to save the whole file content as a secret and save it to file during script execution time.
@stephanebruckert commented on GitHub (Apr 18, 2021):
The github action use case is an interesting one... because indeed the state is not saved between runs. I am not certain that using the same refresh_token as a GHA secret will work, I would bet that it is invalidated as soon as it is used.
Here is another suggestion... It's usually not something I would recommend for production code, but it looks perfect for the CI use case. There is a way to get a user token that is valid for 1 year (instead of 1 hour). It has to be manually retrieved from the cookies. Have a look at https://github.com/enriquegh/spotify-webplayer-token. You could just store it as a GHA secret and then pass it to spotipy as you initially did:
@jiwidi commented on GitHub (Apr 18, 2021):
That is a good solution yeah, if I can't make the secrets work will probably go with that one. I think I could update the secret with a new refresh token if that is generated when one is used. Is the
.cache-usernamefile containing REFRESH_TOKEN updated with new refresh token when this one is used?I was thinking how could the github action look and this is so far what I have
@Peter-Schorn commented on GitHub (Apr 18, 2021):
I don't think it's possible to update the value of a secret during/after the execution of a workflow. The github docs don't say anything about this. Saving the token info to a file in the repository during the workflow is pointless because the file won't persist after the workflow completes.
@jiwidi commented on GitHub (Apr 18, 2021):
With a quick Google search I found some actions that do it: https://github.com/hmanzur/actions-set-secret. Haven't gone too much detailed inside the code but I guess I could get the required code to do what I suggested.
Edit: quick way to make it work would be to just replace the value passes to the action with the result of "cat cache file"
@Peter-Schorn commented on GitHub (Apr 18, 2021):
Well, then, this makes things much simpler. All you need to do is create a custom cache handler that retrieves and saves the token info to the secrets API.
Then create your instance of
Spotifyusing the cache handler:@jiwidi commented on GitHub (Apr 18, 2021):
Such a clean solution! Will try implement it :)
@Peter-Schorn commented on GitHub (Apr 18, 2021):
You'll have to use the secrets API directly because you need to call it from within your python script (as opposed to using a github action).
@stephanebruckert commented on GitHub (Apr 18, 2021):
@Peter-Schorn great idea!
@jiwidi if you manage to do this, feel free to open a PR to add a GithubSecretsCacheHandler.
This is something we could even use for Github Actions in the current repo, as we are not currently running integration tests automatically.
@jiwidi commented on GitHub (Apr 18, 2021):
Sure, will do!
@Peter-Schorn commented on GitHub (Apr 18, 2021):
It looks like there is a python wrapper for the github API: https://github.com/PyGithub/PyGithub
@jiwidi commented on GitHub (Apr 18, 2021):
@Peter-Schorn @stefanondisponibile
I'm now working in the implementation and it can be done in different ways, with a PR in mind to add this secretCacheHandler, would you guys prefer to do the requests manually or use the github api?
Both have benefits, without the github API you don't add an extra requirement and without it your request is easier to become obsolete in the future as the API would presumably keep updating.
I really don't mind which but since it will go for PR you probably have some preferences
@stephanebruckert commented on GitHub (Apr 18, 2021):
Just use the library, that's what it's for!
@jiwidi commented on GitHub (Apr 18, 2021):
I think I found a bug on their API because they list the
create_secret()method and define it in the code but the callable is missing. Maybe the missed to include it in a init file or something, opened an issue on their repo https://github.com/PyGithub/PyGithub/issues/1923Hopefully I missed something and is an easy fix :/
@Peter-Schorn commented on GitHub (Apr 18, 2021):
It's not a bug; you're looking at an unreleased version of the repository. To install the latest commit from master:
@jiwidi commented on GitHub (Apr 18, 2021):
I thought the documentation would only include changes from the latest released versions, mistake then!
@felix-hilden commented on GitHub (Apr 19, 2021):
Just to give my two cents, I've used the same Spotify refresh token for API testing for essentially over a year now with daily runs. It truly does never expire! There's no limit on how many tokens can be requested, hence it's great utility for serialisation and databases. PKCE refresh tokens do expire after the first refresh though, so don't use them.
@jiwidi commented on GitHub (Apr 19, 2021):
So I have a working script now:
And the github action that triggers it:
Will do some more testing and open a PR if all is good.
@Peter-Schorn commented on GitHub (Apr 19, 2021):
You need to store the token info as a property in your cache handler. In your version, after the token gets refreshed, you're still retrieving the old token info from the environment in
get_cached_token. This means that the token will get refreshed before every single call to the Spotify web API.@jiwidi commented on GitHub (Apr 21, 2021):
@Peter-Schorn Sorry I dont follow.
Shouldnt
get_cached_tokenretrieve it from enviorment? In what order aresave_token_to_cacheandget_cached_tokencalled? I thoughtget_cached_tokenwill be called first (meaning you need to read the secret) and after that the token would get refreshed, then the manager callssave_token_to_cachewith the new value and not the old one fromget_cached_token@Peter-Schorn commented on GitHub (Apr 21, 2021):
See my version and the tests for it.
Here's what happens in your version:
SPOTIPY_CACHEsecret and stored in the environment variable of the same name, although these aren't the same things. This is the only time that this environment variable is set.During the workflow you make a request to an endpoint (e.g.,
Spotify.search). Before making the request, a call to your cache handler'sget_cached_tokenmethod is made in order to retrieve the token info:github.com/plamere/spotipy@c4f6a3fa4b/spotipy/oauth2.py (L507-L513)Your cache handler's
get_cached_tokenmethod retrieves the token info from theSPOTIPY_CACHEenvironment variable.Suppose the token info is expired. Then, a call to
refresh_access_tokenis made in order to refresh the access token. At the end of this method your cache handler'ssave_token_to_cachemethod is called in order to save the new token info to the cache. Crucially, you make a call toself.repository.create_secretin order to update the token info in the repository secret, but theSPOTIPY_CACHEenvironment variable stays the same.The next time you make a request to an endpoint, your cache handler's
get_cached_tokenmethod is called again to retrieve the token info. It returns the expired token info from theSPOTIPY_CACHEenvironment variable, which was never updated. This means the token info has to be refreshed again.This process repeats for each call to an endpoint. Your cache handler always returns the now-expired token info from the environment variable.
@Peter-Schorn commented on GitHub (Apr 21, 2021):
What you must understand is that the auth manager will not store the token info in memory.
get_cached_tokenwill be called before every request is made.@stephanebruckert commented on GitHub (Jul 9, 2024):
Closing as a bunch of options were provided