Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworked @bryanlandia extension to allow application-only authentication #423

Merged
merged 4 commits into from
Mar 29, 2017
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 45 additions & 16 deletions twitter/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import base64
import re
import requests
from requests_oauthlib import OAuth1
from requests_oauthlib import OAuth1, OAuth2
import io
import warnings
from uuid import uuid4
Expand Down Expand Up @@ -146,6 +146,7 @@ def __init__(self,
consumer_secret=None,
access_token_key=None,
access_token_secret=None,
application_only_auth=False,
input_encoding=None,
request_headers=None,
cache=DEFAULT_CACHE,
Expand All @@ -171,6 +172,9 @@ def __init__(self,
access_token_secret (str):
The oAuth access token's secret, also retrieved
from the get_access_token.py run.
application_only_auth:
Use Application-Only Auth instead of User Auth.
Defaults to False [Optional]
input_encoding (str, optional):
The encoding used to encode input strings.
request_header (dict, optional):
Expand Down Expand Up @@ -256,16 +260,12 @@ def __init__(self,
"strongly advised to increase it above 16384"
))

if consumer_key is not None and (access_token_key is None or
access_token_secret is None):
print('Twitter now requires an oAuth Access Token for API calls. '
'If you\'re using this library from a command line utility, '
'please run the included get_access_token.py tool to '
'generate one.', file=sys.stderr)
if (consumer_key and not
(application_only_auth or all([access_token_key, access_token_secret]))):
raise TwitterError({'message': "Missing oAuth Consumer Key or Access Token"})

raise TwitterError({'message': "Twitter requires oAuth Access Token for all API access"})

self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret)
self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret,
application_only_auth)

if debugHTTP:
import logging
Expand All @@ -279,11 +279,33 @@ def __init__(self,
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

def GetAppOnlyAuthToken(self, consumer_key, consumer_secret):
"""
Generate a Bearer Token from consumer_key and consumer_secret
"""
from urllib import quote_plus
import base64

key = quote_plus(consumer_key)
secret = quote_plus(consumer_secret)
bearer_token = base64.b64encode('{}:{}'.format(key, secret) )

post_headers = {
'Authorization': 'Basic '+bearer_token,
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
res = requests.post(url='https://api.twitter.com/oauth2/token',
data={'grant_type':'client_credentials'},
headers=post_headers)
bearer_creds = res.json()
return bearer_creds

def SetCredentials(self,
consumer_key,
consumer_secret,
access_token_key=None,
access_token_secret=None):
access_token_secret=None,
application_only_auth=False):
"""Set the consumer_key and consumer_secret for this instance

Args:
Expand All @@ -297,17 +319,23 @@ def SetCredentials(self,
access_token_secret:
The oAuth access token's secret, also retrieved
from the get_access_token.py run.
application_only_auth:
Whether to generate a bearer token and use Application-Only Auth
"""
self._consumer_key = consumer_key
self._consumer_secret = consumer_secret
self._access_token_key = access_token_key
self._access_token_secret = access_token_secret
auth_list = [consumer_key, consumer_secret,
access_token_key, access_token_secret]

if all(auth_list):
self.__auth = OAuth1(consumer_key, consumer_secret,
access_token_key, access_token_secret)
if application_only_auth:
self._bearer_token = self.GetAppOnlyAuthToken(consumer_key, consumer_secret)
self.__auth = OAuth2(token=self._bearer_token)
else:
auth_list = [consumer_key, consumer_secret,
access_token_key, access_token_secret]
if all(auth_list):
self.__auth = OAuth1(consumer_key, consumer_secret,
access_token_key, access_token_secret)

self._config = None

Expand Down Expand Up @@ -350,6 +378,7 @@ def ClearCredentials(self):
self._consumer_secret = None
self._access_token_key = None
self._access_token_secret = None
self._bearer_token = None
self.__auth = None # for request upgrade

def GetSearch(self,
Expand Down