How do I use oAuth with spotipy on headless device? - python

I want to create a simple app that tracks how many minutes I listen to music on Spotify every day. To my knowledge, I need to use oAuth to receive this data (user-read-currently-playing). I am currently authenticating like this:
token = util.prompt_for_user_token("<username>", scope, client_id="<clientID>", client_secret="<client_secret>", redirect_uri="http://localhost:4466")
spotify = spotipy.Spotify(auth=token)
I know that it works because if I run it on Windows where I have a graphical display, everything is just fine and I can get the redirect Url and the auth code from the browser the login page opens in. Is there any way to get this code on a headless linux machine?

I found a solution to this problem:
Instead of using
token = util.prompt_for_user_token("<username>", scope, client_id="<clientID>", client_secret="<client_secret>", redirect_uri="http://localhost:4466")
spotify = spotipy.Spotify(auth=token)
You can use
spotify = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id="id", client_secret="secret", redirect_uri="http://localhost:4466", scope=scope, open_browser=False, ))
This achives the same goal. To authenticate in a headless envirement, you can copy the cashed Auth from for example a windows machine to your Linux machine as long as they are both in the folder cmd is opened in.

Related

Spotipy redirect uri opening on server instead of users browser?

I built a web app using Django and the wrapper for the Spotify api, Spotipy, and deployed it to Heroku. The problem I am facing is that the redirect uri opens on the machine running the code, which in this case is the linux server used by heroku. Because of this, the user never actually sees the page prompting them to authenticate the app and login to their Spotify accounts, resulting in a request timeout from Heroku. This happens when my REDIRECT_URI is set to http://localhost/. I have tried to set the REDIRECT_URI to https://nameofmyapp.herokuapp.com which then resulted in an EOFError from the Spotipy module. I have not been able to find a solution for this. For context, my authentication flow is set up as follows:
def index(request):
cache_handler = spotipy.DjangoSessionCacheHandler(request=request)
auth_manager = spotipy.oauth2.SpotifyOAuth(
env("CLIENT_ID"), env("CLIENT_SECRET"), env("REDIRECT_URI"), scope=env("SCOPE"), cache_handler=cache_handler)
session = spotipy.Spotify(
oauth_manager=auth_manager, requests_session=True)

Spotify / Spotipy web api access token authorization problem running on Google Cloud Function

Im creating a Python script which requests user data from my Spotify account.
This is the piece of my code which gets the access token:
def access_token():
redirect_uri="http://localhost:8080"
scope = 'user-read-recently-played'
obj = spotipy.oauth2.SpotifyOAuth(client_id=CLIENT_ID,client_secret=CLIENT_SECRET,redirect_uri=redirect_uri,scope=scope)
token = obj.get_access_token(as_dict=False,check_cache=False)
return token
Locally when my redirect_uri was http://localhost the script would open a webpage and I would have to copy the url and paste it as an input back in my python script in order to acquire the access token.
screenshot of this
Im obviously trying to automate this so I changed the uri to http://localhost:8080.
This would then open the webpage but immediately close and I would have the access token returned in my script without having to paste the url.
When I run this locally this works fine but when I run it in a Google Cloud Function it times out . I get this info log:
User authentication requires interaction with your web browser. Once you enter your credentials and give authorization, you will be redirected to a url. Paste that url you were directed to to complete the authorization.
any suggestions to fix this as its not an error but it times out my function.

Python Spotify API How to pass variable into the input prompt from the util.prompt_for_user_token response

I am working to create a pipeline with the spotify API that logs my streaming history. I am planning to automate it by uploading it as a lambda function and scheduling it to run every few hours. I have everything mostly in order, except for that on the first run the API requires web authentication. Here is my code:
import spotipy
import spotipy.util as util
import urllib3
un = USERNAME
scope = 'user-read-recently-played'
cid = CLIENT_ID
csid = CLIENT_SECRET_ID
redr = r'http://localhost:8888/callback/'
token = util.prompt_for_user_token(un,scope,cid,csid,redr)
When this is run for the first time, this message pops up:
User authentication requires interaction with your
web browser. Once you enter your credentials and
give authorization, you will be redirected to
a url. Paste that url you were directed to to
complete the authorization.
Opened <LINK HERE> in your browser
Enter the URL you were redirected to:
And then I have to copy the link from my browser into that space. I can get the URL that I need to paste using urllib3:
req_adr = ADDRESS_IT_OPENS_IN_BROWSER
http = urllib3.PoolManager()
resp = http.request('GET',req_adr)
redrurl = resp.geturl()
But I don't know how to pass it into the input prompt from the util.prompt_for_user_token response
Any suggestions would be very welcome.
So it turns out there is a workaround. You can run it one time on a local machine and that generates a a file called .cache-USERNAME. If you include that file in your deployment package you don't have to copy/paste the URL and it is able to be automated with a lambda function in AWS.

write a script to send files to box application by automatic developer token generation

Requirement: I need a script that sends files to box.
So far, i managed to send the files to box by following https://docs.box.com/docs/getting-started-box-integration . I am using box-python-sdk to acheive this, but i have to use this developer token which is active only for 60 min for authenticaton. I have to generate a developer token everyday to run this script.
oauth = OAuth2(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
access_token=DEVELOPER_TOKEN,
)
client = Client(oauth)
I cannot set the redirect URI as am not running an application on a server, am just running this script using "python box.py ". Is there a way to refresh the developer token in my script?
This can be achieved using JWT authentication, refer https://github.com/box/box-python-sdk.

Cannot get authentication with google api from python script to work - Error: redirect_uri_mismatch

I am trying to create a trivial python script that allows me to bulk add a list of youtube videos to a playlist of mine.
The problem I am having is getting this script to get authenticated to the google api with my apps credentials.
I am basically just using the sample authentication script at https://developers.google.com/google-apps/calendar/quickstart/python
and this stackoverflow question (Adding youtube video to playlist using Python)
The main stopping point is that I keep getting an Error: redirect_uri_mismatch. Since I am calling the script from the commandline on my laptop, the error is saying: The redirect URI in the request: http://localhost:8080/ did not match a registered redirect URI.
I have set http://localhost:8080 as the JavaScript origins and http://localhost:8080/oauth2callback as the Redirect URIs
And i am using the following (as run from the python shell):
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client import tools
from oauth2client.tools import argparser, run_flow
import argparse, sys, os
flow = flow_from_clientsecrets('path to my CLIENT_SECRETS.json file', scope='https://www.googleapis.com/auth/youtube')
store = Storage('config/%s-oauth2.json' % sys.argv[0])
parser = argparse.ArgumentParser(parents=[tools.argparser])
flags = parser.parse_args()
credentials = run_flow(flow, store, flags)
then the terminal opens my browser and in the browser I get the 400 error. The following gets printed to the terminal:
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=my-CLIENT-ID&access_type=offline
If your browser is on a different machine then exit and re-run this
application with the command-line parameter
--noauth_local_webserver
I am not sure what I am really supposed to be putting as the redirect URIs and javascript origins, but I don't intend to run this anywhere else other than as a python script from the terminal of my laptop. The documentation provides https://example.com/ and https://example.com/oauth2callback as pre populated values, but clearly that's not where I am running this "app" from and I know that's just placeholder stuff.
UPDATE: not sure why, but i realize that the url the app is sending me to has the redirect_uri parameter set to just http://localhost:8080/, if i add oauth2callback to the uri than i get sent to the screen where it asks me to accept management of the youtube account. so that's odd.
UPDATE 2: and if I change my redirect uris to just http://localhost:8080/ via the developer console, i can get my credentials, but I am sure this is not the best way to be going about this.
If you are just running this through you terminal than you can use the native host by creating a client ID as an installed app and then selecting other. If you are trying to do this using the web app client ID and only want it to be local then you would use these:
JavaScript origins: http://localhost:your_port_here/
Redirect URIs: http://localhost:your_port_here/url_path
where url_path is the place you want google to send you after authentication.
Edit: the tutorial code only works if you are using a native app. If you are indeed planning to create a web app there are separate instructions.
The redirect_uri parameter set to just http://localhost:8080/ is by design. When you call tools.run_flow() it is spinning up a server of it's own behind the scenes and initiating the oauth flow. It is then expecting the redirect_uri to redirect back to the server it spun up (which is listening on port 8080) so that it can use the access_token it receives to create the credentials and put them in storage.

Categories

Resources