I'm trying to set up oauth in Django using Tweepy. I am getting the following error.
AttributeError at /auth/
'dict' object has no attribute 'key'
This occurs in the following code when I try to store the request token for later access when the user is forwarded to the callback url (http://localhost:8000/callback).
def auth(request):
# start the OAuth process, set up a handler with our details
oauth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK)
# direct the user to the authentication url
# if user is logged-in and authorized then transparently goto the callback URL
try:
auth_url = oauth.get_authorization_url()
except tweepy.TweepError:
return HttpResponse('error', status=500)
# store the request token
request.session['unauthed_token_tw'] = (oauth.request_token.key, oauth.request_token.secret)
return HttpResponseRedirect(auth_url)
I am new to Python and Django, does this error mean that the oauth.request_token is null? Could it be a problem with my callback url? Do I need to forward port 8000? Any help or pointers would be much appreciated!
I changed this line of code:
request.session['unauthed_token_tw'] = (oauth.request_token.key, oauth.request_token.secret)
to this:
request.session['unauthed_token_tw'] = oauth.request_token
... after reading this documentation. And now it works!
Related
I am looking forward to extract some data from my profile in Twitter by using the following Tweepy code:
import tweepy
client = tweepy.Client(consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token=access_token, access_token_secret=access_token_secret)
client.get_tweets(ids=[user_id], tweet_fields=["public_metrics"], expansions=["attachments.media_keys"],
media_fields=["public_metrics"])
The issue is that for some reason, I get the following error: tweepy.errors.Unauthorized: 401 Authorization Required, and I know my credentials are valid because I pass tests successfully like the following:
lookup_users = api.lookup_users(screen_name=screen_name)
The issue here is that I have to authorize the account/app/project to get this data, but I haven't found the documentation related to give those authorizations.
How can I authorize my app to get this info from the account??
Since the GET /2/tweets endpoint Client.get_tweets uses allows authentication via bearer token, that's what the method uses by default.
If you want to authorize with user context, you'll have to pass user_auth and set it to True, as it defaults to False, e.g.:
client.get_tweets(
ids=[user_id],
tweet_fields=["public_metrics"],
expansions=["attachments.media_keys"],
media_fields=["public_metrics"],
user_auth=True
)
I'm using Active Directory Authentication library for python following the documentation. Earlier on I managed to get the access_token through the Acquire Token with Client Credentials sample:
import adal
RESOURCE_URI = 'https://<mydomain>.crm.dynamics.com'
AUTHORITY_URL = "https://login.microsoftonline.com/<tenant_id>"
CLIENT_ID = 'xxxx' #application_id
CLIENT_SECRET = 'xxxx'
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_client_credentials(
RESOURCE_URI,
CLIENT_ID,
CLIENT_SECRET)
print token
But I get an error message when I tried the Acquire token and Refresh token sample
context = adal.AuthenticationContext(AUTHORITY_URL)
token = context.acquire_token_with_username_password(
RESOURCE_URI,
USERNAME,
PASSWORD,
CLIENT_ID)
print token
>>> adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
adal.adal_error.AdalError: Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.........."correlation_id"......}
There are two kinds of app we can register on Azure, native or web app. Based on the error message, it seems that you have register a confident app which requires provide its client secret to acquire the access token.
For this issue please register a native app instead of web app. Also the resource owner password credentials flow should be consider used carefully since this may leak the credentials. Refer the flows from link below:
The OAuth 2.0 Authorization Framework - Authorization Grant
I suffered from the same error.
In app registration section in azure active directory I registered the app as web host/api.
When I changed it to native app everything started to work fine.
I'm consistently getting an "Invalid response from Facebook" error when authenticating over Facebook with Oauthlib when building off of the sample code here.
I've outlined the sections of relevant code below.
Setup:
Setting up the Oauth request object.
Not pictured: Navigational routes and Flask app initialization.
from flask_oauthlib.client import OAuth, OAuthException
oauth = OAuth()
facebook = oauth.remote_app('facebook',
base_url='https://graph.facebook.com/',
request_token_url=None,
access_token_url='/oauth/access_token',
authorize_url='https://www.facebook.com/dialog/oauth',
consumer_key=config.get("app_id"),
consumer_secret=config.get("app_secret"),
request_token_params={'scope': 'public_profile,email'}
)
#facebook.tokengetter
def get_facebook_token():
if current_user.is_authenticated():
return current_user.get_facebook_token()
else:
return None
Login handler:
Sending users here in order to begin the process, with the url for the facebook callback appended to the root URL.
#app.route('/facebook/login')
def facebook_login():
return facebook.authorize(callback="http://example.com%s" % url_for('facebook_callback'))
Facebook callback, source of the issue:
From here I can garner that a code (presumably the token) is returned but Oauthlib fails to parse it correctly.
#app.route('/facebook/callback')
def facebook_callback(response):
response = facebook.authorized_response()
if response is None:
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
if isinstance(response, OAuthException):
flash("Access denied: %s" % response.message, "error")
return redirect(url_for('index'))
# Request fails here, returns the redirect above.
From dumping the request args I can see fairly clearly that after being directed to Facebook and successfully connecting, there is a very long token being returned to the callback along the lines of '?code=1234567890-abcdefghijklmnop', however actually trying to authenticate with this fails with "Invalid response from Facebook".
Here is a sample request dump:
ImmutableMultiDict([('code', 'AQAPedwWavTb_cBx6NVy-qy3AL5YPr780oG5tA1LfITpVwkk-kr_4I0lG6B-vlhcYEubhuKhEM46bPs-1WpWUpJzcWfhkQ64lIkdLm9uSHSqeBHBM_6zw7SDpvVmGK-JKWBpAqRJuBKenl9zslQizthox96104iiul0uYQY67cmZgPXZi9uL-mcgZ5dRj387eKJIjNninBXxwCGgFkg5kLVHYt7t0ktUH58stYlxn2f98AXuSlrIvWsA5NeHsVbM8XY0XQrDrNbCvjDmEwHQGkZ3uZRbyaecN7MAi0bM0TrZzpuQ8j3M34DnQp_v9n4ktM4')])
Having used similar code based off of the Twitter sample that works, I'm thinking this could be a possible library bug due to Facebook API changes, but I would appreciate any pointers!
For anyone who stumbles upon this from Google in the future, I solved this in a solution that can be read here.
Hey there, I solved this issue in a very hacky way which I would not
recommend for production environments, but I eventually found the
issue a few days after my last message.
When you ask Facebook for an access token, it does NOT give you an
access token in the way you might expect. What I assumed to be a
failure on Facebook's side was instead a (perhaps intentional)
formatting error.
What you might expect:
http://example.com/callback?access_token=00000000000
or
http://example.com/callback with the access token passed as a POST
argument in the headers.
What actually happens is that Facebook responds like this:
http://example.com/callback?#access_token=0000000000
Because of this, it is -impossible- for any server side language
to parse it, as the access token will now only be visible to the
browser itself. It is not passed to the backend whatsoever.
Capturing the request:
#app.route('/facebook/translate', methods=['GET'])
def facebook_translate():
# Facebook responds with the access token as ?#access_token,
# rather than ?access_token, which is only accessible to the browser.
# This part is where things get really, really dumb.
return ''' <script type="text/javascript">
var token = window.location.href.split("access_token=")[1];
window.location = "/facebook/callback?access_token=" + token;
</script> '''
Proceeding as usual:
#app.route('/facebook/callback', methods=['GET', 'POST'])
def facebook_callback():
access_token = request.args.get("access_token")
if access_token == "undefined":
flash("You denied the request to sign in.", "error")
return redirect(url_for('index'))
graph = facebooksdk.GraphAPI(access_token)
profile = graph.get_object("me")
I'm trying to get access token from Linkedin API using the python-linkedin package given at https://github.com/ozgur/python-linkedin using following code
def get_linkedin_token(request):
access_code = request.GET.get('code')
if access_code is None:
request.session['authentication'] = linkedin.LinkedInAuthentication(
LINKEDIN_CONSUMER_KEY,
LINKEDIN_CONSUMER_SECRET,
RETURN_URL,
linkedin.PERMISSIONS.enums.values())
**url = request.session['authentication'].authorization_url**
return HttpResponseRedirect(url)
else:
request.session['authentication'].authorization_code = access_code
access_token = authentication.get_access_token()
return HttpResponse(access_token)
the above code give me an Type error at url ' is not JSON serializable'; when I open the url in browser it works fine but in app its giving error described.
what is going wwrong how can I fix it?
thanks in advance
the above code is right the minor correction needed at the line
access_token = authentication.get_access_token()
it should be
access_token = request.session['authentication'].get_access_token()
because I initialized authentication object as session variable and was calling simply without using request.session[ ]. So after doing so anyone can easily get access token for LinkedIn API using python-linkedin
I'm working with the OAuth2Decorator() and Pytgon I'm in that stage where i'm still unsure of something about the App Engine. The documentation is not providing any info or I simply can't follow it. So:
Does OAuth2Decorator() store user Crediantials?
Does OAuth2Decorator() retrieve new tokens automatically?
Conside this following example.:
decorator = OAuth2Decorator(...)
service = build("drive", "v2")
class AppHandler(BaseHandler):
#decorator.oauth_aware
def get(self):
if decorator.has_credentials():
init = service.files().list().execute(decorator.http())
items = init['items']
context = {'data': getitems(items)}
self.render_response('index.html',**context)
else:
url = decorator.authorize_url()
self.redirect(url)
The credentials get stored as CredentialsModel in the datastore.
Provided the access that's requested is 'offline' (I believe this is the default), then there will be a 'refresh token' stored alongside the temporary access-token. If a request is made with a credentials-wrapped Http client, then upon receiving a response that indicates the access token has expired, the client make a request to get a new access token automatically, and then the original request will be retried with the new access token, which will then be stored in place of the expired one.