Spotipy not verifying via Oauth? - python

I'm attempting to write a Python script to create a Spotify playlist via the Spotipy application. I've successfully created an application in Spotify's Dev center and input the necessary variables into Spotipy's example (see below). However, the script is not authorizing properly. I've tried with and without a server running, but to no avail. There are similar questions on Stack but they do not offer complete solutions. Any suggestions would be very helpful.
Here is the message I am receiving via command prompt:
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.
Please navigate here:
https://accounts.spotify.com/authorize?scope=user-library-read&redirect_uri=None&response_type=code&client_id=xxxxx
Enter the URL you were redirected to:
And here is the script that's running. It's nearly identical to that example provided by Spotipy, with a change made for setting os variables for my Windows machine.
import pprint
import sys
import os
import subprocess
import spotipy
import spotipy.util as util
import requests
clientId = 'client id here'
clientSecret = 'client secret here'
clientRedirect = 'http://localhost:8888/callback'
username = 'username here'
scope='user-library-read'
os.environ["SPOTIPY_CLIENT_ID"] = clientId
os.environ["SPOTIPY_CLIENT_SECRET"] = clientSecret
os.environ["POTIPY_REDIRECT_URI"] = clientRedirect
token = util.prompt_for_user_token(username, scope)
if token:
sp = spotipy.Spotify(auth=token)
results = sp.current_user_saved_tracks()
for item in results['items']:
track = item['track']
print track['name'] + ' - ' + track['artists'][0]['name']
else:
print "Can't get token for", username

The application is asking a URL that should contain a "code" which will then be used to exchange with access_token as mentioned in Step.3 in https://developer.spotify.com/web-api/authorization-guide/ and the URL should look like this https://example.com/callback?code=NApCCg..BkWtQ&state=profile%2Factivity. I hope you are entering your credentials properly otherwise you will never get the code to proceed further.

Related

Is there another reason for Illegal redirect_URI error when using Spotify API?

I am trying to use the Spotify API (using Spotipy), however I am having issues with the authentication step. I am following along a youtube playlist to learn it. To do that, I am just following along with the code that is shown below. However, when it opens into my web browser for authentication, I get an "Illegal redirect_uri" error.
I tried searching the web and came across this answer that says that it is probably a typo in the redirect_URI on the spotify website or that has been set in my environment variable, however, I have quadruple checked to make sure there was no typo. An image is attached that shows what my environment variable is and what the redirect_URI is set as in spotify.
Is there another reason that I could be getting this error?
Thank you for the help. Spotify Redirect_URI
import os
import sys
import json
import spotipy
import webbrowser
import spotipy.util as util
from json.decoder import JSONDecodeError
#Get the username from terminal
username = sys.argv[1]
# Erase cache and prompt for user permission
try:
token = util.prompt_for_user_token(username)
except:
os.remove(f".cache-{username}")
token = util.prompt_for_user_token(username)
#Create our spotifyObject
spotifyObject = spotipy.Spotify(auth=token)
It is probably a security issue, since google.com will not understand the parameters of the request sent by the Spotify API. It looks like you are not trying to intercept the request (since you are using google.com), so you could try to use https://localhost:8080/ as the redirect url. Since there is (probably) no server running locally, no page will open (and you will get an error), but you only need to copy the url in the address bar ;-)

Spotify Authentication Flow (Spotify API)

I'm trying to allow users to login with Spotify (using the Spotipy library) to provide authentication for creating a playlist on their account and populating the playlist. After the user has logged in, I will display the playlist they have just created in the redirect template via an embedded Spotify player (using the playlist ID of the newly created playlist).
I have a form input box in my HTML template which takes input from the user (their Spotify username). I also have a list of Spotify URIs for tracks ready to populate the playlist with.
I followed Spotipy's documentation regarding obtaining a token for users for authentication as follows (I have removed my client-id & secret).. I'm not sure why it isn't working:
import os
import spotipy
import spotipy.util as util
from json.decoder import JSONDecodeError
from datetime import date
#login_required
def save_playlist(request, data='Default_Data'):
username = data.split('/')[0] #spotify username
track_ids = data.split('/')[1:11] #list of spotify IDs for playlist tracks
client_id = '****'
client_secret = '****'
scope = 'playlist-modify-public, playlist-modify-private'
redirect_uri = 'http://127.0.0.1:8000/save_playlist/'
#check if username is already in cache, if not, create cache
try:
token = util.prompt_for_user_token(username,
scope=scope,client_id=client_id,
client_secret=client_secret,redirect_uri=redirect_uri)
except (AttributeError, JSONDecodeError):
os.remove(f".cache-{username}")
token = util.prompt_for_user_token(username,
scope=scope,client_id=client_id,
client_secret=client_secret,redirect_uri=redirect_uri)
sp=spotipy.Spotify(auth=token)
today = date.today()
date_string = (str(today.day) + ' - ' + str(today.month) + ' - ' + str(today.year))
#playlist title
playlist_name = f"GENIE - " + username + ' | ' + date_string
#create a new public playlist to be populated
sp.user_playlist_create(username, name=playlist_name, public=True)
#id of playlist we just created
playlist_id = sp.current_user_playlists(limit=1)['items'][0]['id']
#add playlist tracks to this playlist
sp.user_playlist_add_tracks(username,playlist_id,tracks=track_ids)
return render(request, 'blog/save_playlist.html', {'playlist_id':playlist_id})
When a user enters their username and logins to Spotify, multiple windows keep popping up rather than just one (see terminal below). I believe the issue is somewhere in obtaining the token.
terminal output when attempting to login
I have set the redirect URI in the Spotify developer console to be the same as above ('http://127.0.0.1:8000/save_playlist/').
Thanks in advance!
util.prompt_for_user_token should not be used in a web app that would allow any user to sign in, since we don't know the user's ID/name in advance. It's just a helper to get started quickly locally.
Instead you should use spotipy.oauth2.SpotifyOAuth directly, by specifying a unique cache path for your user. In the case of a web app it would be a session ID.
Here is a complete example made for Flask which you can adapt to your needs https://github.com/plamere/spotipy/blob/master/examples/app.py
Give a try to the OAuth requests-oauthlib
https://requests-oauthlib.readthedocs.io/en/latest/examples/spotify.html
It works like a charm.
Instead of using Spotipy, a quick solution is to go to https://pypi.org/project/spotify-token/ ,it is a Python script that can generate a Spotify token if a Spotify username and password is provided.
With that said, just keep in mind that not everyone will provide their username and password willingly. Cheers!

Extract info from address bar in Python

I'm new to Python, using Python 3.5.1 (windows)
I'm trying to write a code to automate a login module for an API server
The first inputs are an API key and secret which I provide and then I get a URL from the API server and using that we open up the browser pointing to that page which requires us to manually enter the username and password to get authenticated. == so far so good.
Once authenticated the server opens up a webpage and displays a token ref in the url parameters, something like
http://www.xxxx.xx.x.../xxxxxxtoken_ref=a1234xyx
I need to extract the token_ref value and use that for further authentication.
I am trying to use a local server at the redirect IP so I can capture the token_ref using Bottle but I think I am doing something wrong.
My code is below:
from kiteconnect import KiteConnect
from kiteconnect import websocket
from bottle import run , request , route
import webbrowser
login to kite
myapi_key="abcdxyz1234"
myapi_secret = "xxxxyyyyzzzz1234"
kite = KiteConnect(api_key=myapi_key)
url = kite.login_url()
webbrowser.open(url)
get token_request (this is where I'm stuck)
#route('/')
def root():
tk_request = request.query.token_request
return 'the token request is' + tk_request
run()
get access token
user = kite.request_access_token(request_token=tk_request,secret=api_secret)

Getting SoundCloud Access Token with Python

https://github.com/soundcloud/soundcloud-python
I'm using the Python wrapper above, and I am struggling to get the access token.
import soundcloud
client = soundcloud.Client(
client_id=YOUR_CLIENT_ID,
client_secret=YOUR_CLIENT_SECRET,
redirect_uri='http://yourapp.com/callback'
)
redirect(client.authorize_url())
I am able to reach this point and it successfully allows the user to authorize. However I am lost as to how I am supposed to get the access token.
The documentation says the following:
access_token, expires, scope, refresh_token = client.exchange_token(
code=request.args.get('code'))
render_text("Hi There, %s" % client.get('/me').username)
When I use this, it gives me a 500 error.
On redirect client.authorize_url(), the user will be redirected to a SoundCloud connect screen in their browser and asked to authorize their account with your application.
If the user approves the authorization request, they will be sent to the redirect_uri specified in redirect_uri='http://yourapp.com/callback'. From there, you can extract the code parameter from the query string and use it to obtain an access token.
import soundcloud
# create client object with app credentials
client = soundcloud.Client(client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
redirect_uri='http://example.com/callback')
# exchange authorization code for access token
code = params['code']
access_token = client.exchange_token(code)
This is straight from the Server-Side Authentication docs.
You could use selenium webdriver
pip install --upgrade selenium
to open a browser window, log in to the soundcloud account and get the code.
#!/usr/bin/env python
# coding=utf-8
import soundcloud
from selenium import webdriver
driver = webdriver.Firefox(
executable_path='<YOUR_PATH_TO>/geckodriver')
CLIENT_ID='<YOUR_CLIENT_ID>'
CLIENT_SECRET='<YOUR_CLIENT_SECRET>'
REDIRECT_URL='<YOUR_REDIRECT_URL>'
client = soundcloud.Client(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
redirect_uri=REDIRECT_URL)
AUTH_URL = client.authorize_url()
driver.get(AUTH_URL) ## open Firefox to access Soundcloud
code = raw_input("WAITING FOR ACCESS... type ENTER")
code = driver.current_url.replace(REDIRECT_URL+'/?code=','')[:-1]
ACCESS_TOKEN = client.exchange_token(code).access_token
USER = client.get('/me').permalink
FILE = "SOUNDCLOUD.%s.access_token" % USER
FILE_W = open(FILE,'w')
FILE_W.write(ACCESS_TOKEN)
FILE_W.close()
driver.quit()
Maybe you'll need to get geckodriver, you can google it to find the one for your OS.
Note that this access_token is not expiring. You don't need a refresh_token.
You can print the full response object with:
from pprint import pprint
[...]
code = driver.current_url.replace(REDIRECT_URL+'/?code=','')[:-1]
TOKEN_OBJECT = client.exchange_token(code)
pprint (vars(TOKEN_OBJECT))
ACCESS_TOKEN = TOKEN_OBJECT.access_token
[...]

Incorrect URL without an access token for facebook login using rauth

I have the code from rauth site:
https://github.com/litl/rauth/blob/master/examples/facebook-cli.py
(The code can be found at the end of this post for reference)
running the program in the command line will open a firefox window and the following message is shown from facebook site:
Success
SECURITY WARNING: Please treat the URL above as you would your password and do not share it with anyone.
when the facebook is logged in beforehand. Even if not logged in, the facebook login window opens up and after logging in using username/password the above message is shown in firefox window.
Now the URL generated in the address bar:
https://www.facebook.com/connect/blank.html#_=_
Which is obviously an incorrect one and it gives exception from the subsequent python code.
Now how can I debug what the problem is?
Thanks
PS:
from rauth.service import OAuth2Service
import re
import webbrowser
# Get a real consumer key & secret from:
# https://developers.facebook.com/apps
facebook = OAuth2Service(
client_id='xxxxxxx',
client_secret='yyyyyyy',
name='facebook',
authorize_url='https://graph.facebook.com/oauth/authorize',
access_token_url='https://graph.facebook.com/oauth/access_token',
base_url='https://graph.facebook.com/')
redirect_uri = 'https://www.facebook.com/connect/login_success.html'
params = {'scope': 'read_stream',
'response_type': 'token',
'redirect_uri': redirect_uri}
authorize_url = facebook.get_authorize_url(**params)
print 'Visit this URL in your browser: ' + authorize_url
webbrowser.open(authorize_url);
url_with_code = raw_input('Copy URL from your browser\'s address bar: ')
access_token = re.search('\#access_token=([^&]*)', url_with_code).group(1)
session = facebook.get_session(access_token)
user = session.get('me').json()
print 'currently logged in as: ' + user['link']
This is happening due to a change on Facebook's end that strips the URL of the access_token programmatically. It happens on a timer, before a human could conceivably copy it out of the URL bar. The example is broken but I don't have an immediate fix for you so I might suggest you take a look at the Flask application instead, which is a more practical demonstration of rauth anyway.
The relevant bit of JS you're fighting:
setTimeout(function() {window.history.replaceState && window.history.replaceState({}, "", "blank.html#_=_");},500);
Not sure whether your q is still outstanding. I came up with a solution last year. But the code is in Powershell; therefore, it can only be used directly on Window machines. Run this script in Powershell and the stripped-out access token is printed out in the shell. Let me know whether it works on your end or not. Thx!
http://groups.yahoo.com/neo/groups/sas_academy/conversations/messages/591

Categories

Resources