I attempted to run the code below and am getting an error that states:
HTTP Error code: 403: Forbidden: Authentication succeeded but account is not authorized to access this resource.
from searchtweets import ResultStream, gen_rule_payload, load_credentials, collect_results
import requests
premium_search_args = load_credentials("/home/dirname/twitter_keys.yaml",
yaml_key="search_tweets_premium",
env_overwrite=False)
rule = gen_rule_payload("basketball", results_per_call=100) # testing with a sandbox account
print(rule)
from searchtweets import collect_results
tweets = collect_results(rule,
max_results=100,
result_stream_args=premium_search_args)
# print(tweets.all_text)
[print(tweet.all_text, end='\n\n') for tweet in tweets[0:10]];
My YAML file looks like this:
search_tweets_premium:
account_type: premium
endpoint: https://api.twitter.com/1.1/tweets/search/fullarchive/dev.json
consumer_key: AAAAAAAAAAAAAAAAAAAAA
consumer_secret: BBBBBBBBBBBBBBBBBBBBBBBBBBB
Only other thing to note is that I am using the free/sandbox service.
Any ideas if I am doing anything wrong in the code, the YAML, and/or within my Twitter developer account?
You'll need to go to https://developer.twitter.com/en/account/environments
There you should be able to see the various development environments that you have. You can create one should they not have been created.
The dev environment label would then be the thing you use to replace in your endpoint.
In my example, it would be:
https://api.twitter.com/1.1/tweets/search/fullarchive/development.json
If that still doesn't work, you might need to include a bearer token in your YAML file.
Related
Here's my problem:
I have a 365 Family OneDrive subscription with 3 members, my account being the admin.
I am trying to build a python application to read/extract the content of the files I have on this onedrive space based on specific criterias. I want to build it as a command line application, running locally on my PC. I am aware some tools may exist for this but I'd like to code my own solution.
After going through tons of different documentation, I ended up doing the following
Registered my application on the Azure portal
Granted some permission on the Microsoft Graph API (User.read, Files.Read and Files.ReadAll)
Created a secret
Grabbed the sample code provided by Microsoft
Replaces some variables with my Client_Id and Secret
Ran the code
The code returns an access token but the authorization requests fails with 401 - Unauthorized: Access is denied due to invalid credentials.
Here's the Python code I'm using.
import msal
config = {
"authority": "https://login.microsoftonline.com/consumers",
"client_id": "<my client ID>",
"scope": ["https://graph.microsoft.com/.default"],
"secret": "<My secret stuff>",
"endpoint": "https://graph.microsoft.com/v1.0/users"
}
# Create a preferably long-lived app instance which maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
)
result = None
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
result = app.acquire_token_for_client(scopes=config["scope"])
if "access_token" in result:
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
print("Graph API call result: ")
print(json.dumps(graph_data, indent=2))
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id")) # You may need this when reporting a bug
According to the error message, I'm obviously missing something in the authorization process but can't tell what. I'm not even sure about the Authority and Endpoints I should use. My account being a personal one, I have no tenant.
Do I need to set-up / configure some URI somewhere?
Any help would be welcome.
Thank you in advance.
In your client app you need to store the token that you are getting from the MSAL. and then send the token with an authorized request.
For OneDrive, download the OneDrive for python. You can see the different option for Authentication.
The reason you are getting an access token, ID token, and a refresh token is because of the flow you're using. My suggestion is to review the flows for a better understanding of how the authentication process works and what will be returned accordingly. You can use this MSAL library for python.
I have a mendeley account which I am using from their online version. I created a userid and client secret, saved it in config.yml file from and using it to authenticate. I am using the below code available on their website
import yaml
from mendeley import Mendeley
with open('config.yml') as f:
config = yaml.load(f)
REDIRECT_URI = 'http://localhost:5000/oauth'
mendeley = Mendeley(config['clientId'], config['clientSecret'], REDIRECT_URI)
auth = mendeley.start_client_credentials_flow()
session = auth.authenticate()
This code works fine and I got not errors. But when I am trying to access data using the commands in the example it throws error. For example
>> print (session.profiles.me.display_name)
mendeley.exception.MendeleyApiException: The Mendeley API returned an error (status: 400, message: No userid found in auth token)
>> for document in session.documents.iter():
print document.title
mendeley.exception.MendeleyApiException: The Mendeley API returned an error (status: 403, message: Access to this document is not allowed)
I am stuck here and do not know how to access the data or articles I have on mendeley fom its API. Any help will be highly appreciated.
You are using the Client Credentials flow (a term from OAuth). Quoting from the docs:
This flow does not require the user to log in. However, it only
provides access to a limited set of resources (the read-only Mendeley
Catalog of crowd sourced documents).
The two calls from your questions are private (user) information, and will therefor fail.
On the other hand, the following should work:
print session.catalog.by_identifier(doi='10.1371/journal.pmed.0020124', view='stats').reader_count
If you want to access private information, you will need users to log in. This question should help.
I'm trying to get this example to work from https://github.com/ozgur/python-linkedin. I'm using his example. When I run this code. I don't get the RETURN_URL and authorization_code talked about in the example. I'm not sure why, I think it is because I'm not setting up the HTTP API example correctly. I can't find http_api.py, and when I visit http://localhost:8080, I get a "this site can't be reached".
from linkedin import linkedin
API_KEY = 'wFNJekVpDCJtRPFX812pQsJee-gt0zO4X5XmG6wcfSOSlLocxodAXNMbl0_hw3Vl'
API_SECRET = 'daJDa6_8UcnGMw1yuq9TjoO_PMKukXMo8vEMo7Qv5J-G3SPgrAV0FqFCd0TNjQyG'
RETURN_URL = 'http://localhost:8000'
authentication = linkedin.LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL, linkedin.PERMISSIONS.enums.values())
# Optionally one can send custom "state" value that will be returned from OAuth server
# It can be used to track your user state or something else (it's up to you)
# Be aware that this value is sent to OAuth server AS IS - make sure to encode or hash it
#authorization.state = 'your_encoded_message'
print authentication.authorization_url # open this url on your browser
application = linkedin.LinkedInApplication(authentication)
http_api.py is one of the examples provided in the package. This is an HTTP server that will handle the response from LinkedIn's OAuth end point, so you'll need to boot it up for the example to work.
As stated in the guide, you'll need to execute that example file to get the server working. Note you'll also need to supply the following environment variables: LINKEDIN_API_KEY and LINKEDIN_API_SECRET.
You can run the example file by downloading the repo and calling LINKEDIN_API_KEY=yourkey LINKEDIN_API_SECRET=yoursecret python examples/http_api.py. Note you'll need Python 3.4 for it to work.
I created 2 applications in my Azure directory, 1 for my API Server and one for my API client. I am using the Python ADAL Library and can successfully obtain a token using the following code:
tenant_id = "abc123-abc123-abc123"
context = adal.AuthenticationContext('https://login.microsoftonline.com/' + tenant_id)
token = context.acquire_token_with_username_password(
'https://myapiserver.azurewebsites.net/',
'myuser',
'mypassword',
'my_apiclient_client_id'
)
I then try to send a request to my API app using the following method but keep getting 'unauthorized':
at = token['accessToken']
id_token = "Bearer {0}".format(at)
response = requests.get('https://myapiserver.azurewebsites.net/', headers={"Authorization": id_token})
I am able to successfully login using myuser/mypass from the loginurl. I have also given the client app access to the server app in Azure AD.
Although the question was posted a long time ago, I'll try to provide an answer. I stumbled across the question because we had the exact same problem here. We could successfully obtain a token with the adal library but then we were not able to access the resource I obtained the token for.
To make things worse, we sat up a simple console app in .Net, used the exact same parameters, and it was working. We could also copy the token obtained through the .Net app and use it in our Python request and it worked (this one is kind of obvious, but made us confident that the problem was not related to how I assemble the request).
The source of the problem was in the end in the oauth2_client of the adal python package. When I compared the actual HTTP requests sent by the .Net and the python app, a subtle difference was that the python app sent a POST request explicitly asking for api-version=1.0.
POST https://login.microsoftonline.com/common//oauth2/token?api-version=1.0
Once I changed the following line in oauth2_client.py in the adal library, I could access my resource.
Changed
return urlparse('{}?{}'.format(self._token_endpoint, urlencode(parameters)))
in the method _create_token_url, to
return urlparse(self._token_endpoint)
We are working on a pull request to patch the library in github.
For the current release of Azure Python SDK, it support authentication with a service principal. It does not support authentication using an ADAL library yet. Maybe it will in future releases.
See https://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagement.html#authentication for details.
See also Azure Active Directory Authentication Libraries for the platforms ADAL is available on.
#Derek,
Could you set your Issue URL on Azure Portal? If I set the wrong Issue URL, I could get the same error with you. It seems that your code is right.
Base on my experience, you need add your application into Azure AD and get a client ID.(I am sure you have done this.) And then you can get the tenant ID and input into Issue URL textbox on Azure portal.
NOTE:
On old portal(manage.windowsazure.com),in the bottom command bar, click View Endpoints, and then copy the Federation Metadata Document URL and download that document or navigate to it in a browser.
Within the root EntityDescriptor element, there should be an entityID attribute of the form https://sts.windows.net/ followed by a GUID specific to your tenant (called a "tenant ID"). Copy this value - it will serve as your Issuer URL. You will configure your application to use this later.
My demo is as following:
import adal
import requests
TenantURL='https://login.microsoftonline.com/*******'
context = adal.AuthenticationContext(TenantURL)
RESOURCE = 'http://wi****.azurewebsites.net'
ClientID='****'
ClientSect='7****'
token_response = context.acquire_token_with_client_credentials(
RESOURCE,
ClientID,
ClientSect
)
access_token = token_response.get('accessToken')
print(access_token)
id_token = "Bearer {0}".format(access_token)
response = requests.get(RESOURCE, headers={"Authorization": id_token})
print(response)
Please try to modified it. Any updates, please let me know.
I am having trouble generating a refresh token using Python for the AdWords API & need some help. Here is the situation:
I have a client on AdWords that I want to pull reports for through the AdWords API (we have a developer token now for this). Let's say that, in AdWords, the clients account is 521-314-0974 (making this up). Here is where I am confused:
Below is the following code snippet needed to generate a refresh token that I am trying to get working:
"""Generates a refresh token for use with AdWords."""
__author__ = 'Nathaniel Payne'
import sys
import urllib2
from oauthlib import oauth2
# Your OAuth 2.0 Client ID and Secret. If you do not have an ID and Secret yet,
# please go to https://console.developers.google.com and create a set.
CLIENT_ID = 'INSERT_CLIENT_ID_HERE'
CLIENT_SECRET = 'INSERT_CLIENT_SECRET_HERE'
# You may optionally provide an HTTPS proxy.
HTTPS_PROXY = None
# The AdWords API OAuth 2.0 scope.
SCOPE = u'https://adwords.google.com/api/adwords'
# This callback URL will allow you to copy the token from the success screen.
CALLBACK_URL = 'urn:ietf:wg:oauth:2.0:oob'
# The HTTP headers needed on OAuth 2.0 refresh requests.
OAUTH2_REFRESH_HEADERS = {'content-type':
'application/x-www-form-urlencoded'}
# The web address for generating new OAuth 2.0 credentials at Google.
GOOGLE_OAUTH2_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth'
GOOGLE_OAUTH2_GEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
def main():
oauthlib_client = oauth2.WebApplicationClient(CLIENT_ID)
authorize_url = oauthlib_client.prepare_request_uri(
GOOGLE_OAUTH2_AUTH_ENDPOINT, redirect_uri=CALLBACK_URL, scope=SCOPE)
print ('Log in to your AdWords account and open the following URL: \n%s\n' %
authorize_url)
print 'After approving the token enter the verification code (if specified).'
code = raw_input('Code: ').strip()
post_body = oauthlib_client.prepare_request_body(
client_secret=CLIENT_SECRET, code=code, redirect_uri=CALLBACK_URL)
if sys.version_info[0] == 3:
post_body = bytes(post_body, 'utf8')
request = urllib2.Request(GOOGLE_OAUTH2_GEN_ENDPOINT, post_body,
OAUTH2_REFRESH_HEADERS)
if HTTPS_PROXY:
request.set_proxy(HTTPS_PROXY, 'https')
raw_response = urllib2.urlopen(request).read().decode()
oauth2_credentials = oauthlib_client.parse_request_body_response(raw_response)
print ('Your access token is %s and your refresh token is %s'
% (oauth2_credentials['access_token'],
oauth2_credentials['refresh_token']))
print ('You can cache these credentials into a yaml file with the '
'following keys:\nadwords:\n client_id: %s\n client_secret: %s\n'
' refresh_token: %s\n'
% (CLIENT_ID, CLIENT_SECRET, oauth2_credentials['refresh_token']))
if __name__ == '__main__':
main()
Questions:
1) Do I need to have a special project set-up for every AdWords customer in the console.developers.google.com, in order to pull from the AdWords Reporting API? Or, can I simply provide the client secret and ID for a generic account in the console?
2) Following from this, can someone please confirm what should go in place of the client_ID & Client_Secret in order to make the Python code block below work. What I mean is, I was using the client ID and client secret from https://console.developers.google.com ... for the analytics account that we have billing set-up on (and which I have used for BigQuery API access previously). Is that correct? I am not seeing clearly how this will be linked to the AdWords account for this client.
2) In the consent screen, I put my own e-mail, since I am owner of the project,. That said, when I run the code, I get the link to the URL that I need to run to generate the code. That said, when I sun this snippet:
print ('Log in to your AdWords account and open the following URL: \n%s\n' %
authorize_url)
print 'After approving the token enter the verification code (if specified).'
code = raw_input('Code: ').strip()
I get an error. This is the message that I get in error:
Error: redirect_uri_mismatch
The redirect URI in the request: urn:ietf:wg:oauth:2.0:oob did not match a registered redirect URI
Learn more
Request Details
cookie_policy_enforce=false
scope=https://adwords.google.com/api/adwords
response_type=code
access_type=online
redirect_uri=urn:ietf:wg:oauth:2.0:oob
display=page
client_id=XXXXXXXXX.apps.googleusercontent.com
I am puzzled here. Some folks suggested changing the e-mail address in the consent screen (which I did ... but was unsuccessful). Again, my simple goal is to be able to pull one report from tis clients through the AdWords API (which I will expand once I get there). Any help would be appreciated. Cheers.
After some work, I was able to successfully navigate through this issue. Here are the detailed steps that I took to get to the point where I could successfully pull data through the API. In my situation, I manage an AdWords MCC with multiple accounts. Thus, I went back to the beginning of many of the help manuals and did the following:
Create a new project called AdWords-API-XXXX.
In the credentials screen on the console, I created a new "Client ID for native application". This allowed me to generate my CLIENT_ID and the CLIENT_SECRET that I needed. Critically, it also generated a re-direct URI which was the source of my problem.
I took both of these values, added them to the main script, and ran the generate_refresh_token.py script. This allowed me to generate a working refresh token. I had to be signed into my AdWords account MCC, in order to make sure that OAuth2 provided me the ability to access all potential AdWord clientsinside my MCC. I got an authentication screen generated by URL for this process which asked me to confirm that permission was being granted for AdWords access.
Following this, I created a new googleads.yaml script and placed this in my c:\gsutil directory. This is the code in most Python programs where the program looks for the file googleads.yaml:
adwords_client = adwords.AdWordsClient.LoadFromStorage()
Once this was done, I was able to successfully run the script from my command line to generate the final output. The script was:
python download_criteria_report.py
Note of course that I have changed my path variable previously in order to run Python 2.7 from the command line. This script was run inside the directory of the download_criteria_report.py file. This script ran successfully and enabled me to pull data from the AdWords API for one of my test clients.
The next challenge will be working with the returned output from the API and putting it into a format that I can quickly use for analysis & storage.