Working on a small app that takes a Spotify track URL submitted by a user in a messaging application and adds it to a public Spotify playlist. The app is running with the help of spotipy python on a Heroku site (so I have a valid /callback) and listens for the user posting a track URL.
When I run the app through command line, I use util.prompt_for_user_token. A browser opens, I move through the auth flow successfully, and I copy-paste the provided callback URL back into terminal.
When I run this app and attempt to add a track on the messaging application, it does not open a browser for the user to authenticate, so the auth flow never completes.
Any advice on how to handle this? Can I auth once via terminal, capture the code/token and then handle the refreshing process so that the end-user never has to authenticate?
P.S. can't add the tag "spotipy" yet but surprised it was not already available
Unfortunately, the spotipy util function only returns the access_token, not the all-important refresh_token. The access_token will expire after a limited amount of time. At that point, you'll need to create a new access_token using a refresh_token.
I did not see any public functions in spotipy that allow you to grab the refresh_token. However, you can always create a new access_token with the following components:
Your Spotify client id (found on your app page)
Your Spotify client secret (found on your app page)
Your Spotify refresh token - See here for a way to get that ONCE -
https://developer.spotify.com/web-api/tutorial/
Word to the wise, when debugging I requested a new access_token using POSTMAN to POST to https://accounts.spotify.com/api/token - it only worked after specifying in the headers
'Content-Type': 'application/x-www-form-urlencoded'
I once ran into a similar issue with Google's Calendar API. The app was pretty low-importance so I botched a solution together by running through the auth locally in my browser, finding the response token, and manually copying it over into an environment variable on Heroku. The downside of course was that tokens are set to auto-expire (I believe Google Calendar's was set to 30 days), so periodically the app stopped working and I had to run through the auth flow and copy the key over again. There might be a way to automate that.
Good luck!
Related
I have a Python script that should download data from a web resource using link. It so happened that resource is in Azure App Service protected by Active Directory. My user account is allowed to access the link and download data (I can do it from web browser manually, but want to automate this process). The Python script uses requests library. I can't figure out how to authenticate properly, cause when I'm trying to run the script, I get:
Error 403 - Forbidden
The web app you have attempted to reach has blocked your access.
Usual authentication with requests doesn't work (using auth parameter or session.auth or with HttpNtlmAuth).
I know one can use VS Code to authenticate to Azure and then use DefaultAzureCredential, but I can't get where you should use this DefaultAzureCredential object (cause it doesn't work with requests).
I don't need the whole Python app to be registered or somehow else recognizable by Azure resource. It's just a script to download data, that is not supposed to be productionized.
Any ideas how I can scrap the data from Azure?
Note: I'm not an admin or creator of this Azure App, so can't change any restriction settings.
In short, the part of script making request looks like:
params = {"param1": param1,
"param2": param2}
session = requests.Session()
session.auth = HttpNtlmAuth(USERNAME, PASSWORD)
url = "my-app.azurewebsites.net/the-rest-of-the-path"
response = session.get(url, params=params, verify=False)
If you want to access the Azure App Service, you have to authenticate the Azure App Service. If you don't have access for Azure App Service, we cannot access the Azure resources.
Genereally, when a web server stops you from accessing the page you're trying to open in your browser, you'll get a 403 Forbidden Error. There isn't much you can do most of the time. However, occasionally the issue is on your end.
Here are some points that can cause this error.
If you have an open public API and public access is not allowed on Azure App Service.
Your app's IP address, which you're using to call the app service, isn't whitelisted.
If you have a gateway in the middle, it's possible that it's also blocking your calls.
Here are the possible solutions that you can try:
Remove the access restrictions from your web app's Networking page.
Try adding 0.0.0.0/0 to give access to all. You can later add restrictions based on your needs.
The order of the restrictions is important, so double-check it. It may have an impact if you have a blocked call before an approved call.
You can also have restrictions based on http-headers like X-Forwarded-For. Please double-check that. This can also happen in code, depending on how you handle errors.
Protocol support for HTTP headers in Azure Front Door | Microsoft Docs
Chech this, if your API is behind the Gateway Application Gateway integration with service endpoints
I am writing a simple Twitter authentication flow with a REST API setup. Client side is just plain javascript/Vue code - there is no server-side rendering. This consumes a backend REST API built with Django Rest Framework, using tweepy library to wrap the Twitter API.
I have the authentication working, with the following steps:
User clicks a 'log in to twitter' button, which fires a call to my backend API /get-url/
API calls Twitter's get_authorization_url (using my Twitter app credentials), gets the token, and returns this redirection URL to the client
Client redirects user to the Twitter URL to complete authentication
On callback, client passes all params thru to backend API endpoint
API gets token and secret; creates a tweepy API with user auth; and calls verify_credentials
If everything worked fine, we create a user account in a Django database tied to the Twitter user, storing their token and secret; logs the user in with a JWT; and returns a 200 success with token.
Front end deals with doing JWT token refreshing etc; but otherwise uses this for authentication on the rest of the API.
However, there is one bit I'm stumped on: The Twitter docs suggest that in my step 2, I should save the request_token so that, on step 5, I can check it matches what is returned from the Twitter API (https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter).
The tweepy docs example (http://docs.tweepy.org/en/latest/auth_tutorial.html) suggests storing it in the session, then on callback checking them and deleting from the session.
However, this doesn't make sense (at least to me) in a REST API setup like mine. I'm stumped on how to temporarily store this on the server so that on callback I can check its value - prior to the redirect, I know nothing about the user to "tie" this token to, there is no user record to store in the database.
All I can think to do is for the API on (2) to return it to the client; then it can be stored in a cookie before redirect; then on callback, pass it back to the server... but this seems very convoluted and doing it all in plain text I assume nullifies the value of doing this extra check.
Hopefully I'm missing something obvious here.
Have you tried using python-social-auth library?
from_the_docs: twitter is in supported Authentication Backends.
You can try letting the user register with basic details, then have a 'link to Twitter' button that shows they have to activate their twitter connection to do anything else on your web app
I have developed a simple Django app, using Spotify API and Spotipy Authorisation (authorisation flow). This runs a localhost server where I click a simple button which creates a playlist in Spotify.
My issue however is in setting this up for an alternative user to login via their credentials and gain authorisation.
Atm, I have set this app up using a hardcoded cid and client secret within the views.py module (in the backend). This uses the following code to gain auth.
token = util.prompt_for_user_token(username, scope, client_id= cid, client_secret= secret, redirect_uri=r_uri)
My index.html file then links a button to this script so that when clicked, the playlist is created. I expect this index.html needs to be updated to allow the user to login to their own spotify account and to authorise their token. However I am unsure on how to update this or if I am on the right track.
Alternatively, I think I may need to restart the project using java to gain authorisation for another user or using Implicit Grant Auth method, if spotipy authorisation cannot be used.
You won't be able to use prompt_for_user_token for this because it is a helper meant to be used locally by a single user and will block the app if the signin process is not completed.
Have a look at this Flask python app and adapt it to make it work in Django. https://github.com/plamere/spotipy/blob/master/examples/app.py
It does everything you need:
uses python and spotipy
allows user to login using a link
allows user to do any action by clicking another link
keeps client id and secret on the backend
Have fun!
I am not very familiar with Spottily API , but what i would try to do it to get the user id as describe below:
https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids
from the client to the server using Ajax ,and then in the client
use the the Playlist API:
https://developer.spotify.com/documentation/web-api/reference-beta/#category-playlists
Can’t respond to above comment directly but the flask cache handler can be changed to django cache handler with
https://github.com/plamere/spotipy/blob/master/spotipy/cache_handler.py
I'm writing a opensource app in python following this example:
https://developers.google.com/gmail/api/quickstart/quickstart-python?hl=it
I generated correctly the client_secret.json and ran successfully that example.
Now.. considering I'm starting to write my code and according with google doc:
Warning: Keep your client secret private. If someone obtains your client secret, they could use it to consume your quota, incur charges against your Google APIs Console project, and request access to user data.
so, how can I (in the future) share my app's code and keep at same time the client_secret.json secret?
Ok, I got the answer here:
https://developers.google.com/accounts/docs/OAuth2InstalledApp
This flow is similar to the one shown in the Using OAuth 2.0 for Web
Server Applications, but with three differences:
When creating a client ID, you specify that your application is an
Installed application. This results in a different value for the
redirect_uri parameter.
The client ID and client secret obtained from
the Developers Console are embedded in the source code of your
application. In this context, the client secret is obviously not
treated as a secret.
The authorization code can be returned to your
application in the title bar of the browser or to an http ://localhost
port in the query string.
In other words, if you specify that your project is an "Installed Application" while creating it in the Google APIs Console, you can safely embed secret in your code
I'm using the Google AppEngine 1.3.4 SDK which offers to allow your application to act as a OAuth service provider (http://code.google.com/appengine/docs/python/oauth/). Setting up a standard application on my localhost and using the following:
Request URL /_ah/OAuthGetRequestToken
Authorize URL /_ah/OAuthAuthorizeToken
Access Token URL /_ah/OAuthGetAccessToken
The client application just gets sent to a page requesting to grant OAuth access even though no user is logged in. Clicking 'Grant access' results in a message saying 'OAuth access granted' with no tokens or anything exchange. Can't see how this could work when it's not even prompting for a login.
As this functionality is quite new I can't find much out there. I've created a OAuth provider before in Rails and know that you need a Consumer Key and Secret, something that seems to be lacking in GAE?
Any ideas on how to get OAuth working in a sample GAE project are most welcome.
I would hazard a guess that the SDK implementation simply grants access regardless. It's also possible you still have a dev_appserver login cookie. Either way, try it in production - it'll almost certainly request login in that case.