Spotipy -- accessing tracks from a public playlist without authentication - python

I want to search through public playlists and get the tracks. So far I have code which can get the names of the playlists but not the tracks:
import spotipy
import sys
sp = spotipy.Spotify()
if len(sys.argv) > 1:
artist_name = ' '.join(sys.argv[1:])
results = sp.search(q=artist_name, limit=20, type='playlist')
for i, t in enumerate(results['playlists']['items']):
print(i,' ', t['name'])
This will print a list of the first 20 public playlists names given the search condition. What I want is to also print the tracks in each playlist! I thought this would be simple, but after searching it seems like the only way is to via authentication, which I do not want. These tracks are public, so why would I need to authenticate to list the tracks?! There are two reasons I think this. 1) if I add (in the loop):
print t['tracks']
the request response says "This request requires authentication". Additionally, I found this example on the spotipy documentation which is exactly what I want, but only for authenticated users. https://github.com/plamere/spotipy/blob/dd021c4087981b583ef0f2b276cd43bbc6fd429f/examples/user_playlists_contents.py
So, is there any way to view the tracks without authenticating as the owner of that playlist? Opening the desktop Spotify app can quickly show anyone that public playlist tracks are completely searchable and viewable so it must be possible.
I apologize if this is an extremely specific question -- but I'm not sure where else to ask seeing as this is my first time with this API or with an API like this at all. I have done quite a bit of research on this topic and now have resigned to asking for help.

This is a typical OAuth confusion. There are potentially three parties involved here.
Your application (that tiny little python snippet above)
Spotify Web API
A Spotify user
If your app wanted to find and delete a Spotify user's playlists that begin with X, the Spotify Web API would demand that your app first nicely ask the user for permission to do that. Feels natural...
In this scenario, your app Playlist X Deleter first has to authenticate to prove that it actually is Playlist X Deleter. The user then needs to authenticate with Spotify to prove that it actually is the user the Playlist X Deleter wanted to delete playlists for. Then, the user who we now know who it is needs to authorize Playlist X Deleter that we now know who it is to delete playlists.
So, you have an app that authenticates and a user who authenticates.
For information that is public, there is no obvious reason why a user needs to authenticate. There is also no obvious reason why an app needs to authenticate. However, Spotify has decided that the app must authenticate to get public playlist information. Maybe so it can disable bad users who spiders too much playlist data or otherwise abuse the api.
In this case, since there are no private playlists involved, and only read rights, no user needs to authorize anything. In the OAuth world, this is called client credentials flow https://www.rfc-editor.org/rfc/rfc6749#section-4.4
Go to the developer console and create an application to get a client_id and client_secret:
https://developer.spotify.com/my-applications/#!/applications/create
Then follow:
https://developer.spotify.com/web-api/authorization-guide/#client_credentials_flow
or in your case, supply the client_id and client_secret to spotipy through the SpotifyClientCredentials
doc: http://spotipy.readthedocs.io/en/latest/#spotipy.oauth2.SpotifyClientCredentials
example snippet (that doesn't fill in anything though): https://github.com/plamere/spotipy/blob/master/examples/client_credentials_flow.py

Related

How exactly should JWT-based authentication be implemented in Django (drf and simplejwt)?

I am struggling to understand exactly how JWT-based authentication should be implemented in Django (I am using simplejwt). I am just a beginner, so please brace yourselves for some silly questions. The rest-framework-simplejwt documentation is very minimal and does not provide enough detail for a newbie like me.
path('token/obtain', jwt_views.TokenObtainPairView.as_view(), name='token_create'),
path('token/refresh', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
So, I've created the paths in my urls.py as suggested by the official documentation. Where do I go from here? I guess my confusion comes from the fact that I am not sure where exactly in the code I have to issue my tokens. Let's say, I am logging in the user. So, in order to obtain the token, do I have to send a request to the 'token_create' endpoint from inside my view? Or do I have to somehow indicate it in one of my serializers? What about the 'refresh_token' endpoint? Is there a specific method that I need to use?
Then, what do I do with the token once it has been issued? Clearly, I shouldn't save it in the database since it defeats the entire purpose of using JWTs in the first place. From my understanding, I should attach it to the headers so that the subsequent requests by the user contain the tokens in the headers.
The frontend will be written in ReactJS and will be on a separate server from my Django backend API, and the communication between the two will be configured through CORS.
In this case, how do I attach the token to the headers and make it so that the user's browser sends in the token with each request? Is there some sort of package that could be useful for that?
I think you just mixed everything up, I'm gonna explain everything however you may already know some stuff.
JWT simply is a way to authorize users, you usually create an endpoint to create a token for the users, this endpoint can be named login, create_token, 'generate_token', or anything! doesn't really matter!
However maybe if u use a specific library maybe it forces you to use a specific endpoint but in Flask it's really what you like.
This login (whatever you call it) endpoint will take a username and password and checks if it exists and it's correct, then generates a JWT with a library like PyJWT, You can configure the JWT to be expired in for example 20 mins or more, then you encrypt a dictionary(JSON?) which usually contains user_id which you query from the database. example of the JSON you provide to the user with:
{
"user_id": something,
"role": something,
...
}
Then it will be encrypted to a long string.
now when the user sends a request, he/she needs to have that long string as the Authorization header of the request.
In postman --> Authorizations, choose Bearer Authorization and then insert that long string.
We also give the user a refresh_token.
This is the example of the JSON you provide the user with when he/she calls the login endpoint:
{
token: some_long_string,
refresh_token: some_long_string,
}
So what is refresh Token?
it's just the token that when the main token expires instead of making the user enter username and password again, he just sends the refresh token we gave him while he called login.
One more point: This was the whole flow and logic you need to implement. Do it as you like, libraries or anything you like, doesn't really matter.

Getting a Facebook page access token for a simple app (Python)

I'm trying to create a very simple Facebook app (using the Python SDK) that does nothing more than post to its own page. The eventual app will make one post per day, and that's all it will do. (Please note that I am a novice programmer, and this is in part a learning exercise for me.)
My initial test code looks like this, and it successfully posts to the page:
import facebook
token = 'XXXXX'
graph = facebook.GraphAPI(access_token = token,
version = "2.1")
graph.put_object(parent_object='me',
connection_name='feed',
message='Test post to page')
The catch is that it only works if I plug in a value for token that is a valid page access token. For testing, I can get one from the Graph API Explorer, but obviously I'd like my app to be able to get one each time it runs, using its own credentials (e.g. app ID and app secret).
I have been searching for a way to do this with the Python SDK, but I have had no luck finding out how, in part because most apps are much more complicated (involving user logins and so forth). I don't see Is there a simple way to do this, or is the problem more complicated than I think it is?
There is no way to auto-generate a Page Token, but you can use an Extended Page Token - it is valid forever.
More information:
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
http://www.devils-heaven.com/facebook-access-tokens/
Token debugger: https://developers.facebook.com/tools/debug/accesstoken/

Failing to pull a sampling of Twitter users

I am doing a project for which I need a fairly small number of random Twitter users (about 20 for now) with a near-identical number of followers (within 45000 - 55000 for example). I brushed up on my Python, got Twython set up, and did some test runs and successfully queried the Twitter API for the list of a users followers and such.
Then I tried to just randomly search for users. I thought that I would just search for users where (q = " "), loop through them, and stop upon reaching my goal of 20 unique users.
However, I came across an error saying "Twitter API returned a 403 (Forbidden), Tour credentials do not allow access to this resource." When looking around for the issue, it appears that it has to do with the Authentication not having a user-context.
Below is my sample code to tell if I am pulling names, but I have a few questions:
What is the difference (in Twitter's context) in Oauth 1 and 2?
for someone not looking to develop an app but rather just pull some data, why would I need a user-context? I am not posting anything on anyone's behalf!
How do I go about fixing the issue (or is there a better way of doing this)?
Thanks!
from twython import Twython
APP_KEY = 'redacted'
APP_SECRET = 'redacted'
twitter = Twython(APP_KEY, APP_SECRET, oauth_version=2)
ACCESS_TOKEN = twitter.obtain_access_token()
twitter = Twython(APP_KEY,access_token=ACCESS_TOKEN)
print "hello twitterQuery\n"
search = twitter.search_users(q=' ')
for user in search['ids']:
print twitter.show_user(user_id=user)['screen_name']
print "\ndone"
I can't really answer everything you have asked, but I'll try here:-
In OAuth1 in twitter, access codes were for a lifetime, i.e., would never expire. In OAuth2, there are refresh codes, that are used for new access codes, after previous ones expire. There are many other differences, but this is what really stuck out to me in a Twitter context. You could look at these links to get more details.
How is OAuth 2 different from OAuth 1?
http://hueniverse.com/2010/05/introducing-oauth-2-0/
http://net.tutsplus.com/tutorials/oauth-2-0-the-good-the-bad-the-ugly/
This, I guess, is just Twitter trying to be more secure. I cannot think of any other reason for this.
I don't know about a solution, but maybe as a workaround, you could try and gather users from the followers list of some popular account, like Twitter's official account. You will get a wide range of users to choose from. Just retrieve the list and choose random users from it.

getting information from all users of my facebook app

I'm doing some research, where I have a facebook app, that asks for some permissions on the users facebook to get some basic information.
I can see that my app has about 600 users, and I'd like to query them, to see some patterns in the users. i.e. how many friends do they have, how long messages do they post in updates etc.
My question is: Do I have to copy the data when the user first visits my app and grants access to his information, or can I query it as long as the user hasn't "removed" my app.
I hope the second option will be true, since I have a lot of considerations about "copying" user data, and storing it in a database - primarily ethical but also related to security issues, compliance, resources so on and so forth.
the programming language is not important, but if anyone needs to exemplify, lets say it's python.
NO. You don't have to copy the data.
You can query Facebook as long as you have a valid access token regardless of whether the user is online or offline.
However, the only thing you need to take care of is handling of expired access token, because in that case the user will need to re-authorize your application for you to get the access_token.

Having trouble installing SimpleAuth for GAE

I have been working for a while, trying to install SimpleAuth on Google App Engine and I am running in to trouble. First off in the bottom of the sample code they have this:
def _get_consumer_info_for(self, provider):
"""Should return a tuple (key, secret) for auth init requests.
For OAuth 2.0 you should also return a scope, e.g.
('my app id', 'my app secret', 'email,user_about_me')
The scope depends solely on the provider.
See example/secrets.py.template
"""
return secrets.AUTH_CONFIG[provider]
and I don't see the secrets file anywhere nor what it is supposed to do.
Then in addition to that small problem I am curious how I am supposed to render the providers and their login URLs to the user. This page: https://github.com/crhym3/simpleauth/blob/master/example/handlers.py has a great description of the general setup but it doesn't have any description of what we actually need to pass to the user to let them login.
Thanks!
First off, please take into account that it's just an example, so some code parts were simplified for the demo purposes.
secrets is a separate module. The README file says to copy secrets.py.template into secrets.py and set proper client/consumer ids and secrets. Again, see README for info on where to get client/secrets for different providers.
The rendering is up to you. What I did as an example is this:
<p>Try logging in with one of these:</p>
Google
Facebook
Yahoo! (OpenID)
Twitter
LinkedIn
Windows Live
Those /auth/... links should get routed to your handler (normally webapp2.RequestHandler or some subclass) that's mixed in with SimpleAuthHandler.
You can see the example app live at https://simpleauth.appspot.com, hopefully it'll clarify things.

Categories