I'm having a hard time trying to authenticate my spotify app on localhost. I have my redirect_uri set as localhost:8888/callback (have also tried it with http://) at my developer account, but I get this error page when terminal prompts me to enter the URL I'm being redirected to.
I am running my server using python -m SimpleHTTPServer 8888, and entering at terminal python script.py username.
This is my Python script:
scope = 'user-library-read'
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print "Usage: %s username" % (sys.argv[0],)
sys.exit()
token = util.prompt_for_user_token(username, scope, client_id='myId', client_secret='mySecret', redirect_uri='localhost:8888/callback')
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
This is the log:
token_info = sp_oauth.get_access_token(code)
File "/Library/Python/2.7/site-packages/spotipy/oauth2.py", line 210, in get_access_token
raise SpotifyOauthError(response.reason)
spotipy.oauth2.SpotifyOauthError: Bad Request
What could be wrong?
have you tried it without the port number?
So replacing
localhost:8888/callback
with this:
localhost:/callback
Related
the authentication to Active directory using python-ldap works well with the code below, now trying to find how can I verify
if a user belongs to a Security Group to be successfully authentificate but cannot figure out how to do that.
I have this code integrated in a flask website.
Here is my code:
import ldap
def authenticate():
conn = ldap.initialize('ldap://ldap.example.com')
conn.protocol_version = 3
conn.set_option(ldap.OPT_REFERRALS, 0)
try:
username = 'user_id'
password = 'motdepasse'
user = "%s#domain" %username
result = conn.simple_bind_s('user', 'password')
except ldap.INVALID_CREDENTIALS:
print "Invalid credentials"
return "Invalid credentials"
except ldap.SERVER_DOWN:
print "Server down"
return "Server down"
except ldap.LDAPError, e:
if type(e.message) == dict and e.message.has_key('desc'):
return "Other LDAP error: " + e.message['desc']
else:
print "Other LDAP error: "
return "Other LDAP error: " + e
finally:
conn.unbind_s()
print "Succesfully"
return "Succesfully authenticated"
authenticate()
Thanks for your help
To restrict the LDAP authentication to a specific AD group I used the "search_s function" which find if the authenticated user is part of a AD group.
conn.search_s("OU={AD Security Group},OU=group,OU=Groups,dc=twpn,dc=root,dc=domain,dc=com", ldap.SCOPE_SUBTREE, "(cn=userid)")
I have a working python/tk program that runs a cgi script based on user selection. I'm working to cut this down to a small script that just focuses on one particular cgi script. It appears to be getting the session id correctly but when I launch the browser I keep getting "access denied". As the other program works I not expecting any issues from the website. Any help will be appreciated.
UPDATE:
If I use a debugger and set a breakpoint on the line print url the url printed in the console, as seen below, does work. I now know the session id token is good.
Also if I step into the webbrowser function and then step over after that the script also works.
Here is my code.
import json
import tornado.web
import tornado.websocket
from tornado import gen
import tornado.ioloop
import webbrowser
from struct import *
request_id = 71
ip_address = "10.22.4.14"
# ************************************************
# Procedure to open websocket and get session id
# ***********************************************
#gen.coroutine
def open_ws(ip, username, password):
global client
global request_id
global session_id
ws_url = "ws://" + ip + ":7011/"
try:
client = yield tornado.websocket.websocket_connect(ws_url, None, None, 5, None, None)
# print("websocket %s open" % ws_url)
except error:
exit()
# Send Mercury login request
JSON = '{"requests":[{"request_id": %s, "login":{"username": "%s","password": "%s"}}]}' % (str(request_id), username, password)
client.write_message(JSON)
results = yield client.read_message()
# print("msg is %s" % results)
# Parse the response of login request to get the error code
parsed_json = json.loads(results)
err_code = parsed_json['responses'][0]['request_response']['result']['err_code']
if 0 == err_code:
# Parse the response of get_command_result to get the session id
session_id = parsed_json['responses'][0]['request_response']['login']['session_id']
# print("login succeeded - session id: %s" % session_id)
else:
print("login failed")
# error_exit(err_code)
def get_token():
tornado.ioloop.IOLoop.instance().run_sync(lambda: open_ws(ip_address, 'admin', 'admin'))
return session_id
session_id = get_token()
print "Token is " + session_id
url = "http://" + ip_address + "/scripts/dostuff.cgi?session=" + session_id
print url # add breakpoint here
# launch browser
webbrowser.open(url)
Console output:
Token is 7zNSZX9liaUDFFN0ijn-LWQ8
http://10.222.4.14/scripts/dostuff.cgi?session=7zNSZX9liaUDFFN0ijn-LWQ8
Resolved. The script was ending therefore closing the socket before the browser had a chance to respond to the request
We created an application for Google Apps Marketplace. Our app works only if it's installed for everyone. But the problem is, some customers install our app for some organizations, not everyone. We want to display a specific message to those customers, but the problem is that we don't know if our app is installed for some organizations, or not installed at all. Therefore, customers who installed our app for some organizations get a message which is intended for customers who didn't install our app at all. We show them the install button but nothing happens when they install our app again, because it's already installed. We want to give them instructions how to change our app's status to "on for everyone".
How can we check if our app is installed for some organizations? We get the following error message from Google:
Failed to retrieve access token: {
"error" : "unauthorized_client",
"error_description" : "Unauthorized client or scope in request."
}
Which is the same error message we receive for cutomers who didn't install our app at all.
This is the Python function who throws the exception:
def _do_refresh_request(self, http_request):
"""Refresh the access_token using the refresh_token.
Args:
http_request: callable, a callable that matches the method signature of
httplib2.Http.request, used to make the refresh request.
Raises:
AccessTokenRefreshError: When the refresh fails.
"""
body = self._generate_refresh_request_body()
headers = self._generate_refresh_request_headers()
logger.info('Refreshing access_token')
resp, content = http_request(
self.token_uri, method='POST', body=body, headers=headers)
if resp.status == 200:
# TODO(jcgregorio) Raise an error if loads fails?
d = simplejson.loads(content)
self.token_response = d
self.access_token = d['access_token']
self.refresh_token = d.get('refresh_token', self.refresh_token)
if 'expires_in' in d:
self.token_expiry = datetime.timedelta(
seconds=int(d['expires_in'])) + datetime.datetime.utcnow()
else:
self.token_expiry = None
if self.store:
self.store.locked_put(self)
else:
# An {'error':...} response body means the token is expired or revoked,
# so we flag the credentials as such.
logger.info('Failed to retrieve access token: %s' % content)
error_msg = 'Invalid response %s.' % resp['status']
try:
d = simplejson.loads(content)
if 'error' in d:
error_msg = d['error']
self.invalid = True
if self.store:
self.store.locked_put(self)
except StandardError:
pass
raise AccessTokenRefreshError(error_msg)
Update 1: in Apps > Marketplace apps, an app can be on for everyone, on for selected orgs or off. We need to know the status of our app.
Update 2: I tried calling check_general_access but also when our application is uninstalled we receive True (Application has general access). This is after we confirmed that check_access returned False.
#staticmethod
def check_access(admin_email):
http = httplib2.Http()
credentials = SignedJwtAssertionCredentials(
SERVICE_EMAIL,
PRIVATE_KEY,
scope='https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://www.googleapis.com/auth/admin.directory.user.readonly',
sub=str(admin_email),
)
http = credentials.authorize(http)
try:
service = build(serviceName='admin', version='directory_v1', http=http)
logging.info("Application has access to admin's %s domain" % (admin_email))
return True
except Exception as e:
logging.info("Application does not have access to admin's %s domain (exception: %s)" % (admin_email, e.message))
return False
#staticmethod
def check_general_access():
http = httplib2.Http()
credentials = SignedJwtAssertionCredentials(
SERVICE_EMAIL,
PRIVATE_KEY,
scope='https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://www.googleapis.com/auth/admin.directory.user.readonly',
)
http = credentials.authorize(http)
try:
service = build(serviceName='admin', version='directory_v1', http=http)
logging.info("Application has general access")
return True
except Exception as e:
logging.info("Application does not have general access (exception: %s)" % e.message)
return False
Not sure, but may have found a way. From the documentation I asserted that domain wide access is needed to impersonate a user within the target domain. Service apps do not need this for other tasks. While convoluted, you can test if you get credentials without the sub parameter to SignedJwtAssertionCredentials. If this succeeds, but adding the sub parameter fails, you're installed but not domain wide.
Let us know if this works and obviously Google has some work to do there still.
You can add ping back, every hour or so call some end point. If the ping was too long ago they probably remove the app
I'm having an error on a python file. What it does is to get acces to an specific google API. OAuth2.0. But that's not the wrong part. The wrong part takes part of argparse (Retriving arguments from console by adding --something="").
Here's my code:
import argparse
import os
import pprint
import sys
import time
import httplib2
from apiclient import discovery
from oauth2client import file
from oauth2client import tools
from oauth2client import client
# Time to wait (in seconds) between successive checks of training status.
SLEEP_TIME = 10
# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('object_name',
help='Full Google Storage path of csv data (ex bucket/object)')
argparser.add_argument('id',
help='Model Id of your choosing to name trained model')
#argparser.add_argument('action');
def print_header(line):
'''Format and print header block sized to length of line'''
header_str = '='
header_line = header_str * len(line)
print '\n' + header_line
print line
print header_line
def main(argv):
parent_parsers = [tools.argparser]
parent_parsers.extend(parents)
parser = argparse.ArgumentParser(
description=doc,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=parent_parsers)
flags = parser.parse_args(argv[1:])
scope='https://www.googleapis.com/auth/prediction'
client_secrets = os.path.join(os.path.dirname(__file__),
'client_secrets.json')
flow = client.flow_from_clientsecrets(client_secrets,
scope=scope,
message=tools.message_if_missing(client_secrets))
storage = file.Storage('prediction.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http = httplib2.Http())
service = discovery.build('prediction', 'v1.6', http=http)
try:
papi = service.trainedmodels()
print_header('Fetching list of first ten models')
result = papi.list(maxResults=10).execute()
print 'List results:'
pprint.pprint(result)
except client.AccessTokenRefreshError:
print ("The credentials have been revoked or expired, please re-run"
"the application to re-authorize")
if __name__ == '__main__':
main(sys.argv)
On this line--> parent_parsers = [tools.argparser] I'm having that error:
line 75, in main
parent_parsers = [tools.argparser]
AttributeError: 'module' object has no attribute 'argparser'
The tools.py file is that one:
import BaseHTTPServer
import argparse
import httplib2
import logging
import os
import socket
import sys
import webbrowser
from oauth2client import client
from oauth2client import file
from oauth2client import util
try:
from urlparse import parse_qsl
except ImportError:
from cgi import parse_qsl
_CLIENT_SECRETS_MESSAGE = """WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:
%s
with information from the APIs Console <https://code.google.com/apis/console>.
"""
# run_parser is an ArgumentParser that contains command-line options expected
# by tools.run(). Pass it in as part of the 'parents' argument to your own
# ArgumentParser.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('--auth_host_name', default='localhost',
help='Hostname when running a local web server.')
argparser.add_argument('--noauth_local_webserver', action='store_true',
default=False, help='Do not run a local web server.')
argparser.add_argument('--auth_host_port', default=[8080, 8090], type=int,
nargs='*', help='Port web server should listen on.')
argparser.add_argument('--logging_level', default='ERROR',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR',
'CRITICAL'],
help='Set the logging level of detail.')
class ClientRedirectServer(BaseHTTPServer.HTTPServer):
"""A server to handle OAuth 2.0 redirects back to localhost.
Waits for a single request and parses the query parameters
into query_params and then stops serving.
"""
query_params = {}
class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""A handler for OAuth 2.0 redirects back to localhost.
Waits for a single request and parses the query parameters
into the servers query_params and then stops serving.
"""
def do_GET(s):
"""Handle a GET request.
Parses the query parameters and prints a message
if the flow has completed. Note that we can't detect
if an error occurred.
"""
s.send_response(200)
s.send_header("Content-type", "text/html")
s.end_headers()
query = s.path.split('?', 1)[-1]
query = dict(parse_qsl(query))
s.server.query_params = query
s.wfile.write("<html><head><title>Authentication Status</title></head>")
s.wfile.write("<body><p>The authentication flow has completed.</p>")
s.wfile.write("</body></html>")
def log_message(self, format, *args):
"""Do not log messages to stdout while running as command line program."""
pass
#util.positional(3)
def run_flow(flow, storage, flags, http=None):
logging.getLogger().setLevel(getattr(logging, flags.logging_level))
if not flags.noauth_local_webserver:
success = False
port_number = 0
for port in flags.auth_host_port:
port_number = port
try:
httpd = ClientRedirectServer((flags.auth_host_name, port),
ClientRedirectHandler)
except socket.error, e:
pass
else:
success = True
break
flags.noauth_local_webserver = not success
if not success:
print 'Failed to start a local webserver listening on either port 8080'
print 'or port 9090. Please check your firewall settings and locally'
print 'running programs that may be blocking or using those ports.'
print
print 'Falling back to --noauth_local_webserver and continuing with',
print 'authorization.'
print
if not flags.noauth_local_webserver:
oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number)
else:
oauth_callback = client.OOB_CALLBACK_URN
flow.redirect_uri = oauth_callback
authorize_url = flow.step1_get_authorize_url()
if not flags.noauth_local_webserver:
webbrowser.open(authorize_url, new=1, autoraise=True)
print 'Your browser has been opened to visit:'
print
print ' ' + authorize_url
print
print 'If your browser is on a different machine then exit and re-run this'
print 'application with the command-line parameter '
print
print ' --noauth_local_webserver'
print
else:
print 'Go to the following link in your browser:'
print
print ' ' + authorize_url
print
code = None
if not flags.noauth_local_webserver:
httpd.handle_request()
if 'error' in httpd.query_params:
sys.exit('Authentication request was rejected.')
if 'code' in httpd.query_params:
code = httpd.query_params['code']
else:
print 'Failed to find "code" in the query parameters of the redirect.'
sys.exit('Try running with --noauth_local_webserver.')
else:
code = raw_input('Enter verification code: ').strip()
try:
credential = flow.step2_exchange(code, http=http)
except client.FlowExchangeError, e:
sys.exit('Authentication has failed: %s' % e)
storage.put(credential)
credential.set_store(storage)
print 'Authentication successful.'
return credential
def message_if_missing(filename):
"""Helpful message to display if the CLIENT_SECRETS file is missing."""
return _CLIENT_SECRETS_MESSAGE % filename
try:
from old_run import run
except ImportError:
def run(*args, **kwargs):
raise NotImplementedError(
'The gflags library must be installed to use tools.run(). '
'Please install gflags or preferrably switch to using '
'tools.run_flow().')
I don't understand the meaning of the error, it may be an import issue but I don't know.
Thanks!
You need to make sure the oauth tools are setup properly:
python setup_oauth2client.py install
it's in the base directory
I am using xmpp with python and I want create a simple client to communicate with a gmail
id.
#!/usr/bin/python
import xmpp
login = 'Your.Login' # #gmail.com
pwd = 'YourPassword'
cnx = xmpp.Client('gmail.com')
cnx.connect( server=('talk.google.com',5223) )
cnx.auth(login,pwd, 'botty')
cnx.send( xmpp.Message( "YourFriend#gmail.com" ,"Hello World form Python" ) )
When I run the last line I get an exception
IOError: Disconnected from server.
Also when I run the other statements I get debug messages in the console.
What could be the issue and how can I resolve it ?
Here is how it did on my PyTalk client.
Don't forget the #gmail.com in the userID.
I think you should try to connect talk.google.com on the 5222 port.
Also try to specify a ressource for the auth.
import xmpp
import sys
userID = 'Your.Login#gmail.com'
password = 'YourPassword'
ressource = 'Script'
jid = xmpp.protocol.JID(userID)
jabber = xmpp.Client(jid.getDomain(), debug=[])
connection = jabber.connect(('talk.google.com',5222))
if not connection:
sys.stderr.write('Could not connect\n')
else:
sys.stderr.write('Connected with %s\n' % connection)
auth = jabber.auth(jid.getNode(), password, ressource)
if not auth:
sys.stderr.write("Could not authenticate\n")
else:
sys.stderr.write('Authenticate using %s\n' % auth)
jabber.sendInitPresence(requestRoster=1)
jabber.send(xmpp.Message( "YourFriend#gmail.com" ,"Hello World form Python" ))
By the way, it looks very close from Philip Answer
Try this code snippet. I didn't handle the error conditions for simplicity's sake.
import xmpp
login = 'Your.Login' # #gmail.com
pwd = 'YourPassword'
jid = xmpp.protocol.JID(login)
cl = xmpp.Client(jid.getDomain(), debug=[])
if cl.connect(('talk.google.com',5223)):
print "Connected"
else:
print "Connectioned failed"
if cl.auth(jid.getNode(), pwd):
cl.sendInitPresence()
cl.send(xmpp.Message( "YourFriend#gmail.com" ,"Hello World form Python" ))
else:
print "Authentication failed"
To switch off the debugging messages, pass debug=[] for the 2nd parameter on the Client class's constructor:
cl = xmpp.Client(jid.getDomain(), debug=[])
i think you must write this. i test it in python 2.7 with xmpppy 0.5.0rc1 and work IT very nice :P :) :
import xmpp
login = 'your mail#gmail.com' # #gmail.com
pwd = 'your pass'
text='Hello worlD!'
tojid='your friend #gmail.com'
jid = xmpp.protocol.JID(login)
cl = xmpp.Client(jid.getDomain(), debug=[])
if cl.connect(('talk.google.com',5223)):
print "Connected"
else:
print "Connectioned failed"
if cl.auth(jid.getNode(), pwd):
cl.sendInitPresence()
cl.send(xmpp.protocol.Message(tojid,text))
else:
print "Authentication failed"
I think you need to call sendInitPresence before sending the first message:
...
cnx.auth(login,pwd, 'botty')
cnx.sendInitPresence()
cnx.send( xmpp.Message( "YourFriend#gmail.com" ,"Hello World form Python" ) )