I am trying to make a bot, which posts tweets.
Since my developer account is only essential, I am restricted to V2 API. At first, this is the example from github i used for posting a tweet: https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Manage-Tweets/create_tweet.py
consumer_key = "somekey"
consumer_secret = "somesecret"
payload = {"text": "Hello world!"}
request_token_url = "https://api.twitter.com/oauth/request_token"
oauth = OAuth1Session(consumer_key, client_secret=consumer_secret)
try:
fetch_response = oauth.fetch_request_token(request_token_url)
except ValueError:
print(
"There may have been an issue with the consumer_key or consumer_secret you entered."
)
resource_owner_key = fetch_response.get("oauth_token")
resource_owner_secret = fetch_response.get("oauth_token_secret")
print("Got OAuth token: %s" % resource_owner_key)
print("Got OAuth token secret: %s" % resource_owner_secret)
# Get authorization
base_authorization_url = "https://api.twitter.com/oauth/authorize"
authorization_url = oauth.authorization_url(base_authorization_url)
print("Please go here and authorize: %s" % authorization_url)
verifier = input("Paste the PIN here: ")
# Get the access token
access_token_url = "https://api.twitter.com/oauth/access_token"
oauth = OAuth1Session(
consumer_key,
client_secret=consumer_secret,
resource_owner_key=resource_owner_key,
resource_owner_secret=resource_owner_secret,
verifier=verifier,
)
oauth_tokens = oauth.fetch_access_token(access_token_url)
access_token = oauth_tokens["oauth_token"]
access_token_secret = oauth_tokens["oauth_token_secret"]
print("Got OAuth token: %s" % access_token)
print("Got OAuth token: %s" % access_token_secret)
# Make the request
oauth = OAuth1Session(
consumer_key,
client_secret=consumer_secret,
resource_owner_key=access_token,
resource_owner_secret=access_token_secret,
)
# Making the request
response = oauth.post(
"https://api.twitter.com/2/tweets",
json=payload,
)
if response.status_code != 201:
raise Exception(
"Request returned an error: {} {}".format(response.status_code, response.text)
)
print("Response code: {}".format(response.status_code))
# Saving the response as JSON
json_response = response.json()
print(json.dumps(json_response, indent=4, sort_keys=True))
The user flow is the following. It seems OAuth has to be used, therefore, you have to get a 6 digit number and enter it in the terminal to get the access token:
Got OAuth token: #######
Got OAuth token secret: #######
Please go here and authorize: https://api.twitter.com/oauth/authorize?oauth_token=####
Paste the PIN here: ######
Got OAuth token: ########################################
Got OAuth token: ###############################
It's all working till the last step: actually posting the tweet with JSON. There, I get the following error:
Request returned an error: 403 {"title":"Forbidden","detail":"Forbidden","type":"about:blank","status":403}
What can I do? I simply want to post a tweet using Twitter V2 API, nothing more. Most tutorial use the old V1 or V1.1 api, which isn't helpful.
Edit: It seems to have to do something with the authentification being only read only: Twitter new API Essential access
Ran into the same issue and I needed to add oauth_callback and x_auth_access_type to the request_token request:
https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Manage-Tweets/create_tweet.py#L16
request_token_url = "https://api.twitter.com/oauth/request_token?oauth_callback=oob&x_auth_access_type=write"
Source: https://developer.twitter.com/en/docs/authentication/api-reference/request_token
(credit to zmoon - https://github.com/twitterdev/Twitter-API-v2-sample-code/issues/73)
Related
We have a use case in which Admin can set Google Or Microsoft's Apps Client Id and Secrets that can later be used for all users who sign up with this Admin's link, Is there a way to verify these fields before saving/using them?
like for Microsoft,How do I verify this info that admin is providing? Is there any API call to verify it?
Update:
I am able to do this for G suite, what I did was:
1- Create a request to get token from client id and secret, (with wrong code).
2- In response, google returns 'invalid_client' in case the credentials are wrong and 'invalid_grant' in case the credentials are correct. (because Code is wrong too.)
try:
discovery_url = settings.GOOGLE_DISCOVERY_URL
callback_url = settings.BASE_URL + "/accounts/invite/google/signup/callback/"
client = WebApplicationClient(client_id)
identity_provider_config = requests.get(
discovery_url,
).json()
token_endpoint = identity_provider_config["token_endpoint"]
token_url, headers, body = client.prepare_token_request(
token_endpoint, redirect_url=callback_url, code='**code'**
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(client_id, client_secret),
).json()
# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response))
except Exception as error:
json_object = json.loads(error.json)
pairs = json_object.items()
if list(pairs)[0][1] == 'invalid_grant':
return "Your credentials are correct"
if list(pairs)[0][1] == 'invalid_client':
return "Your credentials are NOT correct"
FOR MICROSOFT:
For microsoft, additional tenant id is required in order to do this:
We did this in following way:
def validate_azure_credentials(client_id, client_secret, tenant_id):
"""
validate client id and secret from microsoft and google
"""
try:
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=f"https://login.microsoftonline.com/{tenant_id}",
)
# call for default scope in order to verify client id and secret.
scopes = ["https://vault.azure.net/.default"]
token = app.acquire_token_for_client(scopes=scopes)
if token.get("access_token") is None:
return IdpResponseMessages.INVALID_CREDENTIALS
return IdpResponseMessages.VALID_CREDENTIALS
except Exception as error:
logger.debug(f"Exception {error}")
return str(error)
I am working on a module for an application written in Python (it is open-source). I want the module to allow a user to log into Twitter and update status (post a tweet). I have Python script I wrote using the twitter import that requires a developer (me) to put in consumer/authentication token/secrets. I don't want to have the tokens pre-programmed into the module, but rather have a user log in to update THEIR status (obviously).
I need a general direction to pursue. I envision the user clicking on a Share! menu option, a browser popping up with the Twitter login page, a user logging in and the application storing the credentials, and then updating the status from there. I have the module working, but like I said before, I need to input token information from my application's apps.twitter.com page. I want the user to be able to log in.
Here is a snip of code using the twython library:
from twython import Twython
#APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET
OAUTH_TOKEN = '...'
OAUTH_TOKEN_SECRET = '...'
APP_KEY = '...'
APP_SECRET = '...'
twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
if (twitter.update_status(status='The status is updated from Python!')):
print("Working!")
else:
print("Not working!")
The code above works and updates my Twitter status, but I do not want other users of this module to be updating my status, but rather have them log in and update their status.
Thanks in advance.
EDIT
What I have now:
import urllib.parse
import oauth2 as oauth
consumer_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'
consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
request_token_url = 'https://api.twitter.com/oauth/request_token'
access_token_url = 'https://api.twitter.com/oauth/access_token'
authorize_url = 'https://api.twitter.com/oauth/authorize'
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
resp, content = client.request(request_token_url, "GET")
if resp['status'] != '200':
raise Exception("Invalid response %s." % resp['status'])
request_token = dict(urllib.parse.parse_qsl(content))
print("Request Token:")
print(" - oauth_token = %s" % request_token[b'oauth_token'].decode())
print(" - oauth_token_secret = %s" % request_token[b'oauth_token_secret'].decode())
print("Go to the following link in your browser:")
print("%s?oauth_token=%s" % (authorize_url, request_token[b'oauth_token'].decode()))
accepted = 'n'
while accepted.lower() == 'n':
accepted = input('Have you authorized me? (y/n) ')
oauth_verifier = input('What is the PIN? ')
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
token.set_verifier(oauth_verifier)
client = oauth.Client(consumer, token)
resp, content = client.request(access_token_url, "POST")
access_token = dict(urllib.parse.parse_qsl(content))
print(access_token.keys())
print(access_token.values())
print("You may now access protected resources using the access tokens above.")
import twitter
api = twitter.Api(consumer_key=' ', consumer_secret=' ',
access_token_key=' ', access_token_secret=' ')
tweet = api.PostUpdate("First tweet from an authenticated user.")
I get to the point where I authorize my application with the login, the webpage redirects to the callback_url, just like it should, but I don't get a PIN to input. Where does that come in?
i know it late but it can be help others
you can find verify token after your app verify and it will be show into header.
I'm trying to issue a basic UbuntuOne API call.
As explained on https://one.ubuntu.com/developer/account_admin/auth/otherplatforms, I'm getting the OAUTH token and then passing it to the UbuntuOne service.
I get the token and consumer info alright
I'm then trying to issue a /api/file_storage/v1 API call (see: https://one.ubuntu.com/developer/files/store_files/cloud.) The request is signed using the OAUTH token.
The code snippet below is the exact code I'm executing (minus the email.password/description fields.) The token and consumer data is returned properly. I'm getting a '401 UNAUTHORIZED' from the server when issuing the /api/file_storage/v1 request... any idea why?
import base64
import json
import urllib
import urllib2
import oauth2
email = 'bla'
password = 'foo'
description = 'bar'
class Unauthorized(Exception):
"""The provided email address and password were incorrect."""
def acquire_token(email_address, password, description):
"""Aquire an OAuth access token for the given user."""
# Issue a new access token for the user.
request = urllib2.Request(
'https://login.ubuntu.com/api/1.0/authentications?' +
urllib.urlencode({'ws.op': 'authenticate', 'token_name': description}))
request.add_header('Accept', 'application/json')
request.add_header('Authorization', 'Basic %s' % base64.b64encode('%s:%s' % (email_address, password)))
try:
response = urllib2.urlopen(request)
except urllib2.HTTPError, exc:
if exc.code == 401: # Unauthorized
raise Unauthorized("Bad email address or password")
else:
raise
data = json.load(response)
consumer = oauth2.Consumer(data['consumer_key'], data['consumer_secret'])
token = oauth2.Token(data['token'], data['token_secret'])
# Tell Ubuntu One about the new token.
get_tokens_url = ('https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/')
oauth_request = oauth2.Request.from_consumer_and_token(consumer, token, 'GET', get_tokens_url)
oauth_request.sign_request(oauth2.SignatureMethod_PLAINTEXT(), consumer, token)
request = urllib2.Request(get_tokens_url)
for header, value in oauth_request.to_header().items():
request.add_header(header, value)
response = urllib2.urlopen(request)
return consumer, token
if __name__ == '__main__':
consumer, token = acquire_token(email, password, description)
print 'Consumer:', consumer
print 'Token:', token
url = 'https://one.ubuntu.com/api/file_storage/v1'
oauth_request = oauth2.Request.from_consumer_and_token(consumer, token, 'GET', url)
oauth_request.sign_request(oauth2.SignatureMethod_PLAINTEXT(), consumer, token)
request = urllib2.Request(url)
request.add_header('Accept', 'application/json')
for header, value in oauth_request.to_header().items():
request.add_header(header, value)
response = urllib2.urlopen(request)
The issue was with the 'description' field. It must be in the following format:
Ubuntu One # $hostname [$application]
Else, the UbuntuOne service returns a "ok 0/1" and does not register the token.
I am trying to create generic class in python which will do all the oAuth process and then will allow to retrieve data from any oAuth supporting service (for example Twitter,LinkedIn).
Edited:
I have customer key and secret and access token key and secret,when I try to request any resource request I get the following error:
{"error":"Could not authenticate with OAuth.","request":"\/1\/statuses\/retweeted_by_me.json}'
any idea why?
My Code is:
import httplib
import time
import oauth as oauth
# settings for the local test consumer
SERVER = 'api.twitter.com'
RESOURCE_URL = 'https://api.twitter.com/1/statuses/retweeted_by_me.json'
CONSUMER_KEY = 'MY_CUSTOMER_KEY'
CONSUMER_SECRET = 'MY_CUSTOMER_SECRET'
ACCESS_TOKEN_KEY = 'MY_ACCESS_TOKEN_KEY'
ACCESS_TOKEN_SECRET = 'MY_ACCESS_TOKEN_SECRET'
# example client using httplib with headers
class SimpleOAuthClient(oauth.OAuthClient):
def __init__(self, server):
self.server = server
self.connection = httplib.HTTPSConnection(self.server)
def access_resource(self, oauth_request):
# via post body
# -> some protected resources
self.connection.request(oauth_request.http_method, RESOURCE_URL)
response = self.connection.getresponse()
return response.read()
def run_example2():
print '** OAuth Python Library Example **'
client = SimpleOAuthClient(SERVER, )
consumer = oauth.OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
signature_method_hmac_sha1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
pause()
# access some protected resources
print '* Access protected resources ...'
pause()
token = oauth.OAuthToken('ACCESS_TOKEN_KEY', 'ACCESS_TOKEN_SECRET')
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url=RESOURCE_URL)
oauth_request.sign_request(signature_method_hmac_sha1, consumer, token)
print 'REQUEST (via post body)'
print 'parameters: %s' % str(oauth_request.parameters)
pause()
params = client.access_resource(oauth_request)
print 'GOT'
print 'non-oauth parameters: %s' % params
pause()
def pause():
print ''
time.sleep(1)
if __name__ == '__main__':
run_example2()
print 'Done.'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authenticate'
This is the incorrect URL to use for OAuth. If you look at Twitter's 3-legged OAuth documentation, they state "The GET oauth/authorize endpoint is used instead of /oauth/authenticate". Change the URL to "https://api.twitter.com/oauth/authorize" and try again.
I managed to fix it by changing self.connection.request(oauth_request.http_method, RESOURCE_URL)
to self.connection.request(oauth_request.http_method, oauth_request.to_url())
Notice that will will work only if oauth_request.http_method is GET
I am trying to setup this Twitter authorization without having the user to enter the pin in our screen but I am having trouble getting the correct setup I am always directed to enter the PIN. trying to use and follow this package https://github.com/simplegeo/python-oauth2
Here is my current code
env = Environment(loader = PackageLoader('buzzient','tmpl'))
template = env.get_template('authtwitter.html')
tmpldict = {}
#SETUP TWITTER AUTHORIZATION OBJECT
consumer_key = '######################'
consumer_secret = '##############################'
request_token_url = 'http://twitter.com/oauth/request_token'
access_token_url = 'http://twitter.com/oauth/access_token'
authorize_url = 'http://twitter.com/oauth/authenticate'
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
#get request token
resp, content = client.request(request_token_url, "GET")
if resp['status'] != '200':
raise Exception("Invalid Response %s." %resp['status'])
request_token = dict(urlparse.parse_qsl(content))
tmpldict['twitauthurl'] = "%s?oauth_token=%s" % ( authorize_url, request_token['oauth_token'] )
qargs=buzzientlib.urlparse_qs(self.request.url,True,False)
t = template.render(tmpldict)
self.response_body = str(t)
The template just includes a link to twitauthurl
Switched packages to Tweepy and followed this example
http://packages.python.org/tweepy/html/auth_tutorial.html